aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/journal.c20
-rw-r--r--fs/ocfs2/ocfs2.h3
-rw-r--r--fs/ocfs2/ocfs2_fs.h4
-rw-r--r--fs/ocfs2/super.c222
4 files changed, 245 insertions, 4 deletions
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index c60242018d9a..302f1144a708 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -56,7 +56,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
56 int node_num, int slot_num); 56 int node_num, int slot_num);
57static int __ocfs2_recovery_thread(void *arg); 57static int __ocfs2_recovery_thread(void *arg);
58static int ocfs2_commit_cache(struct ocfs2_super *osb); 58static int ocfs2_commit_cache(struct ocfs2_super *osb);
59static int ocfs2_wait_on_mount(struct ocfs2_super *osb); 59static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota);
60static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, 60static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
61 int dirty, int replayed); 61 int dirty, int replayed);
62static int ocfs2_trylock_journal(struct ocfs2_super *osb, 62static int ocfs2_trylock_journal(struct ocfs2_super *osb,
@@ -65,6 +65,17 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
65 int slot); 65 int slot);
66static int ocfs2_commit_thread(void *arg); 66static int ocfs2_commit_thread(void *arg);
67 67
68static inline int ocfs2_wait_on_mount(struct ocfs2_super *osb)
69{
70 return __ocfs2_wait_on_mount(osb, 0);
71}
72
73static inline int ocfs2_wait_on_quotas(struct ocfs2_super *osb)
74{
75 return __ocfs2_wait_on_mount(osb, 1);
76}
77
78
68 79
69/* 80/*
70 * The recovery_list is a simple linked list of node numbers to recover. 81 * The recovery_list is a simple linked list of node numbers to recover.
@@ -895,6 +906,8 @@ void ocfs2_complete_recovery(struct work_struct *work)
895 906
896 mlog(0, "Complete recovery for slot %d\n", item->lri_slot); 907 mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
897 908
909 ocfs2_wait_on_quotas(osb);
910
898 la_dinode = item->lri_la_dinode; 911 la_dinode = item->lri_la_dinode;
899 if (la_dinode) { 912 if (la_dinode) {
900 mlog(0, "Clean up local alloc %llu\n", 913 mlog(0, "Clean up local alloc %llu\n",
@@ -1701,13 +1714,14 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
1701 return ret; 1714 return ret;
1702} 1715}
1703 1716
1704static int ocfs2_wait_on_mount(struct ocfs2_super *osb) 1717static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota)
1705{ 1718{
1706 /* This check is good because ocfs2 will wait on our recovery 1719 /* This check is good because ocfs2 will wait on our recovery
1707 * thread before changing it to something other than MOUNTED 1720 * thread before changing it to something other than MOUNTED
1708 * or DISABLED. */ 1721 * or DISABLED. */
1709 wait_event(osb->osb_mount_event, 1722 wait_event(osb->osb_mount_event,
1710 atomic_read(&osb->vol_state) == VOLUME_MOUNTED || 1723 (!quota && atomic_read(&osb->vol_state) == VOLUME_MOUNTED) ||
1724 atomic_read(&osb->vol_state) == VOLUME_MOUNTED_QUOTAS ||
1711 atomic_read(&osb->vol_state) == VOLUME_DISABLED); 1725 atomic_read(&osb->vol_state) == VOLUME_DISABLED);
1712 1726
1713 /* If there's an error on mount, then we may never get to the 1727 /* If there's an error on mount, then we may never get to the
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 6b25b4aa7205..5c777988042f 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -161,6 +161,7 @@ enum ocfs2_vol_state
161{ 161{
162 VOLUME_INIT = 0, 162 VOLUME_INIT = 0,
163 VOLUME_MOUNTED, 163 VOLUME_MOUNTED,
164 VOLUME_MOUNTED_QUOTAS,
164 VOLUME_DISMOUNTED, 165 VOLUME_DISMOUNTED,
165 VOLUME_DISABLED 166 VOLUME_DISABLED
166}; 167};
@@ -196,6 +197,8 @@ enum ocfs2_mount_options
196 OCFS2_MOUNT_NOUSERXATTR = 1 << 6, /* No user xattr */ 197 OCFS2_MOUNT_NOUSERXATTR = 1 << 6, /* No user xattr */
197 OCFS2_MOUNT_INODE64 = 1 << 7, /* Allow inode numbers > 2^32 */ 198 OCFS2_MOUNT_INODE64 = 1 << 7, /* Allow inode numbers > 2^32 */
198 OCFS2_MOUNT_POSIX_ACL = 1 << 8, /* POSIX access control lists */ 199 OCFS2_MOUNT_POSIX_ACL = 1 << 8, /* POSIX access control lists */
200 OCFS2_MOUNT_USRQUOTA = 1 << 9, /* We support user quotas */
201 OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
199}; 202};
200 203
201#define OCFS2_OSB_SOFT_RO 0x0001 204#define OCFS2_OSB_SOFT_RO 0x0001
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 0a5ac790a628..359732e18e82 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -94,7 +94,9 @@
94 | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \ 94 | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \
95 | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \ 95 | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \
96 | OCFS2_FEATURE_INCOMPAT_XATTR) 96 | OCFS2_FEATURE_INCOMPAT_XATTR)
97#define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN) 97#define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
98 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
99 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
98 100
99/* 101/*
100 * Heartbeat-only devices are missing journals and other files. The 102 * Heartbeat-only devices are missing journals and other files. The
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 60f1d29421ad..2eb657c3e7a8 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -41,6 +41,7 @@
41#include <linux/debugfs.h> 41#include <linux/debugfs.h>
42#include <linux/mount.h> 42#include <linux/mount.h>
43#include <linux/seq_file.h> 43#include <linux/seq_file.h>
44#include <linux/quotaops.h>
44 45
45#define MLOG_MASK_PREFIX ML_SUPER 46#define MLOG_MASK_PREFIX ML_SUPER
46#include <cluster/masklog.h> 47#include <cluster/masklog.h>
@@ -127,6 +128,9 @@ static int ocfs2_get_sector(struct super_block *sb,
127static void ocfs2_write_super(struct super_block *sb); 128static void ocfs2_write_super(struct super_block *sb);
128static struct inode *ocfs2_alloc_inode(struct super_block *sb); 129static struct inode *ocfs2_alloc_inode(struct super_block *sb);
129static void ocfs2_destroy_inode(struct inode *inode); 130static void ocfs2_destroy_inode(struct inode *inode);
131static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend);
132static int ocfs2_enable_quotas(struct ocfs2_super *osb);
133static void ocfs2_disable_quotas(struct ocfs2_super *osb);
130 134
131static const struct super_operations ocfs2_sops = { 135static const struct super_operations ocfs2_sops = {
132 .statfs = ocfs2_statfs, 136 .statfs = ocfs2_statfs,
@@ -165,6 +169,8 @@ enum {
165 Opt_inode64, 169 Opt_inode64,
166 Opt_acl, 170 Opt_acl,
167 Opt_noacl, 171 Opt_noacl,
172 Opt_usrquota,
173 Opt_grpquota,
168 Opt_err, 174 Opt_err,
169}; 175};
170 176
@@ -189,6 +195,8 @@ static const match_table_t tokens = {
189 {Opt_inode64, "inode64"}, 195 {Opt_inode64, "inode64"},
190 {Opt_acl, "acl"}, 196 {Opt_acl, "acl"},
191 {Opt_noacl, "noacl"}, 197 {Opt_noacl, "noacl"},
198 {Opt_usrquota, "usrquota"},
199 {Opt_grpquota, "grpquota"},
192 {Opt_err, NULL} 200 {Opt_err, NULL}
193}; 201};
194 202
@@ -452,6 +460,12 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
452 460
453 /* We're going to/from readonly mode. */ 461 /* We're going to/from readonly mode. */
454 if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { 462 if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
463 /* Disable quota accounting before remounting RO */
464 if (*flags & MS_RDONLY) {
465 ret = ocfs2_susp_quotas(osb, 0);
466 if (ret < 0)
467 goto out;
468 }
455 /* Lock here so the check of HARD_RO and the potential 469 /* Lock here so the check of HARD_RO and the potential
456 * setting of SOFT_RO is atomic. */ 470 * setting of SOFT_RO is atomic. */
457 spin_lock(&osb->osb_lock); 471 spin_lock(&osb->osb_lock);
@@ -487,6 +501,21 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
487 } 501 }
488unlock_osb: 502unlock_osb:
489 spin_unlock(&osb->osb_lock); 503 spin_unlock(&osb->osb_lock);
504 /* Enable quota accounting after remounting RW */
505 if (!ret && !(*flags & MS_RDONLY)) {
506 if (sb_any_quota_suspended(sb))
507 ret = ocfs2_susp_quotas(osb, 1);
508 else
509 ret = ocfs2_enable_quotas(osb);
510 if (ret < 0) {
511 /* Return back changes... */
512 spin_lock(&osb->osb_lock);
513 sb->s_flags |= MS_RDONLY;
514 osb->osb_flags |= OCFS2_OSB_SOFT_RO;
515 spin_unlock(&osb->osb_lock);
516 goto out;
517 }
518 }
490 } 519 }
491 520
492 if (!ret) { 521 if (!ret) {
@@ -647,6 +676,131 @@ static int ocfs2_verify_userspace_stack(struct ocfs2_super *osb,
647 return 0; 676 return 0;
648} 677}
649 678
679static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend)
680{
681 int type;
682 struct super_block *sb = osb->sb;
683 unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
684 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
685 int status = 0;
686
687 for (type = 0; type < MAXQUOTAS; type++) {
688 if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
689 continue;
690 if (unsuspend)
691 status = vfs_quota_enable(
692 sb_dqopt(sb)->files[type],
693 type, QFMT_OCFS2,
694 DQUOT_SUSPENDED);
695 else
696 status = vfs_quota_disable(sb, type,
697 DQUOT_SUSPENDED);
698 if (status < 0)
699 break;
700 }
701 if (status < 0)
702 mlog(ML_ERROR, "Failed to suspend/unsuspend quotas on "
703 "remount (error = %d).\n", status);
704 return status;
705}
706
707static int ocfs2_enable_quotas(struct ocfs2_super *osb)
708{
709 struct inode *inode[MAXQUOTAS] = { NULL, NULL };
710 struct super_block *sb = osb->sb;
711 unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
712 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
713 unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE,
714 LOCAL_GROUP_QUOTA_SYSTEM_INODE };
715 int status;
716 int type;
717
718 sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE;
719 for (type = 0; type < MAXQUOTAS; type++) {
720 if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
721 continue;
722 inode[type] = ocfs2_get_system_file_inode(osb, ino[type],
723 osb->slot_num);
724 if (!inode[type]) {
725 status = -ENOENT;
726 goto out_quota_off;
727 }
728 status = vfs_quota_enable(inode[type], type, QFMT_OCFS2,
729 DQUOT_USAGE_ENABLED);
730 if (status < 0)
731 goto out_quota_off;
732 }
733
734 for (type = 0; type < MAXQUOTAS; type++)
735 iput(inode[type]);
736 return 0;
737out_quota_off:
738 ocfs2_disable_quotas(osb);
739 for (type = 0; type < MAXQUOTAS; type++)
740 iput(inode[type]);
741 mlog_errno(status);
742 return status;
743}
744
745static void ocfs2_disable_quotas(struct ocfs2_super *osb)
746{
747 int type;
748 struct inode *inode;
749 struct super_block *sb = osb->sb;
750
751 /* We mostly ignore errors in this function because there's not much
752 * we can do when we see them */
753 for (type = 0; type < MAXQUOTAS; type++) {
754 if (!sb_has_quota_loaded(sb, type))
755 continue;
756 inode = igrab(sb->s_dquot.files[type]);
757 /* Turn off quotas. This will remove all dquot structures from
758 * memory and so they will be automatically synced to global
759 * quota files */
760 vfs_quota_disable(sb, type, DQUOT_USAGE_ENABLED |
761 DQUOT_LIMITS_ENABLED);
762 if (!inode)
763 continue;
764 iput(inode);
765 }
766}
767
768/* Handle quota on quotactl */
769static int ocfs2_quota_on(struct super_block *sb, int type, int format_id,
770 char *path, int remount)
771{
772 unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
773 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
774
775 if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
776 return -EINVAL;
777
778 if (remount)
779 return 0; /* Just ignore it has been handled in
780 * ocfs2_remount() */
781 return vfs_quota_enable(sb_dqopt(sb)->files[type], type,
782 format_id, DQUOT_LIMITS_ENABLED);
783}
784
785/* Handle quota off quotactl */
786static int ocfs2_quota_off(struct super_block *sb, int type, int remount)
787{
788 if (remount)
789 return 0; /* Ignore now and handle later in
790 * ocfs2_remount() */
791 return vfs_quota_disable(sb, type, DQUOT_LIMITS_ENABLED);
792}
793
794static struct quotactl_ops ocfs2_quotactl_ops = {
795 .quota_on = ocfs2_quota_on,
796 .quota_off = ocfs2_quota_off,
797 .quota_sync = vfs_quota_sync,
798 .get_info = vfs_get_dqinfo,
799 .set_info = vfs_set_dqinfo,
800 .get_dqblk = vfs_get_dqblk,
801 .set_dqblk = vfs_set_dqblk,
802};
803
650static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) 804static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
651{ 805{
652 struct dentry *root; 806 struct dentry *root;
@@ -689,6 +843,22 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
689 osb->osb_commit_interval = parsed_options.commit_interval; 843 osb->osb_commit_interval = parsed_options.commit_interval;
690 osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt); 844 osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt);
691 osb->local_alloc_bits = osb->local_alloc_default_bits; 845 osb->local_alloc_bits = osb->local_alloc_default_bits;
846 if (osb->s_mount_opt & OCFS2_MOUNT_USRQUOTA &&
847 !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
848 OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
849 status = -EINVAL;
850 mlog(ML_ERROR, "User quotas were requested, but this "
851 "filesystem does not have the feature enabled.\n");
852 goto read_super_error;
853 }
854 if (osb->s_mount_opt & OCFS2_MOUNT_GRPQUOTA &&
855 !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
856 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
857 status = -EINVAL;
858 mlog(ML_ERROR, "Group quotas were requested, but this "
859 "filesystem does not have the feature enabled.\n");
860 goto read_super_error;
861 }
692 862
693 status = ocfs2_verify_userspace_stack(osb, &parsed_options); 863 status = ocfs2_verify_userspace_stack(osb, &parsed_options);
694 if (status) 864 if (status)
@@ -793,6 +963,28 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
793 atomic_set(&osb->vol_state, VOLUME_MOUNTED); 963 atomic_set(&osb->vol_state, VOLUME_MOUNTED);
794 wake_up(&osb->osb_mount_event); 964 wake_up(&osb->osb_mount_event);
795 965
966 /* Now we can initialize quotas because we can afford to wait
967 * for cluster locks recovery now. That also means that truncation
968 * log recovery can happen but that waits for proper quota setup */
969 if (!(sb->s_flags & MS_RDONLY)) {
970 status = ocfs2_enable_quotas(osb);
971 if (status < 0) {
972 /* We have to err-out specially here because
973 * s_root is already set */
974 mlog_errno(status);
975 atomic_set(&osb->vol_state, VOLUME_DISABLED);
976 wake_up(&osb->osb_mount_event);
977 mlog_exit(status);
978 return status;
979 }
980 }
981
982 ocfs2_complete_quota_recovery(osb);
983
984 /* Now we wake up again for processes waiting for quotas */
985 atomic_set(&osb->vol_state, VOLUME_MOUNTED_QUOTAS);
986 wake_up(&osb->osb_mount_event);
987
796 mlog_exit(status); 988 mlog_exit(status);
797 return status; 989 return status;
798 990
@@ -980,6 +1172,28 @@ static int ocfs2_parse_options(struct super_block *sb,
980 case Opt_inode64: 1172 case Opt_inode64:
981 mopt->mount_opt |= OCFS2_MOUNT_INODE64; 1173 mopt->mount_opt |= OCFS2_MOUNT_INODE64;
982 break; 1174 break;
1175 case Opt_usrquota:
1176 /* We check only on remount, otherwise features
1177 * aren't yet initialized. */
1178 if (is_remount && !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
1179 OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
1180 mlog(ML_ERROR, "User quota requested but "
1181 "filesystem feature is not set\n");
1182 status = 0;
1183 goto bail;
1184 }
1185 mopt->mount_opt |= OCFS2_MOUNT_USRQUOTA;
1186 break;
1187 case Opt_grpquota:
1188 if (is_remount && !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
1189 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
1190 mlog(ML_ERROR, "Group quota requested but "
1191 "filesystem feature is not set\n");
1192 status = 0;
1193 goto bail;
1194 }
1195 mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA;
1196 break;
983#ifdef CONFIG_OCFS2_FS_POSIX_ACL 1197#ifdef CONFIG_OCFS2_FS_POSIX_ACL
984 case Opt_acl: 1198 case Opt_acl:
985 mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; 1199 mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL;
@@ -1056,6 +1270,10 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
1056 if (osb->osb_cluster_stack[0]) 1270 if (osb->osb_cluster_stack[0])
1057 seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN, 1271 seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN,
1058 osb->osb_cluster_stack); 1272 osb->osb_cluster_stack);
1273 if (opts & OCFS2_MOUNT_USRQUOTA)
1274 seq_printf(s, ",usrquota");
1275 if (opts & OCFS2_MOUNT_GRPQUOTA)
1276 seq_printf(s, ",grpquota");
1059 1277
1060 if (opts & OCFS2_MOUNT_NOUSERXATTR) 1278 if (opts & OCFS2_MOUNT_NOUSERXATTR)
1061 seq_printf(s, ",nouser_xattr"); 1279 seq_printf(s, ",nouser_xattr");
@@ -1394,6 +1612,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
1394 osb = OCFS2_SB(sb); 1612 osb = OCFS2_SB(sb);
1395 BUG_ON(!osb); 1613 BUG_ON(!osb);
1396 1614
1615 ocfs2_disable_quotas(osb);
1616
1397 ocfs2_shutdown_local_alloc(osb); 1617 ocfs2_shutdown_local_alloc(osb);
1398 1618
1399 ocfs2_truncate_log_shutdown(osb); 1619 ocfs2_truncate_log_shutdown(osb);
@@ -1504,6 +1724,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
1504 sb->s_fs_info = osb; 1724 sb->s_fs_info = osb;
1505 sb->s_op = &ocfs2_sops; 1725 sb->s_op = &ocfs2_sops;
1506 sb->s_export_op = &ocfs2_export_ops; 1726 sb->s_export_op = &ocfs2_export_ops;
1727 sb->s_qcop = &ocfs2_quotactl_ops;
1728 sb->dq_op = &ocfs2_quota_operations;
1507 sb->s_xattr = ocfs2_xattr_handlers; 1729 sb->s_xattr = ocfs2_xattr_handlers;
1508 sb->s_time_gran = 1; 1730 sb->s_time_gran = 1;
1509 sb->s_flags |= MS_NOATIME; 1731 sb->s_flags |= MS_NOATIME;