Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e72c0f7 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

GFS2: Clean up gfs2_adjust_quota() and do_glock()



Both of these functions contained confusing and in one case
duplicate code. This patch adds a new check in do_glock()
so that we report -ENOENT if we are asked to sync a quota
entry which doesn't exist. Due to the previous patch this is
now reported correctly to userspace.

Also there are a few new comments, and I hope that the code
is easier to understand now.

Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 6a6ada81
Loading
Loading
Loading
Loading
+26 −56
Original line number Diff line number Diff line
@@ -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;
}