Merge branch 'fix' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6
[pandora-kernel.git] / fs / ocfs2 / super.c
index 5745682..0eaa929 100644 (file)
@@ -96,6 +96,7 @@ struct mount_options
        signed short    slot;
        int             localalloc_opt;
        unsigned int    resv_level;
+       int             dir_resv_level;
        char            cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
 };
 
@@ -178,6 +179,7 @@ enum {
        Opt_usrquota,
        Opt_grpquota,
        Opt_resv_level,
+       Opt_dir_resv_level,
        Opt_err,
 };
 
@@ -205,6 +207,7 @@ static const match_table_t tokens = {
        {Opt_usrquota, "usrquota"},
        {Opt_grpquota, "grpquota"},
        {Opt_resv_level, "resv_level=%u"},
+       {Opt_dir_resv_level, "dir_resv_level=%u"},
        {Opt_err, NULL}
 };
 
@@ -876,13 +879,15 @@ static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend)
                if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
                        continue;
                if (unsuspend)
-                       status = vfs_quota_enable(
-                                       sb_dqopt(sb)->files[type],
-                                       type, QFMT_OCFS2,
-                                       DQUOT_SUSPENDED);
-               else
-                       status = vfs_quota_disable(sb, type,
-                                                  DQUOT_SUSPENDED);
+                       status = dquot_resume(sb, type);
+               else {
+                       struct ocfs2_mem_dqinfo *oinfo;
+
+                       /* Cancel periodic syncing before suspending */
+                       oinfo = sb_dqinfo(sb, type)->dqi_priv;
+                       cancel_delayed_work_sync(&oinfo->dqi_sync_work);
+                       status = dquot_suspend(sb, type);
+               }
                if (status < 0)
                        break;
        }
@@ -913,8 +918,8 @@ static int ocfs2_enable_quotas(struct ocfs2_super *osb)
                        status = -ENOENT;
                        goto out_quota_off;
                }
-               status = vfs_quota_enable(inode[type], type, QFMT_OCFS2,
-                                               DQUOT_USAGE_ENABLED);
+               status = dquot_enable(inode[type], type, QFMT_OCFS2,
+                                     DQUOT_USAGE_ENABLED);
                if (status < 0)
                        goto out_quota_off;
        }
@@ -935,18 +940,22 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb)
        int type;
        struct inode *inode;
        struct super_block *sb = osb->sb;
+       struct ocfs2_mem_dqinfo *oinfo;
 
        /* We mostly ignore errors in this function because there's not much
         * we can do when we see them */
        for (type = 0; type < MAXQUOTAS; type++) {
                if (!sb_has_quota_loaded(sb, type))
                        continue;
+               /* Cancel periodic syncing before we grab dqonoff_mutex */
+               oinfo = sb_dqinfo(sb, type)->dqi_priv;
+               cancel_delayed_work_sync(&oinfo->dqi_sync_work);
                inode = igrab(sb->s_dquot.files[type]);
                /* Turn off quotas. This will remove all dquot structures from
                 * memory and so they will be automatically synced to global
                 * quota files */
-               vfs_quota_disable(sb, type, DQUOT_USAGE_ENABLED |
-                                           DQUOT_LIMITS_ENABLED);
+               dquot_disable(sb, type, DQUOT_USAGE_ENABLED |
+                                       DQUOT_LIMITS_ENABLED);
                if (!inode)
                        continue;
                iput(inode);
@@ -955,7 +964,7 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb)
 
 /* Handle quota on quotactl */
 static int ocfs2_quota_on(struct super_block *sb, int type, int format_id,
-                         char *path, int remount)
+                         char *path)
 {
        unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
                                             OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
@@ -963,30 +972,24 @@ static int ocfs2_quota_on(struct super_block *sb, int type, int format_id,
        if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
                return -EINVAL;
 
-       if (remount)
-               return 0;       /* Just ignore it has been handled in
-                                * ocfs2_remount() */
-       return vfs_quota_enable(sb_dqopt(sb)->files[type], type,
-                                   format_id, DQUOT_LIMITS_ENABLED);
+       return dquot_enable(sb_dqopt(sb)->files[type], type,
+                           format_id, DQUOT_LIMITS_ENABLED);
 }
 
 /* Handle quota off quotactl */
-static int ocfs2_quota_off(struct super_block *sb, int type, int remount)
+static int ocfs2_quota_off(struct super_block *sb, int type)
 {
-       if (remount)
-               return 0;       /* Ignore now and handle later in
-                                * ocfs2_remount() */
-       return vfs_quota_disable(sb, type, DQUOT_LIMITS_ENABLED);
+       return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
 }
 
 static const struct quotactl_ops ocfs2_quotactl_ops = {
        .quota_on       = ocfs2_quota_on,
        .quota_off      = ocfs2_quota_off,
-       .quota_sync     = vfs_quota_sync,
-       .get_info       = vfs_get_dqinfo,
-       .set_info       = vfs_set_dqinfo,
-       .get_dqblk      = vfs_get_dqblk,
-       .set_dqblk      = vfs_set_dqblk,
+       .quota_sync     = dquot_quota_sync,
+       .get_info       = dquot_get_dqinfo,
+       .set_info       = dquot_set_dqinfo,
+       .get_dqblk      = dquot_get_dqblk,
+       .set_dqblk      = dquot_set_dqblk,
 };
 
 static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
@@ -1034,6 +1037,11 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt);
        osb->osb_resv_level = parsed_options.resv_level;
