GFS2: Clean up & move gfs2_quotad
authorSteven Whitehouse <swhiteho@redhat.com>
Mon, 17 Nov 2008 14:25:37 +0000 (14:25 +0000)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 5 Jan 2009 07:39:05 +0000 (07:39 +0000)
This patch is a clean up of gfs2_quotad prior to giving it an
extra job to do in addition to the current portfolio of updating
the quota and statfs information from time to time.

As a result it has been moved into quota.c allowing one of the
functions it calls to be made static. Also the clean up allows
the two existing functions to have separate timeouts and also
to coexist with its future role of dealing with the "truncate in
progress" inode flag.

The (pointless) setting of gfs2_quotad_secs is removed since we
arrange to only wake up quotad when one of the two timers expires.

In addition the struct gfs2_quota_data is moved into a slab cache,
mainly for easier debugging. It should also be possible to use
a shrinker in the future, rather than the current scheme of scanning
the quota data entries from time to time.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/daemon.c
fs/gfs2/incore.h
fs/gfs2/main.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/quota.h
fs/gfs2/sys.c
fs/gfs2/util.c
fs/gfs2/util.h

index e51991947d2cd876c39ba4eea0d8b6b31c838ebe..5668aa77b95afb798e47513c85fd392203ffb912 100644 (file)
@@ -23,7 +23,6 @@
 #include "daemon.h"
 #include "glock.h"
 #include "log.h"
-#include "quota.h"
 #include "recovery.h"
 #include "super.h"
 #include "util.h"
@@ -82,55 +81,3 @@ int gfs2_recoverd(void *data)
        return 0;
 }
 
