aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2013-11-01 14:52:06 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2013-11-04 06:17:07 -0500
commit9b9f039d570bddc1653cda2e38f4331dcacfcde5 (patch)
tree216432682f87903da14562212eebf056e6ca0091 /fs/gfs2
parente66cf161098a634dc96e32d0089c5767cf25668a (diff)
GFS2: Use reflink for quota data cache
This patch adds reflink support to the quota data cache. It looks a bit strange because we still don't have a sensible split in the lookup by id and the lru list. That is coming in later patches though. The intent here is just to swap the current ref count for reflinks in all cases with as little as possible other change. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Signed-off-by: Abhijith Das <adas@redhat.com> Tested-by: Abhijith Das <adas@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/quota.c42
2 files changed, 29 insertions, 15 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index bb88e417231f..9d778044cc6e 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -422,7 +422,7 @@ struct gfs2_quota_data {
422 struct list_head qd_list; 422 struct list_head qd_list;
423 struct list_head qd_reclaim; 423 struct list_head qd_reclaim;
424 424
425 atomic_t qd_count; 425 struct lockref qd_lockref;
426 426
427 struct kqid qd_id; 427 struct kqid qd_id;
428 unsigned long qd_flags; /* QDF_... */ 428 unsigned long qd_flags; /* QDF_... */
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 4a9726aa191f..ed089118c171 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -50,6 +50,7 @@
50#include <linux/freezer.h> 50#include <linux/freezer.h>
51#include <linux/quota.h> 51#include <linux/quota.h>
52#include <linux/dqblk_xfs.h> 52#include <linux/dqblk_xfs.h>
53#include <linux/lockref.h>
53 54
54#include "gfs2.h" 55#include "gfs2.h"
55#include "incore.h" 56#include "incore.h"
@@ -148,7 +149,8 @@ static int qd_alloc(struct gfs2_sbd *sdp, struct kqid qid,
148 if (!qd) 149 if (!qd)
149 return -ENOMEM; 150 return -ENOMEM;
150 151
151 atomic_set(&qd->qd_count, 1); 152 qd->qd_lockref.count = 1;
153 spin_lock_init(&qd->qd_lockref.lock);
152 qd->qd_id = qid; 154 qd->qd_id = qid;
153 qd->qd_slot = -1; 155 qd->qd_slot = -1;
154 INIT_LIST_HEAD(&qd->qd_reclaim); 156 INIT_LIST_HEAD(&qd->qd_reclaim);
@@ -180,13 +182,12 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
180 spin_lock(&qd_lru_lock); 182 spin_lock(&qd_lru_lock);
181 list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) { 183 list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
182 if (qid_eq(qd->qd_id, qid)) { 184 if (qid_eq(qd->qd_id, qid)) {
183 if (!atomic_read(&qd->qd_count) && 185 lockref_get(&qd->qd_lockref);
184 !list_empty(&qd->qd_reclaim)) { 186 if (!list_empty(&qd->qd_reclaim)) {
185 /* Remove it from reclaim list */ 187 /* Remove it from reclaim list */
186 list_del_init(&qd->qd_reclaim); 188 list_del_init(&qd->qd_reclaim);
187 atomic_dec(&qd_lru_count); 189 atomic_dec(&qd_lru_count);
188 } 190 }
189 atomic_inc(&qd->qd_count);
190 found = 1; 191 found = 1;
191 break; 192 break;
192 } 193 }
@@ -222,18 +223,24 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
222static void qd_hold(struct gfs2_quota_data *qd) 223static void qd_hold(struct gfs2_quota_data *qd)
223{ 224{
224 struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; 225 struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
225 gfs2_assert(sdp, atomic_read(&qd->qd_count)); 226 gfs2_assert(sdp, !__lockref_is_dead(&qd->qd_lockref));
226 atomic_inc(&qd->qd_count); 227 lockref_get(&qd->qd_lockref);
227} 228}
228 229
229static void qd_put(struct gfs2_quota_data *qd) 230static void qd_put(struct gfs2_quota_data *qd)
230{ 231{
231 if (atomic_dec_and_lock(&qd->qd_count, &qd_lru_lock)) { 232 spin_lock(&qd_lru_lock);
233
234 if (!lockref_put_or_lock(&qd->qd_lockref)) {
235
232 /* Add to the reclaim list */ 236 /* Add to the reclaim list */
233 list_add_tail(&qd->qd_reclaim, &qd_lru_list); 237 list_add_tail(&qd->qd_reclaim, &qd_lru_list);
234 atomic_inc(&qd_lru_count); 238 atomic_inc(&qd_lru_count);
235 spin_unlock(&qd_lru_lock); 239
240 spin_unlock(&qd->qd_lockref.lock);
236 } 241 }
242
243 spin_unlock(&qd_lru_lock);
237} 244}
238 245
239static int slot_get(struct gfs2_quota_data *qd) 246static int slot_get(struct gfs2_quota_data *qd)
@@ -394,8 +401,8 @@ static int qd_check_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd,
394 list_move_tail(&qd->qd_list, &sdp->sd_quota_list); 401 list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
395 402
396 set_bit(QDF_LOCKED, &qd->qd_flags); 403 set_bit(QDF_LOCKED, &qd->qd_flags);
397 gfs2_assert_warn(sdp, atomic_read(&qd->qd_count)); 404 gfs2_assert_warn(sdp, !__lockref_is_dead(&qd->qd_lockref));
398 atomic_inc(&qd->qd_count); 405 lockref_get(&qd->qd_lockref);
399 qd->qd_change_sync = qd->qd_change; 406 qd->qd_change_sync = qd->qd_change;
400 gfs2_assert_warn(sdp, qd->qd_slot_count); 407 gfs2_assert_warn(sdp, qd->qd_slot_count);
401 qd->qd_slot_count++; 408 qd->qd_slot_count++;
@@ -1303,15 +1310,22 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
1303 while (!list_empty(head)) { 1310 while (!list_empty(head)) {
1304 qd = list_entry(head->prev, struct gfs2_quota_data, qd_list); 1311 qd = list_entry(head->prev, struct gfs2_quota_data, qd_list);
1305 1312
1306 if (atomic_read(&qd->qd_count) > 1 || 1313 /*
1307 (atomic_read(&qd->qd_count) && 1314 * To be removed in due course... we should be able to
1308 !test_bit(QDF_CHANGE, &qd->qd_flags))) { 1315 * ensure that all refs to the qd have done by this point
1316 * so that this rather odd test is not required
1317 */
1318 spin_lock(&qd->qd_lockref.lock);
1319 if (qd->qd_lockref.count > 1 ||
1320 (qd->qd_lockref.count && !test_bit(QDF_CHANGE, &qd->qd_flags))) {
1321 spin_unlock(&qd->qd_lockref.lock);
1309 list_move(&qd->qd_list, head); 1322 list_move(&qd->qd_list, head);
1310 spin_unlock(&qd_lru_lock); 1323 spin_unlock(&qd_lru_lock);
1311 schedule(); 1324 schedule();
1312 spin_lock(&qd_lru_lock); 1325 spin_lock(&qd_lru_lock);
1313 continue; 1326 continue;
1314 } 1327 }
1328 spin_unlock(&qd->qd_lockref.lock);
1315 1329
1316 list_del(&qd->qd_list); 1330 list_del(&qd->qd_list);
1317 /* Also remove if this qd exists in the reclaim list */ 1331 /* Also remove if this qd exists in the reclaim list */
@@ -1322,7 +1336,7 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
1322 atomic_dec(&sdp->sd_quota_count); 1336 atomic_dec(&sdp->sd_quota_count);
1323 spin_unlock(&qd_lru_lock); 1337 spin_unlock(&qd_lru_lock);
1324 1338
1325 if (!atomic_read(&qd->qd_count)) { 1339 if (!qd->qd_lockref.count) {
1326 gfs2_assert_warn(sdp, !qd->qd_change); 1340 gfs2_assert_warn(sdp, !qd->qd_change);
1327 gfs2_assert_warn(sdp, !qd->qd_slot_count); 1341 gfs2_assert_warn(sdp, !qd->qd_slot_count);
1328 } else 1342 } else