aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/quota.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r--fs/gfs2/quota.c113
1 files changed, 103 insertions, 10 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 3e073f5144fa..b08d09696b3e 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
121fail: 123fail:
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;
@@ -1013,7 +1015,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
1013 1015
1014 if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change)) 1016 if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
1015 return; 1017 return;
1016 if (ip->i_di.di_flags & GFS2_DIF_SYSTEM) 1018 if (ip->i_diskflags & GFS2_DIF_SYSTEM)
1017 return; 1019 return;
1018 1020
1019 for (x = 0; x < al->al_qd_num; x++) { 1021 for (x = 0; x < al->al_qd_num; x++) {
@@ -1100,15 +1102,15 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *
1100int gfs2_quota_init(struct gfs2_sbd *sdp) 1102int gfs2_quota_init(struct gfs2_sbd *sdp)
1101{ 1103{
1102 struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); 1104 struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
1103 unsigned int blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift; 1105 unsigned int blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
1104 unsigned int x, slot = 0; 1106 unsigned int x, slot = 0;
1105 unsigned int found = 0; 1107 unsigned int found = 0;
1106 u64 dblock; 1108 u64 dblock;
1107 u32 extlen = 0; 1109 u32 extlen = 0;
1108 int error; 1110 int error;
1109 1111
1110 if (!ip->i_di.di_size || ip->i_di.di_size > (64 << 20) || 1112 if (!ip->i_disksize || ip->i_disksize > (64 << 20) ||
1111 ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) { 1113 ip->i_disksize & (sdp->sd_sb.sb_bsize - 1)) {
1112 gfs2_consist_inode(ip); 1114 gfs2_consist_inode(ip);
1113 return -EIO; 1115 return -EIO;
1114 } 1116 }
@@ -1195,7 +1197,7 @@ fail:
1195 return error; 1197 return error;
1196} 1198}
1197 1199
1198void gfs2_quota_scan(struct gfs2_sbd *sdp) 1200static 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,94 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
1272 } 1274 }
1273} 1275}
1274 1276
1277static 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
1285static 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
1299static void quotad_check_trunc_list(struct gfs2_sbd *sdp)
1300{
1301 struct gfs2_inode *ip;
1302
1303 while(1) {
1304 ip = NULL;
1305 spin_lock(&sdp->sd_trunc_lock);
1306 if (!list_empty(&sdp->sd_trunc_list)) {
1307 ip = list_entry(sdp->sd_trunc_list.next,
1308 struct gfs2_inode, i_trunc_list);
1309 list_del_init(&ip->i_trunc_list);
1310 }
1311 spin_unlock(&sdp->sd_trunc_lock);
1312 if (ip == NULL)
1313 return;
1314 gfs2_glock_finish_truncate(ip);
1315 }
1316}
1317
1318/**
1319 * gfs2_quotad - Write cached quota changes into the quota file
1320 * @sdp: Pointer to GFS2 superblock
1321 *
1322 */
1323
1324int gfs2_quotad(void *data)
1325{
1326 struct gfs2_sbd *sdp = data;
1327 struct gfs2_tune *tune = &sdp->sd_tune;
1328 unsigned long statfs_timeo = 0;
1329 unsigned long quotad_timeo = 0;
1330 unsigned long t = 0;
1331 DEFINE_WAIT(wait);
1332 int empty;
1333
1334 while (!kthread_should_stop()) {
1335
1336 /* Update the master statfs file */
1337 quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
1338 &statfs_timeo, &tune->gt_statfs_quantum);
1339
1340 /* Update quota file */
1341 quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
1342 &quotad_timeo, &tune->gt_quota_quantum);
1343
1344 /* FIXME: This should be turned into a shrinker */
1345 gfs2_quota_scan(sdp);
1346
1347 /* Check for & recover partially truncated inodes */
1348 quotad_check_trunc_list(sdp);
1349
1350 if (freezing(current))
1351 refrigerator();
1352 t = min(quotad_timeo, statfs_timeo);
1353
1354 prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_UNINTERRUPTIBLE);
1355 spin_lock(&sdp->sd_trunc_lock);
1356 empty = list_empty(&sdp->sd_trunc_list);
1357 spin_unlock(&sdp->sd_trunc_lock);
1358 if (empty)
1359 t -= schedule_timeout(t);
1360 else
1361 t = 0;
1362 finish_wait(&sdp->sd_quota_wait, &wait);
1363 }
1364
1365 return 0;
1366}
1367