-/**
- * gfs2_quotad - Write cached quota changes into the quota file
- * @sdp: Pointer to GFS2 superblock
- *
- */
-
-int gfs2_quotad(void *data)
-{
-       struct gfs2_sbd *sdp = data;
-       unsigned long t;
-       int error;
-
-       while (!kthread_should_stop()) {
-               /* Update the master statfs file */
-
-               t = sdp->sd_statfs_sync_time +
-                   gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
-
-               if (time_after_eq(jiffies, t)) {
-                       error = gfs2_statfs_sync(sdp);
-                       if (error &&
-                           error != -EROFS &&
-                           !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
-                               fs_err(sdp, "quotad: (1) error=%d\n", error);
-                       sdp->sd_statfs_sync_time = jiffies;
-               }
-
-               /* Update quota file */
-
-               t = sdp->sd_quota_sync_time +
-                   gfs2_tune_get(sdp, gt_quota_quantum) * HZ;
-
-               if (time_after_eq(jiffies, t)) {
-                       error = gfs2_quota_sync(sdp);
-                       if (error &&
-                           error != -EROFS &&
-                           !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
-                               fs_err(sdp, "quotad: (2) error=%d\n", error);
-                       sdp->sd_quota_sync_time = jiffies;
-               }
-
-               gfs2_quota_scan(sdp);
-
-               t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
-               if (freezing(current))
-                       refrigerator();
-               schedule_timeout_interruptible(t);
-       }
-
-       return 0;
-}
-
index 9e3b613d0baccc6832ba1ad513a100e995e0d2e5..cfebc1793574c75ce8d4914b1eb2ca3eb0f74aad 100644 (file)
@@ -402,7 +402,6 @@ struct gfs2_tune {
 
        unsigned int gt_recoverd_secs;
        unsigned int gt_logd_secs;
-       unsigned int gt_quotad_secs;
 
        unsigned int gt_quota_simul_sync; /* Max quotavals to sync at once */
        unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
@@ -509,7 +508,6 @@ struct gfs2_sbd {
        spinlock_t sd_statfs_spin;
        struct gfs2_statfs_change_host sd_statfs_master;
        struct gfs2_statfs_change_host sd_statfs_local;
-       unsigned long sd_statfs_sync_time;
 
        /* Resource group stuff */
 
@@ -551,13 +549,13 @@ struct gfs2_sbd {
        atomic_t sd_quota_count;
        spinlock_t sd_quota_spin;
        struct mutex sd_quota_mutex;
+       wait_queue_head_t sd_quota_wait;
 
        unsigned int sd_quota_slots;
        unsigned int sd_quota_chunks;
        unsigned char **sd_quota_bitmap;
 
        u64 sd_quota_sync_gen;
-       unsigned long sd_quota_sync_time;
 
        /* Log stuff */
 
index 3eea03c78534496400e26497ad903bd9f51618fa..e3f6f1844a21471b47003a04dea3c28548f278a8 100644 (file)
@@ -93,6 +93,12 @@ static int __init init_gfs2_fs(void)
        if (!gfs2_rgrpd_cachep)
                goto fail;
 
+       gfs2_quotad_cachep = kmem_cache_create("gfs2_quotad",
+                                              sizeof(struct gfs2_quota_data),
+                                              0, 0, NULL);
+       if (!gfs2_quotad_cachep)
+               goto fail;
+
        error = register_filesystem(&gfs2_fs_type);
        if (error)
                goto fail;
@@ -112,6 +118,9 @@ fail_unregister:
 fail:
        gfs2_glock_exit();
 
+       if (gfs2_quotad_cachep)
+               kmem_cache_destroy(gfs2_quotad_cachep);
+
        if (gfs2_rgrpd_cachep)
                kmem_cache_destroy(gfs2_rgrpd_cachep);
 
@@ -140,6 +149,7 @@ static void __exit exit_gfs2_fs(void)
        unregister_filesystem(&gfs2_fs_type);
        unregister_filesystem(&gfs2meta_fs_type);
 
+       kmem_cache_destroy(gfs2_quotad_cachep);
        kmem_cache_destroy(gfs2_rgrpd_cachep);
        kmem_cache_destroy(gfs2_bufdata_cachep);
        kmem_cache_destroy(gfs2_inode_cachep);
index dd83e832235070f7eb87a2b41ad66851d9ee140a..5d137063b67946b7cc491714f206e4e0d999ce75 100644 (file)
@@ -60,7 +60,6 @@ static void gfs2_tune_init(struct gfs2_tune *gt)
        gt->gt_log_flush_secs = 60;
        gt->gt_recoverd_secs = 60;
        gt->gt_logd_secs = 1;
-       gt->gt_quotad_secs = 5;
        gt->gt_quota_simul_sync = 64;
        gt->gt_quota_warn_period = 10;
        gt->gt_quota_scale_num = 1;
@@ -107,6 +106,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
        INIT_LIST_HEAD(&sdp->sd_quota_list);
        spin_lock_init(&sdp->sd_quota_spin);
        mutex_init(&sdp->sd_quota_mutex);
+       init_waitqueue_head(&sdp->sd_quota_wait);
 
        spin_lock_init(&sdp->sd_log_lock);
 
@@ -970,9 +970,6 @@ static int init_threads(struct gfs2_sbd *sdp, int undo)
        }
        sdp->sd_logd_process = p;
 
-       sdp->sd_statfs_sync_time = jiffies;
-       sdp->sd_quota_sync_time = jiffies;
-
        p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad");
        error = IS_ERR(p);
        if (error) {
index 228a46596188e18ede47d23d983fa1ae007be47e..0cfe44f0b6ab6a68e213ad9e934e5a612d2c3326 100644 (file)
@@ -46,6 +46,8 @@
 #include <linux/bio.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -94,7 +96,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
        struct gfs2_quota_data *qd;
        int error;
 
-       qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS);
+       qd = kmem_cache_zalloc(gfs2_quotad_cachep, GFP_NOFS);
        if (!qd)
                return -ENOMEM;
 
@@ -119,7 +121,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
        return 0;
 
 fail:
-       kfree(qd);
+       kmem_cache_free(gfs2_quotad_cachep, qd);
        return error;
 }
 
@@ -158,7 +160,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create,
                if (qd || !create) {
                        if (new_qd) {
                                gfs2_lvb_unhold(new_qd->qd_gl);
-                               kfree(new_qd);
+                               kmem_cache_free(gfs2_quotad_cachep, new_qd);
                        }
                        *qdp = qd;
                        return 0;
@@ -1195,7 +1197,7 @@ fail:
        return error;
 }
 
-void gfs2_quota_scan(struct gfs2_sbd *sdp)
+static void gfs2_quota_scan(struct gfs2_sbd *sdp)
 {
        struct gfs2_quota_data *qd, *safe;
        LIST_HEAD(dead);
@@ -1222,7 +1224,7 @@ void gfs2_quota_scan(struct gfs2_sbd *sdp)
                gfs2_assert_warn(sdp, !qd->qd_bh_count);
 
                gfs2_lvb_unhold(qd->qd_gl);
-               kfree(qd);
+               kmem_cache_free(gfs2_quotad_cachep, qd);
        }
 }
 
@@ -1257,7 +1259,7 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
                gfs2_assert_warn(sdp, !qd->qd_bh_count);
 
                gfs2_lvb_unhold(qd->qd_gl);
-               kfree(qd);
+               kmem_cache_free(gfs2_quotad_cachep, qd);
 
                spin_lock(&sdp->sd_quota_spin);
        }
@@ -1272,3 +1274,65 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
        }
 }
 
