aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--fs/gfs2/quota.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 931a133a5f96..4f2caa06ca93 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -891,7 +891,8 @@ static int gfs2_adjust_quota(struct gfs2_sbd *sdp, loff_t loc,
return err;
}
-static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda,
+ u64 sync_gen)
{
struct gfs2_sbd *sdp = (*qda)->qd_sbd;
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
@@ -982,8 +983,13 @@ out_dq:
gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC);
if (!error) {
- for (x = 0; x < num_qd; x++)
- qda[x]->qd_sync_gen = sdp->sd_quota_sync_gen;
+ for (x = 0; x < num_qd; x++) {
+ qd = qda[x];
+ spin_lock(&qd->qd_lockref.lock);
+ if (qd->qd_sync_gen < sync_gen)
+ qd->qd_sync_gen = sync_gen;
+ spin_unlock(&qd->qd_lockref.lock);
+ }
}
return error;
}
@@ -1177,7 +1183,9 @@ void gfs2_quota_unlock(struct gfs2_inode *ip)
}
if (count) {
- do_sync(count, qda);
+ u64 sync_gen = READ_ONCE(sdp->sd_quota_sync_gen);
+
+ do_sync(count, qda, sync_gen);
for (x = 0; x < count; x++)
qd_unlock(qda[x]);
}
@@ -1323,6 +1331,7 @@ int gfs2_quota_sync(struct super_block *sb, int type)
struct gfs2_sbd *sdp = sb->s_fs_info;
struct gfs2_quota_data **qda;
unsigned int max_qd = PAGE_SIZE / sizeof(struct gfs2_holder);
+ u64 sync_gen;
int error = 0;
if (sb_rdonly(sdp->sd_vfs))
@@ -1335,7 +1344,7 @@ int gfs2_quota_sync(struct super_block *sb, int type)
return -ENOMEM;
mutex_lock(&sdp->sd_quota_sync_mutex);
- sdp->sd_quota_sync_gen++;
+ sync_gen = sdp->sd_quota_sync_gen + 1;
do {
struct gfs2_quota_data *iter;
@@ -1344,7 +1353,7 @@ int gfs2_quota_sync(struct super_block *sb, int type)
spin_lock(&qd_lock);
list_for_each_entry(iter, &sdp->sd_quota_list, qd_list) {
- if (qd_grab_sync(sdp, iter, sdp->sd_quota_sync_gen)) {
+ if (qd_grab_sync(sdp, iter, sync_gen)) {
qda[num_qd++] = iter;
if (num_qd == max_qd)
break;
@@ -1365,8 +1374,10 @@ int gfs2_quota_sync(struct super_block *sb, int type)
break;
}
- if (!error)
- error = do_sync(num_qd, qda);
+ if (!error) {
+ WRITE_ONCE(sdp->sd_quota_sync_gen, sync_gen);
+ error = do_sync(num_qd, qda, sync_gen);
+ }
for (x = 0; x < num_qd; x++)
qd_unlock(qda[x]);