|
@@ -15,7 +15,7 @@
|
|
|
* fuzziness in the current usage value of IDs that are being used on different
|
|
|
* nodes in the cluster simultaneously. So, it is possible for a user on
|
|
|
* multiple nodes to overrun their quota, but that overrun is controlable.
|
|
|
- * Since quota tags are part of transactions, there is no need to a quota check
|
|
|
+ * Since quota tags are part of transactions, there is no need for a quota check
|
|
|
* program to be run on node crashes or anything like that.
|
|
|
*
|
|
|
* There are couple of knobs that let the administrator manage the quota
|
|
@@ -66,13 +66,6 @@
|
|
|
#define QUOTA_USER 1
|
|
|
#define QUOTA_GROUP 0
|
|
|
|
|
|
-struct gfs2_quota_host {
|
|
|
- u64 qu_limit;
|
|
|
- u64 qu_warn;
|
|
|
- s64 qu_value;
|
|
|
- u32 qu_ll_next;
|
|
|
-};
|
|
|
-
|
|
|
struct gfs2_quota_change_host {
|
|
|
u64 qc_change;
|
|
|
u32 qc_flags; /* GFS2_QCF_... */
|
|
@@ -618,33 +611,19 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
|
|
|
mutex_unlock(&sdp->sd_quota_mutex);
|
|
|
}
|
|
|
|
|
|
-static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
|
|
|
-{
|
|
|
- const struct gfs2_quota *str = buf;
|
|
|
-
|
|
|
- qu->qu_limit = be64_to_cpu(str->qu_limit);
|
|
|
- qu->qu_warn = be64_to_cpu(str->qu_warn);
|
|
|
- qu->qu_value = be64_to_cpu(str->qu_value);
|
|
|
- qu->qu_ll_next = be32_to_cpu(str->qu_ll_next);
|
|
|
-}
|
|
|
-
|
|
|
-static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf)
|
|
|
-{
|
|
|
- struct gfs2_quota *str = buf;
|
|
|
-
|
|
|
- str->qu_limit = cpu_to_be64(qu->qu_limit);
|
|
|
- str->qu_warn = cpu_to_be64(qu->qu_warn);
|
|
|
- str->qu_value = cpu_to_be64(qu->qu_value);
|
|
|
- str->qu_ll_next = cpu_to_be32(qu->qu_ll_next);
|
|
|
- memset(&str->qu_reserved, 0, sizeof(str->qu_reserved));
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
- * gfs2_adjust_quota
|
|
|
+ * gfs2_adjust_quota - adjust record of current block usage
|
|
|
+ * @ip: The quota inode
|
|
|
+ * @loc: Offset of the entry in the quota file
|
|
|
+ * @change: The amount of change to record
|
|
|
+ * @qd: The quota data
|
|
|
*
|
|
|
* This function was mostly borrowed from gfs2_block_truncate_page which was
|
|
|
* in turn mostly borrowed from ext3
|
|
|
+ *
|
|
|
+ * Returns: 0 or -ve on error
|
|
|
*/
|
|
|
+
|
|
|
static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
|
|
|
s64 change, struct gfs2_quota_data *qd)
|
|
|
{
|
|
@@ -656,8 +635,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
|
|
|
struct buffer_head *bh;
|
|
|
struct page *page;
|
|
|
void *kaddr;
|
|
|
- char *ptr;
|
|
|
- struct gfs2_quota_host qp;
|
|
|
+ struct gfs2_quota *qp;
|
|
|
s64 value;
|
|
|
int err = -EIO;
|
|
|
|
|
@@ -701,18 +679,13 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
|
|
|
gfs2_trans_add_bh(ip->i_gl, bh, 0);
|
|
|
|
|
|
kaddr = kmap_atomic(page, KM_USER0);
|
|
|
- ptr = kaddr + offset;
|
|
|
- gfs2_quota_in(&qp, ptr);
|
|
|
- qp.qu_value += change;
|
|
|
- value = qp.qu_value;
|
|
|
- gfs2_quota_out(&qp, ptr);
|
|
|
+ qp = kaddr + offset;
|
|
|
+ value = (s64)be64_to_cpu(qp->qu_value) + change;
|
|
|
+ qp->qu_value = cpu_to_be64(value);
|
|
|
+ qd->qd_qb.qb_value = qp->qu_value;
|
|
|
flush_dcache_page(page);
|
|
|
kunmap_atomic(kaddr, KM_USER0);
|
|
|
err = 0;
|
|
|
- qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC);
|
|
|
- qd->qd_qb.qb_value = cpu_to_be64(value);
|
|
|
- ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC);
|
|
|
- ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value);
|
|
|
unlock:
|
|
|
unlock_page(page);
|
|
|
page_cache_release(page);
|
|
@@ -741,8 +714,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
|
|
|
|
|
sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL);
|
|
|
for (qx = 0; qx < num_qd; qx++) {
|
|
|
- error = gfs2_glock_nq_init(qda[qx]->qd_gl,
|
|
|
- LM_ST_EXCLUSIVE,
|
|
|
+ error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE,
|
|
|
GL_NOCACHE, &ghs[qx]);
|
|
|
if (error)
|
|
|
goto out;
|
|
@@ -797,8 +769,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
|
|
qd = qda[x];
|
|
|
offset = qd2offset(qd);
|
|
|
error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync,
|
|
|
- (struct gfs2_quota_data *)
|
|
|
- qd);
|
|
|
+ (struct gfs2_quota_data *)qd);
|
|
|
if (error)
|
|
|
goto out_end_trans;
|
|
|
|
|
@@ -829,8 +800,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
|
|
|
struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
|
|
|
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
|
|
|
struct gfs2_holder i_gh;
|
|
|
- struct gfs2_quota_host q;
|
|
|
- char buf[sizeof(struct gfs2_quota)];
|
|
|
+ struct gfs2_quota q;
|
|
|
int error;
|
|
|
struct gfs2_quota_lvb *qlvb;
|
|
|
|
|
@@ -853,22 +823,23 @@ restart:
|
|
|
if (error)
|
|
|
goto fail;
|
|
|
|
|
|
- memset(buf, 0, sizeof(struct gfs2_quota));
|
|
|
+ memset(&q, 0, sizeof(struct gfs2_quota));
|
|
|
pos = qd2offset(qd);
|
|
|
- error = gfs2_internal_read(ip, NULL, buf, &pos,
|
|
|
- sizeof(struct gfs2_quota));
|
|
|
+ error = gfs2_internal_read(ip, NULL, (char *)&q, &pos, sizeof(q));
|
|
|
if (error < 0)
|
|
|
goto fail_gunlock;
|
|
|
-
|
|
|
+ if ((error < sizeof(q)) && force_refresh) {
|
|
|
+ error = -ENOENT;
|
|
|
+ goto fail_gunlock;
|
|
|
+ }
|
|
|
gfs2_glock_dq_uninit(&i_gh);
|
|
|
|
|
|
- gfs2_quota_in(&q, buf);
|
|
|
qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
|
|
|
qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC);
|
|
|
qlvb->__pad = 0;
|
|
|
- qlvb->qb_limit = cpu_to_be64(q.qu_limit);
|
|
|
- qlvb->qb_warn = cpu_to_be64(q.qu_warn);
|
|
|
- qlvb->qb_value = cpu_to_be64(q.qu_value);
|
|
|
+ qlvb->qb_limit = q.qu_limit;
|
|
|
+ qlvb->qb_warn = q.qu_warn;
|
|
|
+ qlvb->qb_value = q.qu_value;
|
|
|
qd->qd_qb = *qlvb;
|
|
|
|
|
|
gfs2_glock_dq_uninit(q_gh);
|
|
@@ -1126,7 +1097,6 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
|
|
|
gfs2_glock_dq_uninit(&q_gh);
|
|
|
|
|
|
qd_put(qd);
|
|
|
-
|
|
|
return error;
|
|
|
}
|
|
|
|