+static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error)
+{
+       if (error == 0 || error == -EROFS)
+               return;
+       if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
+               fs_err(sdp, "gfs2_quotad: %s error %d\n", msg, error);
+}
+
+static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg,
+                              int (*fxn)(struct gfs2_sbd *sdp),
+                              unsigned long t, unsigned long *timeo,
+                              unsigned int *new_timeo)
+{
+       if (t >= *timeo) {
+               int error = fxn(sdp);
+               quotad_error(sdp, msg, error);
+               *timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ;
+       } else {
+               *timeo -= t;
+       }
+}
+
+/**
+ * gfs2_quotad - Write cached quota changes into the quota file
+ * @sdp: Pointer to GFS2 superblock
+ *
+ */
+
+int gfs2_quotad(void *data)
+{
+       struct gfs2_sbd *sdp = data;
+       struct gfs2_tune *tune = &sdp->sd_tune;
+       unsigned long statfs_timeo = 0;
+       unsigned long quotad_timeo = 0;
+       unsigned long t = 0;
+       DEFINE_WAIT(wait);
+
+       while (!kthread_should_stop()) {
+
+               /* Update the master statfs file */
+               quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
+                                  &statfs_timeo, &tune->gt_statfs_quantum);
+
+               /* Update quota file */
+               quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
+                                  &quotad_timeo, &tune->gt_quota_quantum);
+
+               /* FIXME: This should be turned into a shrinker */
+               gfs2_quota_scan(sdp);
+
+               if (freezing(current))
+                       refrigerator();
+               t = min(quotad_timeo, statfs_timeo);
+
+               prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_UNINTERRUPTIBLE);
+               t -= schedule_timeout(t);
+               finish_wait(&sdp->sd_quota_wait, &wait);
+       }
+
+       return 0;
+}
+
index 3b7f4b0e5dfe0fee9e155f01f2fc3fa224ddabfc..1d08aeef07e67969ec4baf87da5b4128fe8d461c 100644 (file)
@@ -29,7 +29,6 @@ int gfs2_quota_sync(struct gfs2_sbd *sdp);
 int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
 
 int gfs2_quota_init(struct gfs2_sbd *sdp);
-void gfs2_quota_scan(struct gfs2_sbd *sdp);
 void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
 
 static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
index 7e1879f1a02c6e16d83b3d611902f665dc3149b2..59e36fd80903f219d7fe1cf9be5c5bc211243f2d 100644 (file)
@@ -408,7 +408,6 @@ TUNE_ATTR(stall_secs, 1);
 TUNE_ATTR(statfs_quantum, 1);
 TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
 TUNE_ATTR_DAEMON(logd_secs, logd_process);
-TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
 TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
 
 static struct attribute *tune_attrs[] = {
@@ -426,7 +425,6 @@ static struct attribute *tune_attrs[] = {
        &tune_attr_statfs_quantum.attr,
        &tune_attr_recoverd_secs.attr,
        &tune_attr_logd_secs.attr,
-       &tune_attr_quotad_secs.attr,
        &tune_attr_quota_scale.attr,
        &tune_attr_new_files_jdata.attr,
        NULL,
index d31e355c61fbc5040f0a2b8ac9775724a67eee53..374f50e954967a147e56dffe2eec590c9fc087bc 100644 (file)
@@ -25,6 +25,7 @@ struct kmem_cache *gfs2_glock_cachep __read_mostly;
 struct kmem_cache *gfs2_inode_cachep __read_mostly;
 struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
 struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
+struct kmem_cache *gfs2_quotad_cachep __read_mostly;
 
 void gfs2_assert_i(struct gfs2_sbd *sdp)
 {
index 7f48576289c9f9a916aee237d6b2d6308f2bb93b..33e96b0ce9abc6b983aa0d79cba6d77f8676236d 100644 (file)
@@ -148,6 +148,7 @@ extern struct kmem_cache *gfs2_glock_cachep;
 extern struct kmem_cache *gfs2_inode_cachep;
 extern struct kmem_cache *gfs2_bufdata_cachep;
 extern struct kmem_cache *gfs2_rgrpd_cachep;
+extern struct kmem_cache *gfs2_quotad_cachep;
 
 static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
                                           unsigned int *p)