diff options
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r-- | fs/gfs2/quota.c | 59 |
1 files changed, 25 insertions, 34 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 299b6d6aaa79..c537e1d02cf3 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -446,47 +446,29 @@ static void bh_put(struct gfs2_quota_data *qd) mutex_unlock(&sdp->sd_quota_mutex); } -static int qd_check_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd, - u64 *sync_gen) +static bool qd_grab_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd, + u64 sync_gen) { if (test_bit(QDF_LOCKED, &qd->qd_flags) || !test_bit(QDF_CHANGE, &qd->qd_flags) || - (sync_gen && (qd->qd_sync_gen >= *sync_gen))) - return 0; - - /* - * If qd_change is 0 it means a pending quota change was negated. - * We should not sync it, but we still have a qd reference and slot - * reference taken by gfs2_quota_change -> do_qc that need to be put. - */ - if (!qd->qd_change && test_and_clear_bit(QDF_CHANGE, &qd->qd_flags)) { - slot_put(qd); - qd_put(qd); - return 0; - } + qd->qd_sync_gen >= sync_gen) + return false; if (!lockref_get_not_dead(&qd->qd_lockref)) - return 0; + return false; list_move_tail(&qd->qd_list, &sdp->sd_quota_list); set_bit(QDF_LOCKED, &qd->qd_flags); qd->qd_change_sync = qd->qd_change; slot_hold(qd); - return 1; + return true; } -static int qd_bh_get_or_undo(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd) +static void qd_ungrab_sync(struct gfs2_quota_data *qd) { - int error; - - error = bh_get(qd); - if (!error) - return 0; - clear_bit(QDF_LOCKED, &qd->qd_flags); slot_put(qd); qd_put(qd); - return error; } static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) @@ -502,7 +484,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) spin_lock(&qd_lock); list_for_each_entry(iter, &sdp->sd_quota_list, qd_list) { - if (qd_check_sync(sdp, iter, &sdp->sd_quota_sync_gen)) { + if (qd_grab_sync(sdp, iter, sdp->sd_quota_sync_gen)) { qd = iter; break; } @@ -511,12 +493,15 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) spin_unlock(&qd_lock); if (qd) { - error = qd_bh_get_or_undo(sdp, qd); - if (error) + error = bh_get(qd); + if (error) { + qd_ungrab_sync(qd); return error; - *qdp = qd; + } } + *qdp = qd; + return 0; } @@ -1148,7 +1133,6 @@ void gfs2_quota_unlock(struct gfs2_inode *ip) struct gfs2_quota_data *qda[2 * GFS2_MAXQUOTAS]; unsigned int count = 0; u32 x; - int found; if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags)) return; @@ -1156,6 +1140,7 @@ void gfs2_quota_unlock(struct gfs2_inode *ip) for (x = 0; x < ip->i_qadata->qa_qd_num; x++) { struct gfs2_quota_data *qd; bool sync; + int error; qd = ip->i_qadata->qa_qd[x]; sync = need_sync(qd); @@ -1165,14 +1150,20 @@ void gfs2_quota_unlock(struct gfs2_inode *ip) continue; spin_lock(&qd_lock); - found = qd_check_sync(sdp, qd, NULL); + sync = qd_grab_sync(sdp, qd, U64_MAX); spin_unlock(&qd_lock); - if (!found) + if (!sync) + continue; + + gfs2_assert_warn(sdp, qd->qd_change_sync); + error = bh_get(qd); + if (error) { + qd_ungrab_sync(qd); continue; + } - if (!qd_bh_get_or_undo(sdp, qd)) - qda[count++] = qd; + qda[count++] = qd; } if (count) { |