+       osb->osb_dir_resv_level = parsed_options.resv_level;
+       if (parsed_options.dir_resv_level == -1)
+               osb->osb_dir_resv_level = parsed_options.resv_level;
+       else
+               osb->osb_dir_resv_level = parsed_options.dir_resv_level;
 
        status = ocfs2_verify_userspace_stack(osb, &parsed_options);
        if (status)
@@ -1289,12 +1297,13 @@ static int ocfs2_parse_options(struct super_block *sb,
                   options ? options : "(none)");
 
        mopt->commit_interval = 0;
-       mopt->mount_opt = 0;
+       mopt->mount_opt = OCFS2_MOUNT_NOINTR;
        mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
        mopt->slot = OCFS2_INVALID_SLOT;
        mopt->localalloc_opt = -1;
        mopt->cluster_stack[0] = '\0';
        mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL;
+       mopt->dir_resv_level = -1;
 
        if (!options) {
                status = 1;
@@ -1449,6 +1458,17 @@ static int ocfs2_parse_options(struct super_block *sb,
                            option < OCFS2_MAX_RESV_LEVEL)
                                mopt->resv_level = option;
                        break;
+               case Opt_dir_resv_level:
+                       if (is_remount)
+                               break;
+                       if (match_int(&args[0], &option)) {
+                               status = 0;
+                               goto bail;
+                       }
+                       if (option >= OCFS2_MIN_RESV_LEVEL &&
+                           option < OCFS2_MAX_RESV_LEVEL)
+                               mopt->dir_resv_level = option;
+                       break;
                default:
                        mlog(ML_ERROR,
                             "Unrecognized mount option \"%s\" "
@@ -1533,6 +1553,9 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL)
                seq_printf(s, ",resv_level=%d", osb->osb_resv_level);
 
+       if (osb->osb_dir_resv_level != osb->osb_resv_level)
+               seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level);
+
        return 0;
 }
 
@@ -2254,7 +2277,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
        osb->osb_clusters_at_boot = OCFS2_I(inode)->ip_clusters;
        iput(inode);
 
-       osb->bitmap_cpg = ocfs2_group_bitmap_size(sb) * 8;
+       osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0,
+                                osb->s_feature_incompat) * 8;
 
        status = ocfs2_init_slot_info(osb);
        if (status < 0) {
@@ -2537,5 +2561,25 @@ void __ocfs2_abort(struct super_block* sb,
        ocfs2_handle_error(sb);
 }
 
+/*
+ * Void signal blockers, because in-kernel sigprocmask() only fails
+ * when SIG_* is wrong.
+ */
+void ocfs2_block_signals(sigset_t *oldset)
+{
+       int rc;
+       sigset_t blocked;
+
+       sigfillset(&blocked);
+       rc = sigprocmask(SIG_BLOCK, &blocked, oldset);
+       BUG_ON(rc);
+}
+
+void ocfs2_unblock_signals(sigset_t *oldset)
+{
+       int rc = sigprocmask(SIG_SETMASK, oldset, NULL);
+       BUG_ON(rc);
+}
+
 module_init(ocfs2_init);
 module_exit(ocfs2_exit);