|
@@ -527,37 +527,70 @@ static void qdsb_put(struct gfs2_quota_data *qd)
|
|
qd_put(qd);
|
|
qd_put(qd);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * gfs2_qa_alloc - make sure we have a quota allocations data structure,
|
|
|
|
+ * if necessary
|
|
|
|
+ * @ip: the inode for this reservation
|
|
|
|
+ */
|
|
|
|
+int gfs2_qa_alloc(struct gfs2_inode *ip)
|
|
|
|
+{
|
|
|
|
+ int error = 0;
|
|
|
|
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
|
+
|
|
|
|
+ if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ down_write(&ip->i_rw_mutex);
|
|
|
|
+ if (ip->i_qadata == NULL) {
|
|
|
|
+ ip->i_qadata = kmem_cache_zalloc(gfs2_qadata_cachep, GFP_NOFS);
|
|
|
|
+ if (!ip->i_qadata)
|
|
|
|
+ error = -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ up_write(&ip->i_rw_mutex);
|
|
|
|
+ return error;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void gfs2_qa_delete(struct gfs2_inode *ip)
|
|
|
|
+{
|
|
|
|
+ down_write(&ip->i_rw_mutex);
|
|
|
|
+ if (ip->i_qadata) {
|
|
|
|
+ kmem_cache_free(gfs2_qadata_cachep, ip->i_qadata);
|
|
|
|
+ ip->i_qadata = NULL;
|
|
|
|
+ }
|
|
|
|
+ up_write(&ip->i_rw_mutex);
|
|
|
|
+}
|
|
|
|
+
|
|
int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
|
int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
|
{
|
|
{
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
struct gfs2_quota_data **qd;
|
|
struct gfs2_quota_data **qd;
|
|
int error;
|
|
int error;
|
|
|
|
|
|
- if (ip->i_res == NULL) {
|
|
|
|
- error = gfs2_rs_alloc(ip);
|
|
|
|
|
|
+ if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (ip->i_qadata == NULL) {
|
|
|
|
+ error = gfs2_rsqa_alloc(ip);
|
|
if (error)
|
|
if (error)
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
- qd = ip->i_res->rs_qa_qd;
|
|
|
|
|
|
+ qd = ip->i_qadata->qa_qd;
|
|
|
|
|
|
- if (gfs2_assert_warn(sdp, !ip->i_res->rs_qa_qd_num) ||
|
|
|
|
|
|
+ if (gfs2_assert_warn(sdp, !ip->i_qadata->qa_qd_num) ||
|
|
gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)))
|
|
gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)))
|
|
return -EIO;
|
|
return -EIO;
|
|
|
|
|
|
- if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
error = qdsb_get(sdp, make_kqid_uid(ip->i_inode.i_uid), qd);
|
|
error = qdsb_get(sdp, make_kqid_uid(ip->i_inode.i_uid), qd);
|
|
if (error)
|
|
if (error)
|
|
goto out;
|
|
goto out;
|
|
- ip->i_res->rs_qa_qd_num++;
|
|
|
|
|
|
+ ip->i_qadata->qa_qd_num++;
|
|
qd++;
|
|
qd++;
|
|
|
|
|
|
error = qdsb_get(sdp, make_kqid_gid(ip->i_inode.i_gid), qd);
|
|
error = qdsb_get(sdp, make_kqid_gid(ip->i_inode.i_gid), qd);
|
|
if (error)
|
|
if (error)
|
|
goto out;
|
|
goto out;
|
|
- ip->i_res->rs_qa_qd_num++;
|
|
|
|
|
|
+ ip->i_qadata->qa_qd_num++;
|
|
qd++;
|
|
qd++;
|
|
|
|
|
|
if (!uid_eq(uid, NO_UID_QUOTA_CHANGE) &&
|
|
if (!uid_eq(uid, NO_UID_QUOTA_CHANGE) &&
|
|
@@ -565,7 +598,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
|
error = qdsb_get(sdp, make_kqid_uid(uid), qd);
|
|
error = qdsb_get(sdp, make_kqid_uid(uid), qd);
|
|
if (error)
|
|
if (error)
|
|
goto out;
|
|
goto out;
|
|
- ip->i_res->rs_qa_qd_num++;
|
|
|
|
|
|
+ ip->i_qadata->qa_qd_num++;
|
|
qd++;
|
|
qd++;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -574,7 +607,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
|
error = qdsb_get(sdp, make_kqid_gid(gid), qd);
|
|
error = qdsb_get(sdp, make_kqid_gid(gid), qd);
|
|
if (error)
|
|
if (error)
|
|
goto out;
|
|
goto out;
|
|
- ip->i_res->rs_qa_qd_num++;
|
|
|
|
|
|
+ ip->i_qadata->qa_qd_num++;
|
|
qd++;
|
|
qd++;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -589,15 +622,15 @@ void gfs2_quota_unhold(struct gfs2_inode *ip)
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
unsigned int x;
|
|
unsigned int x;
|
|
|
|
|
|
- if (ip->i_res == NULL)
|
|
|
|
|
|
+ if (ip->i_qadata == NULL)
|
|
return;
|
|
return;
|
|
gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
|
|
gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
|
|
|
|
|
|
- for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
|
|
|
|
- qdsb_put(ip->i_res->rs_qa_qd[x]);
|
|
|
|
- ip->i_res->rs_qa_qd[x] = NULL;
|
|
|
|
|
|
+ for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
|
|
|
|
+ qdsb_put(ip->i_qadata->qa_qd[x]);
|
|
|
|
+ ip->i_qadata->qa_qd[x] = NULL;
|
|
}
|
|
}
|
|
- ip->i_res->rs_qa_qd_num = 0;
|
|
|
|
|
|
+ ip->i_qadata->qa_qd_num = 0;
|
|
}
|
|
}
|
|
|
|
|
|
static int sort_qd(const void *a, const void *b)
|
|
static int sort_qd(const void *a, const void *b)
|
|
@@ -843,7 +876,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
|
unsigned int nalloc = 0, blocks;
|
|
unsigned int nalloc = 0, blocks;
|
|
int error;
|
|
int error;
|
|
|
|
|
|
- error = gfs2_rs_alloc(ip);
|
|
|
|
|
|
+ error = gfs2_rsqa_alloc(ip);
|
|
if (error)
|
|
if (error)
|
|
return error;
|
|
return error;
|
|
|
|
|
|
@@ -1006,20 +1039,20 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
|
unsigned int x;
|
|
unsigned int x;
|
|
int error = 0;
|
|
int error = 0;
|
|
|
|
|
|
- error = gfs2_quota_hold(ip, uid, gid);
|
|
|
|
- if (error)
|
|
|
|
- return error;
|
|
|
|
-
|
|
|
|
if (capable(CAP_SYS_RESOURCE) ||
|
|
if (capable(CAP_SYS_RESOURCE) ||
|
|
sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
|
|
sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- sort(ip->i_res->rs_qa_qd, ip->i_res->rs_qa_qd_num,
|
|
|
|
|
|
+ error = gfs2_quota_hold(ip, uid, gid);
|
|
|
|
+ if (error)
|
|
|
|
+ return error;
|
|
|
|
+
|
|
|
|
+ sort(ip->i_qadata->qa_qd, ip->i_qadata->qa_qd_num,
|
|
sizeof(struct gfs2_quota_data *), sort_qd, NULL);
|
|
sizeof(struct gfs2_quota_data *), sort_qd, NULL);
|
|
|
|
|
|
- for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
|
|
|
|
- qd = ip->i_res->rs_qa_qd[x];
|
|
|
|
- error = do_glock(qd, NO_FORCE, &ip->i_res->rs_qa_qd_ghs[x]);
|
|
|
|
|
|
+ for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
|
|
|
|
+ qd = ip->i_qadata->qa_qd[x];
|
|
|
|
+ error = do_glock(qd, NO_FORCE, &ip->i_qadata->qa_qd_ghs[x]);
|
|
if (error)
|
|
if (error)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -1028,7 +1061,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
|
set_bit(GIF_QD_LOCKED, &ip->i_flags);
|
|
set_bit(GIF_QD_LOCKED, &ip->i_flags);
|
|
else {
|
|
else {
|
|
while (x--)
|
|
while (x--)
|
|
- gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]);
|
|
|
|
|
|
+ gfs2_glock_dq_uninit(&ip->i_qadata->qa_qd_ghs[x]);
|
|
gfs2_quota_unhold(ip);
|
|
gfs2_quota_unhold(ip);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1082,14 +1115,14 @@ void gfs2_quota_unlock(struct gfs2_inode *ip)
|
|
if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
|
|
if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
|
|
|
|
|
|
+ for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
|
|
struct gfs2_quota_data *qd;
|
|
struct gfs2_quota_data *qd;
|
|
int sync;
|
|
int sync;
|
|
|
|
|
|
- qd = ip->i_res->rs_qa_qd[x];
|
|
|
|
|
|
+ qd = ip->i_qadata->qa_qd[x];
|
|
sync = need_sync(qd);
|
|
sync = need_sync(qd);
|
|
|
|
|
|
- gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]);
|
|
|
|
|
|
+ gfs2_glock_dq_uninit(&ip->i_qadata->qa_qd_ghs[x]);
|
|
if (!sync)
|
|
if (!sync)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
@@ -1168,8 +1201,8 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
|
|
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
|
|
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
|
|
|
|
- qd = ip->i_res->rs_qa_qd[x];
|
|
|
|
|
|
+ for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
|
|
|
|
+ qd = ip->i_qadata->qa_qd[x];
|
|
|
|
|
|
if (!(qid_eq(qd->qd_id, make_kqid_uid(uid)) ||
|
|
if (!(qid_eq(qd->qd_id, make_kqid_uid(uid)) ||
|
|
qid_eq(qd->qd_id, make_kqid_gid(gid))))
|
|
qid_eq(qd->qd_id, make_kqid_gid(gid))))
|
|
@@ -1217,14 +1250,16 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
|
|
{
|
|
{
|
|
struct gfs2_quota_data *qd;
|
|
struct gfs2_quota_data *qd;
|
|
unsigned int x;
|
|
unsigned int x;
|
|
|
|
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
|
|
|
- if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
|
|
|
|
|
|
+ if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON ||
|
|
|
|
+ gfs2_assert_warn(sdp, change))
|
|
return;
|
|
return;
|
|
if (ip->i_diskflags & GFS2_DIF_SYSTEM)
|
|
if (ip->i_diskflags & GFS2_DIF_SYSTEM)
|
|
return;
|
|
return;
|
|
|
|
|
|
- for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
|
|
|
|
- qd = ip->i_res->rs_qa_qd[x];
|
|
|
|
|
|
+ for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
|
|
|
|
+ qd = ip->i_qadata->qa_qd[x];
|
|
|
|
|
|
if (qid_eq(qd->qd_id, make_kqid_uid(uid)) ||
|
|
if (qid_eq(qd->qd_id, make_kqid_uid(uid)) ||
|
|
qid_eq(qd->qd_id, make_kqid_gid(gid))) {
|
|
qid_eq(qd->qd_id, make_kqid_gid(gid))) {
|
|
@@ -1635,7 +1670,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
|
|
if (error)
|
|
if (error)
|
|
return error;
|
|
return error;
|
|
|
|
|
|
- error = gfs2_rs_alloc(ip);
|
|
|
|
|
|
+ error = gfs2_rsqa_alloc(ip);
|
|
if (error)
|
|
if (error)
|
|
goto out_put;
|
|
goto out_put;
|
|
|
|
|