diff options
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r-- | fs/gfs2/quota.c | 76 |
1 files changed, 70 insertions, 6 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 228a46596188..0cfe44f0b6ab 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include <linux/bio.h> | 46 | #include <linux/bio.h> |
47 | #include <linux/gfs2_ondisk.h> | 47 | #include <linux/gfs2_ondisk.h> |
48 | #include <linux/lm_interface.h> | 48 | #include <linux/lm_interface.h> |
49 | #include <linux/kthread.h> | ||
50 | #include <linux/freezer.h> | ||
49 | 51 | ||
50 | #include "gfs2.h" | 52 | #include "gfs2.h" |
51 | #include "incore.h" | 53 | #include "incore.h" |
@@ -94,7 +96,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, | |||
94 | struct gfs2_quota_data *qd; | 96 | struct gfs2_quota_data *qd; |
95 | int error; | 97 | int error; |
96 | 98 | ||
97 | qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS); | 99 | qd = kmem_cache_zalloc(gfs2_quotad_cachep, GFP_NOFS); |
98 | if (!qd) | 100 | if (!qd) |
99 | return -ENOMEM; | 101 | return -ENOMEM; |
100 | 102 | ||
@@ -119,7 +121,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, | |||
119 | return 0; | 121 | return 0; |
120 | 122 | ||
121 | fail: | 123 | fail: |
122 | kfree(qd); | 124 | kmem_cache_free(gfs2_quotad_cachep, qd); |
123 | return error; | 125 | return error; |
124 | } | 126 | } |
125 | 127 | ||
@@ -158,7 +160,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, | |||
158 | if (qd || !create) { | 160 | if (qd || !create) { |
159 | if (new_qd) { | 161 | if (new_qd) { |
160 | gfs2_lvb_unhold(new_qd->qd_gl); | 162 | gfs2_lvb_unhold(new_qd->qd_gl); |
161 | kfree(new_qd); | 163 | kmem_cache_free(gfs2_quotad_cachep, new_qd); |
162 | } | 164 | } |
163 | *qdp = qd; | 165 | *qdp = qd; |
164 | return 0; | 166 | return 0; |
@@ -1195,7 +1197,7 @@ fail: | |||
1195 | return error; | 1197 | return error; |
1196 | } | 1198 | } |
1197 | 1199 | ||
1198 | void gfs2_quota_scan(struct gfs2_sbd *sdp) | 1200 | static void gfs2_quota_scan(struct gfs2_sbd *sdp) |
1199 | { | 1201 | { |
1200 | struct gfs2_quota_data *qd, *safe; | 1202 | struct gfs2_quota_data *qd, *safe; |
1201 | LIST_HEAD(dead); | 1203 | LIST_HEAD(dead); |
@@ -1222,7 +1224,7 @@ void gfs2_quota_scan(struct gfs2_sbd *sdp) | |||
1222 | gfs2_assert_warn(sdp, !qd->qd_bh_count); | 1224 | gfs2_assert_warn(sdp, !qd->qd_bh_count); |
1223 | 1225 | ||
1224 | gfs2_lvb_unhold(qd->qd_gl); | 1226 | gfs2_lvb_unhold(qd->qd_gl); |
1225 | kfree(qd); | 1227 | kmem_cache_free(gfs2_quotad_cachep, qd); |
1226 | } | 1228 | } |
1227 | } | 1229 | } |
1228 | 1230 | ||
@@ -1257,7 +1259,7 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp) | |||
1257 | gfs2_assert_warn(sdp, !qd->qd_bh_count); | 1259 | gfs2_assert_warn(sdp, !qd->qd_bh_count); |
1258 | 1260 | ||
1259 | gfs2_lvb_unhold(qd->qd_gl); | 1261 | gfs2_lvb_unhold(qd->qd_gl); |
1260 | kfree(qd); | 1262 | kmem_cache_free(gfs2_quotad_cachep, qd); |
1261 | 1263 | ||
1262 | spin_lock(&sdp->sd_quota_spin); | 1264 | spin_lock(&sdp->sd_quota_spin); |
1263 | } | 1265 | } |
@@ -1272,3 +1274,65 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp) | |||
1272 | } | 1274 | } |
1273 | } | 1275 | } |
1274 | 1276 | ||
1277 | static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error) | ||
1278 | { | ||
1279 | if (error == 0 || error == -EROFS) | ||
1280 | return; | ||
1281 | if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
1282 | fs_err(sdp, "gfs2_quotad: %s error %d\n", msg, error); | ||
1283 | } | ||
1284 | |||
1285 | static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg, | ||
1286 | int (*fxn)(struct gfs2_sbd *sdp), | ||
1287 | unsigned long t, unsigned long *timeo, | ||
1288 | unsigned int *new_timeo) | ||
1289 | { | ||
1290 | if (t >= *timeo) { | ||
1291 | int error = fxn(sdp); | ||
1292 | quotad_error(sdp, msg, error); | ||
1293 | *timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ; | ||
1294 | } else { | ||
1295 | *timeo -= t; | ||
1296 | } | ||
1297 | } | ||
1298 | |||
1299 | /** | ||
1300 | * gfs2_quotad - Write cached quota changes into the quota file | ||
1301 | * @sdp: Pointer to GFS2 superblock | ||
1302 | * | ||
1303 | */ | ||
1304 | |||
1305 | int gfs2_quotad(void *data) | ||
1306 | { | ||
1307 | struct gfs2_sbd *sdp = data; | ||
1308 | struct gfs2_tune *tune = &sdp->sd_tune; | ||
1309 | unsigned long statfs_timeo = 0; | ||
1310 | unsigned long quotad_timeo = 0; | ||
1311 | unsigned long t = 0; | ||
1312 | DEFINE_WAIT(wait); | ||
1313 | |||
1314 | while (!kthread_should_stop()) { | ||
1315 | |||
1316 | /* Update the master statfs file */ | ||
1317 | quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t, | ||
1318 | &statfs_timeo, &tune->gt_statfs_quantum); | ||
1319 | |||
1320 | /* Update quota file */ | ||
1321 | quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t, | ||
1322 | "ad_timeo, &tune->gt_quota_quantum); | ||
1323 | |||
1324 | /* FIXME: This should be turned into a shrinker */ | ||
1325 | gfs2_quota_scan(sdp); | ||
1326 | |||
1327 | if (freezing(current)) | ||
1328 | refrigerator(); | ||
1329 | t = min(quotad_timeo, statfs_timeo); | ||
1330 | |||
1331 | prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_UNINTERRUPTIBLE); | ||
1332 | t -= schedule_timeout(t); | ||
1333 | finish_wait(&sdp->sd_quota_wait, &wait); | ||
1334 | } | ||
1335 | |||
1336 | return 0; | ||
1337 | } | ||
1338 | |||