aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-06-23 06:26:22 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-06-23 06:26:22 -0400
commit3357d4c75f1fb67e7304998c4ad4e9a9fed66fa4 (patch)
treeceba46966a5a1112a05d257d8ecb25ae5eee95e0 /fs
parent364f6c717deef4a3ac4982e670fa9846b43cd060 (diff)
parentee98689be1b054897ff17655008c3048fe88be94 (diff)
Automatic merge with /usr/src/ntfs-2.6.git.
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig85
-rw-r--r--fs/Makefile1
-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/buffer.c2
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c34
-rw-r--r--fs/coda/psdev.c18
-rw-r--r--fs/debugfs/file.c67
-rw-r--r--fs/exec.c16
-rw-r--r--fs/hugetlbfs/inode.c3
-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/jfs/acl.c6
-rw-r--r--fs/jfs/file.c9
-rw-r--r--fs/jfs/inode.c11
-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.c14
-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.c40
-rw-r--r--fs/jfs/jfs_txnmgr.h52
-rw-r--r--fs/jfs/namei.c28
-rw-r--r--fs/jfs/super.c37
-rw-r--r--fs/jfs/symlink.c3
-rw-r--r--fs/jfs/xattr.c6
-rw-r--r--fs/libfs.c100
-rw-r--r--fs/lockd/clntlock.c113
-rw-r--r--fs/lockd/clntproc.c40
-rw-r--r--fs/lockd/host.c8
-rw-r--r--fs/lockd/mon.c7
-rw-r--r--fs/locks.c6
-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.c160
-rw-r--r--fs/nfs/direct.c2
-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/Makefile2
-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/nfs4callback.c4
-rw-r--r--fs/nfsd/nfsproc.c1
-rw-r--r--fs/nfsd/nfssvc.c28
-rw-r--r--fs/nfsd/nfsxdr.c11
-rw-r--r--fs/nfsd/vfs.c107
-rw-r--r--fs/proc/proc_misc.c14
-rw-r--r--fs/super.c1
-rw-r--r--fs/sysfs/bin.c4
-rw-r--r--fs/sysfs/dir.c26
-rw-r--r--fs/sysfs/file.c6
-rw-r--r--fs/sysfs/inode.c102
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/symlink.c8
-rw-r--r--fs/sysfs/sysfs.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c153
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c27
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c11
-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.c12
-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.c65
-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
168 files changed, 5449 insertions, 2644 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 6a4ad4bb7a54..a7c0cc3203cb 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -741,56 +741,6 @@ config SYSFS
741 741
742 Designers of embedded systems may wish to say N here to conserve space. 742 Designers of embedded systems may wish to say N here to conserve space.
743 743
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 744config DEVPTS_FS_XATTR
795 bool "/dev/pts Extended Attributes" 745 bool "/dev/pts Extended Attributes"
796 depends on UNIX98_PTYS 746 depends on UNIX98_PTYS
@@ -1318,6 +1268,7 @@ config NFS_FS
1318 depends on INET 1268 depends on INET
1319 select LOCKD 1269 select LOCKD
1320 select SUNRPC 1270 select SUNRPC
1271 select NFS_ACL_SUPPORT if NFS_V3_ACL
1321 help 1272 help
1322 If you are connected to some other (usually local) Unix computer 1273 If you are connected to some other (usually local) Unix computer
1323 (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing 1274 (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
@@ -1360,6 +1311,16 @@ config NFS_V3
1360 1311
1361 If unsure, say Y. 1312 If unsure, say Y.
1362 1313
1314config NFS_V3_ACL
1315 bool "Provide client support for the NFSv3 ACL protocol extension"
1316 depends on NFS_V3
1317 help
1318 Implement the NFSv3 ACL protocol extension for manipulating POSIX
1319 Access Control Lists. The server should also be compiled with
1320 the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option.
1321
1322 If unsure, say N.
1323
1363config NFS_V4 1324config NFS_V4
1364 bool "Provide NFSv4 client support (EXPERIMENTAL)" 1325 bool "Provide NFSv4 client support (EXPERIMENTAL)"
1365 depends on NFS_FS && EXPERIMENTAL 1326 depends on NFS_FS && EXPERIMENTAL
@@ -1403,6 +1364,7 @@ config NFSD
1403 select LOCKD 1364 select LOCKD
1404 select SUNRPC 1365 select SUNRPC
1405 select EXPORTFS 1366 select EXPORTFS
1367 select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL
1406 help 1368 help
1407 If you want your Linux box to act as an NFS *server*, so that other 1369 If you want your Linux box to act as an NFS *server*, so that other
1408 computers on your local network which support NFS can access certain 1370 computers on your local network which support NFS can access certain
@@ -1426,6 +1388,10 @@ config NFSD
1426 To compile the NFS server support as a module, choose M here: the 1388 To compile the NFS server support as a module, choose M here: the
1427 module will be called nfsd. If unsure, say N. 1389 module will be called nfsd. If unsure, say N.
1428 1390
1391config NFSD_V2_ACL
1392 bool
1393 depends on NFSD
1394
1429config NFSD_V3 1395config NFSD_V3
1430 bool "Provide NFSv3 server support" 1396 bool "Provide NFSv3 server support"
1431 depends on NFSD 1397 depends on NFSD
@@ -1433,6 +1399,16 @@ config NFSD_V3
1433 If you would like to include the NFSv3 server as well as the NFSv2 1399 If you would like to include the NFSv3 server as well as the NFSv2
1434 server, say Y here. If unsure, say Y. 1400 server, say Y here. If unsure, say Y.
1435 1401
1402config NFSD_V3_ACL
1403 bool "Provide server support for the NFSv3 ACL protocol extension"
1404 depends on NFSD_V3
1405 select NFSD_V2_ACL
1406 help
1407 Implement the NFSv3 ACL protocol extension for manipulating POSIX
1408 Access Control Lists on exported file systems. NFS clients should
1409 be compiled with the NFSv3 ACL protocol extension; see the
1410 CONFIG_NFS_V3_ACL option. If unsure, say N.
1411
1436config NFSD_V4 1412config NFSD_V4
1437 bool "Provide NFSv4 server support (EXPERIMENTAL)" 1413 bool "Provide NFSv4 server support (EXPERIMENTAL)"
1438 depends on NFSD_V3 && EXPERIMENTAL 1414 depends on NFSD_V3 && EXPERIMENTAL
@@ -1477,6 +1453,15 @@ config LOCKD_V4
1477config EXPORTFS 1453config EXPORTFS
1478 tristate 1454 tristate
1479 1455
1456config NFS_ACL_SUPPORT
1457 tristate
1458 select FS_POSIX_ACL
1459
1460config NFS_COMMON
1461 bool
1462 depends on NFSD || NFS_FS
1463 default y
1464
1480config SUNRPC 1465config SUNRPC
1481 tristate 1466 tristate
1482 1467
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/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/buffer.c b/fs/buffer.c
index 7e9e409feaa7..0befa724ab98 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -528,7 +528,7 @@ static void free_more_memory(void)
528 for_each_pgdat(pgdat) { 528 for_each_pgdat(pgdat) {
529 zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones; 529 zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
530 if (*zones) 530 if (*zones)
531 try_to_free_pages(zones, GFP_NOFS, 0); 531 try_to_free_pages(zones, GFP_NOFS);
532 } 532 }
533} 533}
534 534
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/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/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 b8b78cbb34c9..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,7 @@ 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 if(direntry->d_inode) 425 if (direntry->d_inode)
426 direntry->d_inode->i_nlink--; 426 direntry->d_inode->i_nlink--;
427 } else if (rc == -ENOENT) { 427 } else if (rc == -ENOENT) {
428 d_drop(direntry); 428 d_drop(direntry);
@@ -441,7 +441,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
441 cifs_sb->mnt_cifs_flags & 441 cifs_sb->mnt_cifs_flags &
442 CIFS_MOUNT_MAP_SPECIAL_CHR); 442 CIFS_MOUNT_MAP_SPECIAL_CHR);
443 CIFSSMBClose(xid, pTcon, netfid); 443 CIFSSMBClose(xid, pTcon, netfid);
444 if(direntry->d_inode) 444 if (direntry->d_inode)
445 direntry->d_inode->i_nlink--; 445 direntry->d_inode->i_nlink--;
446 } 446 }
447 } else if (rc == -EACCES) { 447 } else if (rc == -EACCES) {
@@ -496,7 +496,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
496 cifs_sb->mnt_cifs_flags & 496 cifs_sb->mnt_cifs_flags &
497 CIFS_MOUNT_MAP_SPECIAL_CHR); 497 CIFS_MOUNT_MAP_SPECIAL_CHR);
498 if (!rc) { 498 if (!rc) {
499 if(direntry->d_inode) 499 if (direntry->d_inode)
500 direntry->d_inode->i_nlink--; 500 direntry->d_inode->i_nlink--;
501 } else if (rc == -ETXTBSY) { 501 } else if (rc == -ETXTBSY) {
502 int oplock = FALSE; 502 int oplock = FALSE;
@@ -517,14 +517,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
517 cifs_sb->mnt_cifs_flags & 517 cifs_sb->mnt_cifs_flags &
518 CIFS_MOUNT_MAP_SPECIAL_CHR); 518 CIFS_MOUNT_MAP_SPECIAL_CHR);
519 CIFSSMBClose(xid, pTcon, netfid); 519 CIFSSMBClose(xid, pTcon, netfid);
520 if(direntry->d_inode) 520 if (direntry->d_inode)
521 direntry->d_inode->i_nlink--; 521 direntry->d_inode->i_nlink--;
522 } 522 }
523 /* BB if rc = -ETXTBUSY goto the rename logic BB */ 523 /* BB if rc = -ETXTBUSY goto the rename logic BB */
524 } 524 }
525 } 525 }
526 } 526 }
527 if(direntry->d_inode) { 527 if (direntry->d_inode) {
528 cifsInode = CIFS_I(direntry->d_inode); 528 cifsInode = CIFS_I(direntry->d_inode);
529 cifsInode->time = 0; /* will force revalidate to get info 529 cifsInode->time = 0; /* will force revalidate to get info
530 when needed */ 530 when needed */
@@ -582,7 +582,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
582 if (direntry->d_inode) 582 if (direntry->d_inode)
583 direntry->d_inode->i_nlink = 2; 583 direntry->d_inode->i_nlink = 2;
584 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) 584 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
585 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 585 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
586 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 586 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
587 mode, 587 mode,
588 (__u64)current->euid, 588 (__u64)current->euid,
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/exec.c b/fs/exec.c
index e56ee2437025..3a4b35a14c0d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -649,6 +649,7 @@ static inline int de_thread(struct task_struct *tsk)
649 } 649 }
650 sig->group_exit_task = NULL; 650 sig->group_exit_task = NULL;
651 sig->notify_count = 0; 651 sig->notify_count = 0;
652 sig->real_timer.data = (unsigned long)current;
652 spin_unlock_irq(lock); 653 spin_unlock_irq(lock);
653 654
654 /* 655 /*
@@ -675,10 +676,8 @@ static inline int de_thread(struct task_struct *tsk)
675 proc_dentry2 = proc_pid_unhash(leader); 676 proc_dentry2 = proc_pid_unhash(leader);
676 write_lock_irq(&tasklist_lock); 677 write_lock_irq(&tasklist_lock);
677 678
678 if (leader->tgid != current->tgid) 679 BUG_ON(leader->tgid != current->tgid);
679 BUG(); 680 BUG_ON(current->pid == current->tgid);
680 if (current->pid == current->tgid)
681 BUG();
682 /* 681 /*
683 * An exec() starts a new thread group with the 682 * An exec() starts a new thread group with the
684 * TGID of the previous thread group. Rehash the 683 * TGID of the previous thread group. Rehash the
@@ -726,8 +725,7 @@ static inline int de_thread(struct task_struct *tsk)
726 proc_pid_flush(proc_dentry1); 725 proc_pid_flush(proc_dentry1);
727 proc_pid_flush(proc_dentry2); 726 proc_pid_flush(proc_dentry2);
728 727
729 if (exit_state != EXIT_ZOMBIE) 728 BUG_ON(exit_state != EXIT_ZOMBIE);
730 BUG();
731 release_task(leader); 729 release_task(leader);
732 } 730 }
733 731
@@ -772,10 +770,8 @@ no_thread_group:
772 kmem_cache_free(sighand_cachep, oldsighand); 770 kmem_cache_free(sighand_cachep, oldsighand);
773 } 771 }
774 772
775 if (!thread_group_empty(current)) 773 BUG_ON(!thread_group_empty(current));
776 BUG(); 774 BUG_ON(!thread_group_leader(current));
777 if (!thread_group_leader(current))
778 BUG();
779 return 0; 775 return 0;
780} 776}
781 777
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/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/jfs/acl.c b/fs/jfs/acl.c
index 8d2a9ab981d4..30a2bf9eeda5 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -70,8 +70,7 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
70 if (!IS_ERR(acl)) 70 if (!IS_ERR(acl))
71 *p_acl = posix_acl_dup(acl); 71 *p_acl = posix_acl_dup(acl);
72 } 72 }
73 if (value) 73 kfree(value);
74 kfree(value);
75 return acl; 74 return acl;
76} 75}
77 76
@@ -112,8 +111,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
112 } 111 }
113 rc = __jfs_setxattr(inode, ea_name, value, size, 0); 112 rc = __jfs_setxattr(inode, ea_name, value, size, 0);
114out: 113out:
115 if (value) 114 kfree(value);
116 kfree(value);
117 115
118 if (!rc) { 116 if (!rc) {
119 if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) 117 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_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..7c8387ed4192 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}
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..8cbaaff1d5fa 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 *
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..810a3653d8b3 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -28,6 +28,7 @@
28 28
29#include "jfs_incore.h" 29#include "jfs_incore.h"
30#include "jfs_filsys.h" 30#include "jfs_filsys.h"
31#include "jfs_inode.h"
31#include "jfs_metapage.h" 32#include "jfs_metapage.h"
32#include "jfs_superblock.h" 33#include "jfs_superblock.h"
33#include "jfs_dmap.h" 34#include "jfs_dmap.h"
@@ -62,37 +63,6 @@ module_param(jfsloglevel, int, 0644);
62MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); 63MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
63#endif 64#endif
64 65
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) 66static void jfs_handle_error(struct super_block *sb)
97{ 67{
98 struct jfs_sb_info *sbi = JFS_SBI(sb); 68 struct jfs_sb_info *sbi = JFS_SBI(sb);
@@ -593,11 +563,6 @@ static struct file_system_type jfs_fs_type = {
593 .fs_flags = FS_REQUIRES_DEV, 563 .fs_flags = FS_REQUIRES_DEV,
594}; 564};
595 565
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) 566static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
602{ 567{
603 struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; 568 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..6016373701a3 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -946,8 +946,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
946 out: 946 out:
947 up_write(&JFS_IP(inode)->xattr_sem); 947 up_write(&JFS_IP(inode)->xattr_sem);
948 948
949 if (os2name) 949 kfree(os2name);
950 kfree(os2name);
951 950
952 return rc; 951 return rc;
953} 952}
@@ -1042,8 +1041,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
1042 out: 1041 out:
1043 up_read(&JFS_IP(inode)->xattr_sem); 1042 up_read(&JFS_IP(inode)->xattr_sem);
1044 1043
1045 if (os2name) 1044 kfree(os2name);
1046 kfree(os2name);
1047 1045
1048 return size; 1046 return size;
1049} 1047}
diff --git a/fs/libfs.c b/fs/libfs.c
index f90b29595927..5025563e7379 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -519,6 +519,102 @@ int simple_transaction_release(struct inode *inode, struct file *file)
519 return 0; 519 return 0;
520} 520}
521 521
522/* Simple attribute files */
523
524struct simple_attr {
525 u64 (*get)(void *);
526 void (*set)(void *, u64);
527 char get_buf[24]; /* enough to store a u64 and "\n\0" */
528 char set_buf[24];
529 void *data;
530 const char *fmt; /* format for read operation */
531 struct semaphore sem; /* protects access to these buffers */
532};
533
534/* simple_attr_open is called by an actual attribute open file operation
535 * to set the attribute specific access operations. */
536int simple_attr_open(struct inode *inode, struct file *file,
537 u64 (*get)(void *), void (*set)(void *, u64),
538 const char *fmt)
539{
540 struct simple_attr *attr;
541
542 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
543 if (!attr)
544 return -ENOMEM;
545
546 attr->get = get;
547 attr->set = set;
548 attr->data = inode->u.generic_ip;
549 attr->fmt = fmt;
550 init_MUTEX(&attr->sem);
551
552 file->private_data = attr;
553
554 return nonseekable_open(inode, file);
555}
556
557int simple_attr_close(struct inode *inode, struct file *file)
558{
559 kfree(file->private_data);
560 return 0;
561}
562
563/* read from the buffer that is filled with the get function */
564ssize_t simple_attr_read(struct file *file, char __user *buf,
565 size_t len, loff_t *ppos)
566{
567 struct simple_attr *attr;
568 size_t size;
569 ssize_t ret;
570
571 attr = file->private_data;
572
573 if (!attr->get)
574 return -EACCES;
575
576 down(&attr->sem);
577 if (*ppos) /* continued read */
578 size = strlen(attr->get_buf);
579 else /* first read */
580 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
581 attr->fmt,
582 (unsigned long long)attr->get(attr->data));
583
584 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
585 up(&attr->sem);
586 return ret;
587}
588
589/* interpret the buffer as a number to call the set function with */
590ssize_t simple_attr_write(struct file *file, const char __user *buf,
591 size_t len, loff_t *ppos)
592{
593 struct simple_attr *attr;
594 u64 val;
595 size_t size;
596 ssize_t ret;
597
598 attr = file->private_data;
599
600 if (!attr->set)
601 return -EACCES;
602
603 down(&attr->sem);
604 ret = -EFAULT;
605 size = min(sizeof(attr->set_buf) - 1, len);
606 if (copy_from_user(attr->set_buf, buf, size))
607 goto out;
608
609 ret = len; /* claim we got the whole input */
610 attr->set_buf[size] = '\0';
611 val = simple_strtol(attr->set_buf, NULL, 0);
612 attr->set(attr->data, val);
613out:
614 up(&attr->sem);
615 return ret;
616}
617
522EXPORT_SYMBOL(dcache_dir_close); 618EXPORT_SYMBOL(dcache_dir_close);
523EXPORT_SYMBOL(dcache_dir_lseek); 619EXPORT_SYMBOL(dcache_dir_lseek);
524EXPORT_SYMBOL(dcache_dir_open); 620EXPORT_SYMBOL(dcache_dir_open);
@@ -547,3 +643,7 @@ EXPORT_SYMBOL(simple_read_from_buffer);
547EXPORT_SYMBOL(simple_transaction_get); 643EXPORT_SYMBOL(simple_transaction_get);
548EXPORT_SYMBOL(simple_transaction_read); 644EXPORT_SYMBOL(simple_transaction_read);
549EXPORT_SYMBOL(simple_transaction_release); 645EXPORT_SYMBOL(simple_transaction_release);
646EXPORT_SYMBOL_GPL(simple_attr_open);
647EXPORT_SYMBOL_GPL(simple_attr_close);
648EXPORT_SYMBOL_GPL(simple_attr_read);
649EXPORT_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..fd77ed1d710d 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 *);
@@ -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/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/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 ff6155f5e8d9..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.
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 68df803f27ca..d6a30c844de3 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
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..9f043f44c92f 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
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/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 1a55dfcb74bc..634465e9cfc6 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -430,7 +430,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
430 clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); 430 clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
431 if (IS_ERR(clnt)) { 431 if (IS_ERR(clnt)) {
432 dprintk("NFSD: couldn't create callback client\n"); 432 dprintk("NFSD: couldn't create callback client\n");
433 goto out_xprt; 433 goto out_err;
434 } 434 }
435 clnt->cl_intr = 0; 435 clnt->cl_intr = 0;
436 clnt->cl_softrtry = 1; 436 clnt->cl_softrtry = 1;
@@ -465,8 +465,6 @@ out_rpciod:
465out_clnt: 465out_clnt:
466 rpc_shutdown_client(clnt); 466 rpc_shutdown_client(clnt);
467 goto out_err; 467 goto out_err;
468out_xprt:
469 xprt_destroy(xprt);
470out_err: 468out_err:
471 dprintk("NFSD: warning: no callback path to client %.*s\n", 469 dprintk("NFSD: warning: no callback path to client %.*s\n",
472 (int)clp->cl_name.len, clp->cl_name.data); 470 (int)clp->cl_name.len, clp->cl_name.data);
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..904df604e86b 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
@@ -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..ae3940dc85cc 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -46,8 +46,9 @@
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_acl.h>
53#include <linux/xattr.h> 54#include <linux/xattr.h>
@@ -1857,3 +1858,107 @@ nfsd_racache_init(int cache_size)
1857 nfsdstats.ra_size = cache_size; 1858 nfsdstats.ra_size = cache_size;
1858 return 0; 1859 return 0;
1859} 1860}
1861
1862#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
1863struct posix_acl *
1864nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1865{
1866 struct inode *inode = fhp->fh_dentry->d_inode;
1867 char *name;
1868 void *value = NULL;
1869 ssize_t size;
1870 struct posix_acl *acl;
1871
1872 if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
1873 return ERR_PTR(-EOPNOTSUPP);
1874 switch(type) {
1875 case ACL_TYPE_ACCESS:
1876 name = XATTR_NAME_ACL_ACCESS;
1877 break;
1878 case ACL_TYPE_DEFAULT:
1879 name = XATTR_NAME_ACL_DEFAULT;
1880 break;
1881 default:
1882 return ERR_PTR(-EOPNOTSUPP);
1883 }
1884
1885 size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
1886
1887 if (size < 0) {
1888 acl = ERR_PTR(size);
1889 goto getout;
1890 } else if (size > 0) {
1891 value = kmalloc(size, GFP_KERNEL);
1892 if (!value) {
1893 acl = ERR_PTR(-ENOMEM);
1894 goto getout;
1895 }
1896 size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1897 if (size < 0) {
1898 acl = ERR_PTR(size);
1899 goto getout;
1900 }
1901 }
1902 acl = posix_acl_from_xattr(value, size);
1903
1904getout:
1905 kfree(value);
1906 return acl;
1907}
1908
1909int
1910nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1911{
1912 struct inode *inode = fhp->fh_dentry->d_inode;
1913 char *name;
1914 void *value = NULL;
1915 size_t size;
1916 int error;
1917
1918 if (!IS_POSIXACL(inode) || !inode->i_op ||
1919 !inode->i_op->setxattr || !inode->i_op->removexattr)
1920 return -EOPNOTSUPP;
1921 switch(type) {
1922 case ACL_TYPE_ACCESS:
1923 name = XATTR_NAME_ACL_ACCESS;
1924 break;
1925 case ACL_TYPE_DEFAULT:
1926 name = XATTR_NAME_ACL_DEFAULT;
1927 break;
1928 default:
1929 return -EOPNOTSUPP;
1930 }
1931
1932 if (acl && acl->a_count) {
1933 size = xattr_acl_size(acl->a_count);
1934 value = kmalloc(size, GFP_KERNEL);
1935 if (!value)
1936 return -ENOMEM;
1937 size = posix_acl_to_xattr(acl, value, size);
1938 if (size < 0) {
1939 error = size;
1940 goto getout;
1941 }
1942 } else
1943 size = 0;
1944
1945 if (!fhp->fh_locked)
1946 fh_lock(fhp); /* unlocking is done automatically */
1947 if (size)
1948 error = inode->i_op->setxattr(fhp->fh_dentry, name,
1949 value, size, 0);
1950 else {
1951 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1952 error = 0;
1953 else {
1954 error = inode->i_op->removexattr(fhp->fh_dentry, name);
1955 if (error == -ENODATA)
1956 error = 0;
1957 }
1958 }
1959
1960getout:
1961 kfree(value);
1962 return error;
1963}
1964#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index a60a3b3d8a7b..63a9fbf1ac51 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -219,6 +219,19 @@ static struct file_operations fragmentation_file_operations = {
219 .release = seq_release, 219 .release = seq_release,
220}; 220};
221 221
222extern struct seq_operations zoneinfo_op;
223static int zoneinfo_open(struct inode *inode, struct file *file)
224{
225 return seq_open(file, &zoneinfo_op);
226}
227
228static struct file_operations proc_zoneinfo_file_operations = {
229 .open = zoneinfo_open,
230 .read = seq_read,
231 .llseek = seq_lseek,
232 .release = seq_release,
233};
234
222static int version_read_proc(char *page, char **start, off_t off, 235static int version_read_proc(char *page, char **start, off_t off,
223 int count, int *eof, void *data) 236 int count, int *eof, void *data)
224{ 237{
@@ -589,6 +602,7 @@ void __init proc_misc_init(void)
589 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); 602 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
590 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); 603 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
591 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); 604 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
605 create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
592 create_seq_entry("diskstats", 0, &proc_diskstats_operations); 606 create_seq_entry("diskstats", 0, &proc_diskstats_operations);
593#ifdef CONFIG_MODULES 607#ifdef CONFIG_MODULES
594 create_seq_entry("modules", 0, &proc_modules_operations); 608 create_seq_entry("modules", 0, &proc_modules_operations);
diff --git a/fs/super.c b/fs/super.c
index 3a1b8ca04ba6..573bcc81bb82 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -835,6 +835,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
835 mnt->mnt_parent = mnt; 835 mnt->mnt_parent = mnt;
836 mnt->mnt_namespace = current->namespace; 836 mnt->mnt_namespace = current->namespace;
837 up_write(&sb->s_umount); 837 up_write(&sb->s_umount);
838 free_secdata(secdata);
838 put_filesystem(type); 839 put_filesystem(type);
839 return mnt; 840 return mnt;
840out_sb: 841out_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..37d7a6875d86 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -101,18 +101,19 @@ static int create_dir(struct kobject * k, struct dentry * p,
101 down(&p->d_inode->i_sem); 101 down(&p->d_inode->i_sem);
102 *d = sysfs_get_dentry(p,n); 102 *d = sysfs_get_dentry(p,n);
103 if (!IS_ERR(*d)) { 103 if (!IS_ERR(*d)) {
104 error = sysfs_create(*d, mode, init_dir); 104 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
105 if (!error) { 105 if (!error) {
106 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, 106 error = sysfs_create(*d, mode, init_dir);
107 SYSFS_DIR);
108 if (!error) { 107 if (!error) {
109 p->d_inode->i_nlink++; 108 p->d_inode->i_nlink++;
110 (*d)->d_op = &sysfs_dentry_ops; 109 (*d)->d_op = &sysfs_dentry_ops;
111 d_rehash(*d); 110 d_rehash(*d);
112 } 111 }
113 } 112 }
114 if (error && (error != -EEXIST)) 113 if (error && (error != -EEXIST)) {
114 sysfs_put((*d)->d_fsdata);
115 d_drop(*d); 115 d_drop(*d);
116 }
116 dput(*d); 117 dput(*d);
117 } else 118 } else
118 error = PTR_ERR(*d); 119 error = PTR_ERR(*d);
@@ -171,17 +172,19 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
171 init = init_file; 172 init = init_file;
172 } 173 }
173 174
175 dentry->d_fsdata = sysfs_get(sd);
176 sd->s_dentry = dentry;
174 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); 177 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
175 if (error) 178 if (error) {
179 sysfs_put(sd);
176 return error; 180 return error;
181 }
177 182
178 if (bin_attr) { 183 if (bin_attr) {
179 dentry->d_inode->i_size = bin_attr->size; 184 dentry->d_inode->i_size = bin_attr->size;
180 dentry->d_inode->i_fop = &bin_fops; 185 dentry->d_inode->i_fop = &bin_fops;
181 } 186 }
182 dentry->d_op = &sysfs_dentry_ops; 187 dentry->d_op = &sysfs_dentry_ops;
183 dentry->d_fsdata = sysfs_get(sd);
184 sd->s_dentry = dentry;
185 d_rehash(dentry); 188 d_rehash(dentry);
186 189
187 return 0; 190 return 0;
@@ -191,13 +194,15 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
191{ 194{
192 int err = 0; 195 int err = 0;
193 196
197 dentry->d_fsdata = sysfs_get(sd);
198 sd->s_dentry = dentry;
194 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); 199 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
195 if (!err) { 200 if (!err) {
196 dentry->d_op = &sysfs_dentry_ops; 201 dentry->d_op = &sysfs_dentry_ops;
197 dentry->d_fsdata = sysfs_get(sd);
198 sd->s_dentry = dentry;
199 d_rehash(dentry); 202 d_rehash(dentry);
200 } 203 } else
204 sysfs_put(sd);
205
201 return err; 206 return err;
202} 207}
203 208
@@ -228,6 +233,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
228 233
229struct inode_operations sysfs_dir_inode_operations = { 234struct inode_operations sysfs_dir_inode_operations = {
230 .lookup = sysfs_lookup, 235 .lookup = sysfs_lookup,
236 .setattr = sysfs_setattr,
231}; 237};
232 238
233static void remove_dir(struct dentry * d) 239static void remove_dir(struct dentry * d)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 364208071e17..849aac115460 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -23,7 +23,7 @@ subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
23{ 23{
24 struct subsystem * s = to_subsys(kobj); 24 struct subsystem * s = to_subsys(kobj);
25 struct subsys_attribute * sattr = to_sattr(attr); 25 struct subsys_attribute * sattr = to_sattr(attr);
26 ssize_t ret = 0; 26 ssize_t ret = -EIO;
27 27
28 if (sattr->show) 28 if (sattr->show)
29 ret = sattr->show(s,page); 29 ret = sattr->show(s,page);
@@ -36,7 +36,7 @@ subsys_attr_store(struct kobject * kobj, struct attribute * attr,
36{ 36{
37 struct subsystem * s = to_subsys(kobj); 37 struct subsystem * s = to_subsys(kobj);
38 struct subsys_attribute * sattr = to_sattr(attr); 38 struct subsys_attribute * sattr = to_sattr(attr);
39 ssize_t ret = 0; 39 ssize_t ret = -EIO;
40 40
41 if (sattr->store) 41 if (sattr->store)
42 ret = sattr->store(s,page,count); 42 ret = sattr->store(s,page,count);
@@ -182,7 +182,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
182 return -ENOMEM; 182 return -ENOMEM;
183 183
184 if (count >= PAGE_SIZE) 184 if (count >= PAGE_SIZE)
185 count = PAGE_SIZE - 1; 185 count = PAGE_SIZE;
186 error = copy_from_user(buffer->page,buf,count); 186 error = copy_from_user(buffer->page,buf,count);
187 buffer->needs_read_fill = 1; 187 buffer->needs_read_fill = 1;
188 return error ? -EFAULT : count; 188 return error ? -EFAULT : count;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2dfa8ee..565cac1d4200 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;
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..29da6f5f07c8 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,7 +2,7 @@
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 *,
@@ -17,6 +17,7 @@ extern void sysfs_remove_subdir(struct dentry *);
17 17
18extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); 18extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
19extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); 19extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
20extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
20 21
21extern struct rw_semaphore sysfs_rename_sem; 22extern struct rw_semaphore sysfs_rename_sem;
22extern struct super_block * sysfs_sb; 23extern struct super_block * sysfs_sb;
@@ -75,6 +76,7 @@ static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
75 kobject_put(sl->target_kobj); 76 kobject_put(sl->target_kobj);
76 kfree(sl); 77 kfree(sl);
77 } 78 }
79 kfree(sd->s_iattr);
78 kmem_cache_free(sysfs_dir_cachep, sd); 80 kmem_cache_free(sysfs_dir_cachep, sd);
79} 81}
80 82
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 997963e53622..c60e69431e11 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(current->flags & PF_FREEZE)) {
1784 force_sleep = 1; 1775 xfsbufd_force_sleep = 1;
1785 refrigerator(PF_FREEZE); 1776 refrigerator(PF_FREEZE);
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 24fa3b101b93..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 */
@@ -609,7 +622,15 @@ struct file_operations linvfs_dir_operations = {
609static struct vm_operations_struct linvfs_file_vm_ops = { 622static struct vm_operations_struct linvfs_file_vm_ops = {
610 .nopage = filemap_nopage, 623 .nopage = filemap_nopage,
611 .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,
612#ifdef HAVE_VMOP_MPROTECT 632#ifdef HAVE_VMOP_MPROTECT
613 .mprotect = linvfs_mprotect, 633 .mprotect = linvfs_mprotect,
614#endif 634#endif
615}; 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_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 455e2b2fb964..5fe9af38aa20 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -590,8 +590,10 @@ linvfs_sync_super(
590 int error; 590 int error;
591 int flags = SYNC_FSDATA; 591 int flags = SYNC_FSDATA;
592 592
593 if (wait) 593 if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
594 flags |= SYNC_WAIT; 594 flags = SYNC_QUIESCE;
595 else
596 flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
595 597
596 VFS_SYNC(vfsp, flags, NULL, error); 598 VFS_SYNC(vfsp, flags, NULL, error);
597 sb->s_dirt = 0; 599 sb->s_dirt = 0;
@@ -701,7 +703,8 @@ linvfs_getxquota(
701 struct vfs *vfsp = LINVFS_GET_VFS(sb); 703 struct vfs *vfsp = LINVFS_GET_VFS(sb);
702 int error, getmode; 704 int error, getmode;
703 705
704 getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA; 706 getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
707 ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
705 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); 708 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
706 return -error; 709 return -error;
707} 710}
@@ -716,7 +719,8 @@ linvfs_setxquota(
716 struct vfs *vfsp = LINVFS_GET_VFS(sb); 719 struct vfs *vfsp = LINVFS_GET_VFS(sb);
717 int error, setmode; 720 int error, setmode;
718 721
719 setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM; 722 setmode = (type == USRQUOTA) ? Q_XSETQLIM :
723 ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
720 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); 724 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
721 return -error; 725 return -error;
722} 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 469e1a7939d4..2edd6769e5d3 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -385,15 +385,15 @@ xfs_iomap_write_direct(
385 int nimaps, maps; 385 int nimaps, maps;
386 int error; 386 int error;
387 int bmapi_flag; 387 int bmapi_flag;
388 int quota_flag;
388 int rt; 389 int rt;
389 xfs_trans_t *tp; 390 xfs_trans_t *tp;
390 xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; 391 xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
391 xfs_bmap_free_t free_list; 392 xfs_bmap_free_t free_list;
392 int aeof; 393 int aeof;
393 xfs_filblks_t datablocks; 394 xfs_filblks_t datablocks, qblocks, resblks;
394 int committed; 395 int committed;
395 int numrtextents; 396 int numrtextents;
396 uint resblks;
397 397
398 /* 398 /*
399 * Make sure that the dquots are there. This doesn't hold 399 * Make sure that the dquots are there. This doesn't hold
@@ -419,7 +419,6 @@ xfs_iomap_write_direct(
419 xfs_fileoff_t map_last_fsb; 419 xfs_fileoff_t map_last_fsb;
420 420
421 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; 421 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
422
423 if (map_last_fsb < last_fsb) { 422 if (map_last_fsb < last_fsb) {
424 last_fsb = map_last_fsb; 423 last_fsb = map_last_fsb;
425 count_fsb = last_fsb - offset_fsb; 424 count_fsb = last_fsb - offset_fsb;
@@ -428,56 +427,47 @@ xfs_iomap_write_direct(
428 } 427 }
429 428
430 /* 429 /*
431 * determine if reserving space on 430 * Determine if reserving space on the data or realtime partition.
432 * the data or realtime partition.
433 */ 431 */
434 if ((rt = XFS_IS_REALTIME_INODE(ip))) { 432 if ((rt = XFS_IS_REALTIME_INODE(ip))) {
435 int sbrtextsize, iprtextsize; 433 xfs_extlen_t extsz;
436 434
437 sbrtextsize = mp->m_sb.sb_rextsize; 435 if (!(extsz = ip->i_d.di_extsize))
438 iprtextsize = 436 extsz = mp->m_sb.sb_rextsize;
439 ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; 437 numrtextents = qblocks = (count_fsb + extsz - 1);
440 numrtextents = (count_fsb + iprtextsize - 1); 438 do_div(numrtextents, mp->m_sb.sb_rextsize);
441 do_div(numrtextents, sbrtextsize); 439 quota_flag = XFS_QMOPT_RES_RTBLKS;
442 datablocks = 0; 440 datablocks = 0;
443 } else { 441 } else {
444 datablocks = count_fsb; 442 datablocks = qblocks = count_fsb;
443 quota_flag = XFS_QMOPT_RES_REGBLKS;
445 numrtextents = 0; 444 numrtextents = 0;
446 } 445 }
447 446
448 /* 447 /*
449 * allocate and setup the transaction 448 * Allocate and setup the transaction
450 */ 449 */
451 xfs_iunlock(ip, XFS_ILOCK_EXCL); 450 xfs_iunlock(ip, XFS_ILOCK_EXCL);
452 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 451 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
453
454 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); 452 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
455
456 error = xfs_trans_reserve(tp, resblks, 453 error = xfs_trans_reserve(tp, resblks,
457 XFS_WRITE_LOG_RES(mp), numrtextents, 454 XFS_WRITE_LOG_RES(mp), numrtextents,
458 XFS_TRANS_PERM_LOG_RES, 455 XFS_TRANS_PERM_LOG_RES,
459 XFS_WRITE_LOG_COUNT); 456 XFS_WRITE_LOG_COUNT);
460 457
461 /* 458 /*
462 * check for running out of space 459 * Check for running out of space, note: need lock to return
463 */ 460 */
464 if (error) 461 if (error)
465 /*
466 * Free the transaction structure.
467 */
468 xfs_trans_cancel(tp, 0); 462 xfs_trans_cancel(tp, 0);
469
470 xfs_ilock(ip, XFS_ILOCK_EXCL); 463 xfs_ilock(ip, XFS_ILOCK_EXCL);
471
472 if (error) 464 if (error)
473 goto error_out; /* Don't return in above if .. trans .., 465 goto error_out;
474 need lock to return */
475 466
476 if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { 467 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
477 error = (EDQUOT); 468 error = (EDQUOT);
478 goto error1; 469 goto error1;
479 } 470 }
480 nimaps = 1;
481 471
482 bmapi_flag = XFS_BMAPI_WRITE; 472 bmapi_flag = XFS_BMAPI_WRITE;
483 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 473 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -487,31 +477,29 @@ xfs_iomap_write_direct(
487 bmapi_flag |= XFS_BMAPI_PREALLOC; 477 bmapi_flag |= XFS_BMAPI_PREALLOC;
488 478
489 /* 479 /*
490 * issue the bmapi() call to allocate the blocks 480 * Issue the bmapi() call to allocate the blocks
491 */ 481 */
492 XFS_BMAP_INIT(&free_list, &firstfsb); 482 XFS_BMAP_INIT(&free_list, &firstfsb);
483 nimaps = 1;
493 imapp = &imap[0]; 484 imapp = &imap[0];
494 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, 485 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
495 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); 486 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
496 if (error) { 487 if (error)
497 goto error0; 488 goto error0;
498 }
499 489
500 /* 490 /*
501 * complete the transaction 491 * Complete the transaction
502 */ 492 */
503
504 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); 493 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
505 if (error) { 494 if (error)
506 goto error0; 495 goto error0;
507 }
508
509 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); 496 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
510 if (error) { 497 if (error)
511 goto error_out; 498 goto error_out;
512 }
513 499
514 /* 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 */
515 if (nimaps == 0) { 503 if (nimaps == 0) {
516 error = (ENOSPC); 504 error = (ENOSPC);
517 goto error_out; 505 goto error_out;
@@ -530,10 +518,11 @@ xfs_iomap_write_direct(
530 } 518 }
531 return 0; 519 return 0;
532 520
533 error0: /* Cancel bmap, unlock inode, and cancel trans */ 521error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
534 xfs_bmap_cancel(&free_list); 522 xfs_bmap_cancel(&free_list);
523 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
535 524
536 error1: /* Just cancel transaction */ 525error1: /* Just cancel transaction */
537 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);
538 *nmaps = 0; /* nothing set-up here */ 527 *nmaps = 0; /* nothing set-up here */
539 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