quota: move unmount handling into the filesystem

Currently the VFS calls into the quotactl interface for unmounting
filesystems.  This means filesystems with their own quota handling
can't easily distinguish between user-space originating quotaoff
and an unount.  Instead move the responsibily of the unmount handling
into the filesystem to be consistent with all other dquot handling.

Note that we do call dquot_disable a lot later now, e.g. after
a sync_filesystem.  But this is fine as the quota code does all its
writes via blockdev's mapping and that is synced even later.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 318ebc5..b9b77c3 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -119,6 +119,8 @@
 	int i;
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 
+	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	if (sb->s_dirt)
 		ext2_write_super(sb);
 
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9d5e582..b2f3715 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -410,6 +410,8 @@
 	struct ext3_super_block *es = sbi->s_es;
 	int i, err;
 
+	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	lock_kernel();
 
 	ext3_xattr_put_super(sb);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 08d3110..808aca3 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -645,6 +645,8 @@
 	struct ext4_super_block *es = sbi->s_es;
 	int i, err;
 
+	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	flush_workqueue(sbi->dio_unwritten_wq);
 	destroy_workqueue(sbi->dio_unwritten_wq);
 
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index b8a07d4..7d940a3 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -179,6 +179,8 @@
 
 	jfs_info("In jfs_put_super");
 
+	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	lock_kernel();
 
 	rc = jfs_umount(sb);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 5dad5a2..08879af 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -466,6 +466,8 @@
 	struct reiserfs_transaction_handle th;
 	th.t_trans_id = 0;
 
+	dquot_disable(s, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	reiserfs_write_lock(s);
 
 	if (s->s_dirt)
diff --git a/fs/super.c b/fs/super.c
index a38e6e9..05f62e5 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -160,7 +160,6 @@
 {
 	struct file_system_type *fs = s->s_type;
 	if (atomic_dec_and_test(&s->s_active)) {
-		vfs_dq_off(s, 0);
 		fs->kill_sb(s);
 		put_filesystem(fs);
 		put_super(s);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index b154c41..76a6156 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -2102,6 +2102,8 @@
 	int i;
 	struct udf_sb_info *sbi;
 
+	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	sbi = UDF_SB(sb);
 
 	lock_kernel();
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 495fdc1..d3977c7 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1227,6 +1227,8 @@
 		
 	UFSD("ENTER\n");
 
+	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
 	if (sb->s_dirt)
 		ufs_write_super(sb);
 
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 8115292..cfa2abb 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -156,16 +156,6 @@
 #define sb_dquot_ops (&dquot_operations)
 #define sb_quotactl_ops (&vfs_quotactl_ops)
 
-/* Cannot be called inside a transaction */
-static inline int vfs_dq_off(struct super_block *sb, int remount)
-{
-	int ret = -ENOSYS;
-
-	if (sb->s_qcop && sb->s_qcop->quota_off)
-		ret = sb->s_qcop->quota_off(sb, -1, remount);
-	return ret;
-}
-
 #else
 
 static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
@@ -232,11 +222,6 @@
 {
 }
 
-static inline int vfs_dq_off(struct super_block *sb, int remount)
-{
-	return 0;
-}
-
 static inline int dquot_transfer(struct inode *inode, struct iattr *iattr)
 {
 	return 0;