public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Mark Fasheh <mfasheh@suse.com>
Cc: linux-kernel@vger.kernel.org, ocfs2-devel@oss.oracle.com,
	joel.becker@oracle.com, jack@suse.cz, mfasheh@suse.com
Subject: Re: [PATCH 23/56] ocfs2: Implementation of local and global quota file handling
Date: Mon, 22 Dec 2008 16:11:38 -0800	[thread overview]
Message-ID: <20081222161138.779cbffa.akpm@linux-foundation.org> (raw)
In-Reply-To: <1229982517-3455-24-git-send-email-mfasheh@suse.com>

On Mon, 22 Dec 2008 13:48:04 -0800
Mark Fasheh <mfasheh@suse.com> wrote:

> From: Jan Kara <jack@suse.cz>
> 
> For each quota type each node has local quota file. In this file it stores
> changes users have made to disk usage via this node. Once in a while this
> information is synced to global file (and thus with other nodes) so that
> limits enforcement at least aproximately works.
> 
> Global quota files contain all the information about usage and limits. It's
> mostly handled by the generic VFS code (which implements a trie of structures
> inside a quota file). We only have to provide functions to convert structures
> from on-disk format to in-memory one. We also have to provide wrappers for
> various quota functions starting transactions and acquiring necessary cluster
> locks before the actual IO is really started.
> 
> +static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
> +{
> +	struct ocfs2_qinfo_lvb *lvb;
> +	struct ocfs2_mem_dqinfo *oinfo = ocfs2_lock_res_qinfo(lockres);
> +	struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
> +					    oinfo->dqi_gi.dqi_type);
> +
> +	mlog_entry_void();
> +
> +	lvb = (struct ocfs2_qinfo_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);

Unneeded cast.

> +	lvb->lvb_version = OCFS2_QINFO_LVB_VERSION;
> +	lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
> +	lvb->lvb_igrace = cpu_to_be32(info->dqi_igrace);
> +	lvb->lvb_syncms = cpu_to_be32(oinfo->dqi_syncms);
> +	lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
> +	lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
> +	lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
> +
> +	mlog_exit_void();
> +}
> +
> +void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
> +{
> +	struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
> +	struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
> +	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
> +
> +	mlog_entry_void();
> +	if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
> +		ocfs2_cluster_unlock(osb, lockres, level);
> +	mlog_exit_void();
> +}
> +
> +static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
> +{
> +	struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
> +					    oinfo->dqi_gi.dqi_type);
> +	struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
> +	struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);

yeah, like that ;)

> +	struct buffer_head *bh;
> +	struct ocfs2_global_disk_dqinfo *gdinfo;
> +	int status = 0;
> +
> +	if (lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
> +		info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
> +		info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
> +		oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
> +		oinfo->dqi_gi.dqi_blocks = be32_to_cpu(lvb->lvb_blocks);
> +		oinfo->dqi_gi.dqi_free_blk = be32_to_cpu(lvb->lvb_free_blk);
> +		oinfo->dqi_gi.dqi_free_entry =
> +					be32_to_cpu(lvb->lvb_free_entry);
> +	} else {
> +		bh = ocfs2_read_quota_block(oinfo->dqi_gqinode, 0, &status);
> +		if (!bh) {
> +			mlog_errno(status);
> +			goto bail;
> +		}
> +		gdinfo = (struct ocfs2_global_disk_dqinfo *)
> +					(bh->b_data + OCFS2_GLOBAL_INFO_OFF);
> +		info->dqi_bgrace = le32_to_cpu(gdinfo->dqi_bgrace);
> +		info->dqi_igrace = le32_to_cpu(gdinfo->dqi_igrace);
> +		oinfo->dqi_syncms = le32_to_cpu(gdinfo->dqi_syncms);
> +		oinfo->dqi_gi.dqi_blocks = le32_to_cpu(gdinfo->dqi_blocks);
> +		oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(gdinfo->dqi_free_blk);
> +		oinfo->dqi_gi.dqi_free_entry =
> +					le32_to_cpu(gdinfo->dqi_free_entry);
> +		brelse(bh);

put_bh() is more efficient and modern, in the case where bh is known to
not be NULL.

> +		ocfs2_track_lock_refresh(lockres);
> +	}
> +
> +bail:
> +	return status;
> +}
> +
> +/* Lock quota info, this function expects at least shared lock on the quota file
> + * so that we can safely refresh quota info from disk. */
> +int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
> +{
> +	struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
> +	struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
> +	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
> +	int status = 0;
> +
> +	mlog_entry_void();
> +
> +	/* On RO devices, locking really isn't needed... */
> +	if (ocfs2_is_hard_readonly(osb)) {
> +		if (ex)
> +			status = -EROFS;
> +		goto bail;
> +	}
> +	if (ocfs2_mount_local(osb))
> +		goto bail;

This is not an error case?

> +
> +	status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
> +	if (status < 0) {
> +		mlog_errno(status);
> +		goto bail;
> +	}
> +	if (!ocfs2_should_refresh_lock_res(lockres))
> +		goto bail;

ditto?

> +	/* OK, we have the lock but we need to refresh the quota info */
> +	status = ocfs2_refresh_qinfo(oinfo);
> +	if (status)
> +		ocfs2_qinfo_unlock(oinfo, ex);
> +	ocfs2_complete_lock_res_refresh(lockres, status);
> +bail:
> +	mlog_exit(status);
> +	return status;
> +}
> +
>
> ...
>
> +ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
> +			 size_t len, loff_t off)
> +{
> +	struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
> +	struct inode *gqinode = oinfo->dqi_gqinode;
> +	loff_t i_size = i_size_read(gqinode);
> +	int offset = off & (sb->s_blocksize - 1);
> +	sector_t blk = off >> sb->s_blocksize_bits;
> +	int err = 0;
> +	struct buffer_head *bh;
> +	size_t toread, tocopy;
> +
> +	if (off > i_size)
> +		return 0;
> +	if (off + len > i_size)
> +		len = i_size - off;
> +	toread = len;
> +	while (toread > 0) {
> +		tocopy = min((size_t)(sb->s_blocksize - offset), toread);

min_t is preferred.

> +		bh = ocfs2_read_quota_block(gqinode, blk, &err);
> +		if (!bh) {
> +			mlog_errno(err);
> +			return err;
> +		}
> +		memcpy(data, bh->b_data + offset, tocopy);
> +		brelse(bh);
> +		offset = 0;
> +		toread -= tocopy;
> +		data += tocopy;
> +		blk++;
> +	}
> +	return len;
> +}
> +
> +/* Write to quotafile (we know the transaction is already started and has
> + * enough credits) */
> +ssize_t ocfs2_quota_write(struct super_block *sb, int type,
> +			  const char *data, size_t len, loff_t off)
> +{
> +	struct mem_dqinfo *info = sb_dqinfo(sb, type);
> +	struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
> +	struct inode *gqinode = oinfo->dqi_gqinode;
> +	int offset = off & (sb->s_blocksize - 1);
> +	sector_t blk = off >> sb->s_blocksize_bits;

does ocfs2 attempt to support CONFIG_LBD=n?

> +	int err = 0, new = 0;
> +	struct buffer_head *bh;
> +	handle_t *handle = journal_current_handle();
> +
>
> ...
>
> +	lock_buffer(bh);
> +	if (new)
> +		memset(bh->b_data, 0, sb->s_blocksize);
> +	memcpy(bh->b_data + offset, data, len);
> +	flush_dcache_page(bh->b_page);
> +	unlock_buffer(bh);
> +	ocfs2_set_buffer_uptodate(gqinode, bh);
> +	err = ocfs2_journal_dirty(handle, bh);
> +	brelse(bh);

lots of put_bh()'s

> +	if (err < 0)
> +		goto out;
> +out:
> +	if (err) {
> +		mutex_unlock(&gqinode->i_mutex);
> +		mlog_errno(err);
> +		return err;
> +	}
> +	gqinode->i_version++;
> +	ocfs2_mark_inode_dirty(handle, gqinode, oinfo->dqi_gqi_bh);
> +	mutex_unlock(&gqinode->i_mutex);
> +	return len;
> +}
> +
>
> ...
>

gee, what a lot of code.

  reply	other threads:[~2008-12-23  0:12 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-22 21:47 [git patches] Ocfs2 patches for merge window, batch 2/3 Mark Fasheh
2008-12-22 21:47 ` [PATCH 01/56] quota: Add callbacks for allocating and destroying dquot structures Mark Fasheh
2008-12-22 21:47 ` [PATCH 02/56] quota: Increase size of variables for limits and inode usage Mark Fasheh
2008-12-22 21:47 ` [PATCH 03/56] quota: Remove bogus 'optimization' in check_idq() and check_bdq() Mark Fasheh
2008-12-22 21:47 ` [PATCH 04/56] quota: Make _SUSPENDED just a flag Mark Fasheh
2008-12-22 21:47 ` [PATCH 05/56] quota: Allow to separately enable quota accounting and enforcing limits Mark Fasheh
2008-12-22 21:47 ` [PATCH 06/56] ext3: Use sb_any_quota_loaded() instead of sb_any_quota_enabled() Mark Fasheh
2008-12-22 21:47 ` [PATCH 07/56] ext4: " Mark Fasheh
2008-12-22 21:47 ` [PATCH 08/56] reiserfs: " Mark Fasheh
2008-12-22 21:47 ` [PATCH 09/56] quota: Remove compatibility function sb_any_quota_enabled() Mark Fasheh
2008-12-22 21:47 ` [PATCH 10/56] quota: Introduce DQUOT_QUOTA_SYS_FILE flag Mark Fasheh
2008-12-22 21:47 ` [PATCH 11/56] quota: Move quotaio_v[12].h from include/linux/ to fs/ Mark Fasheh
2008-12-22 21:47 ` [PATCH 12/56] quota: Split off quota tree handling into a separate file Mark Fasheh
2008-12-22 21:47 ` [PATCH 13/56] quota: Convert union in mem_dqinfo to a pointer Mark Fasheh
2008-12-22 21:47 ` [PATCH 14/56] quota: Allow negative usage of space and inodes Mark Fasheh
2008-12-22 21:47 ` [PATCH 15/56] quota: Keep which entries were set by SETQUOTA quotactl Mark Fasheh
2008-12-22 21:47 ` [PATCH 16/56] quota: Update version number Mark Fasheh
2008-12-22 21:47 ` [PATCH 17/56] quota: Add helpers to allow ocfs2 specific quota initialization, freeing and recovery Mark Fasheh
2008-12-22 21:47 ` [PATCH 18/56] quota: Implement function for scanning active dquots Mark Fasheh
2008-12-22 21:48 ` [PATCH 19/56] mm: Export pdflush_operation() Mark Fasheh
2008-12-23  0:01   ` Andrew Morton
2008-12-25  1:05     ` Mark Fasheh
2008-12-31 19:28       ` Mark Fasheh
2008-12-31 22:17         ` Joel Becker
2008-12-31 23:09           ` [Ocfs2-devel] " Mark Fasheh
2009-01-05 13:27             ` Jan Kara
2008-12-22 21:48 ` [PATCH 20/56] ocfs2: Support nested transactions Mark Fasheh
2008-12-22 21:48 ` [PATCH 21/56] ocfs2: Assign feature bits and system inodes to quota feature and quota files Mark Fasheh
2008-12-22 21:48 ` [PATCH 22/56] ocfs2: Mark system files as not subject to quota accounting Mark Fasheh
2008-12-22 21:48 ` [PATCH 23/56] ocfs2: Implementation of local and global quota file handling Mark Fasheh
2008-12-23  0:11   ` Andrew Morton [this message]
2008-12-25  0:29     ` Mark Fasheh
2008-12-26  2:29       ` Andrew Morton
2008-12-22 21:48 ` [PATCH 24/56] ocfs2: Add quota calls for allocation and freeing of inodes and space Mark Fasheh
2008-12-22 21:48 ` [PATCH 25/56] ocfs2: Implement quota syncing thread Mark Fasheh
2008-12-22 21:48 ` [PATCH 26/56] ocfs2: Implement quota recovery Mark Fasheh
2008-12-22 21:48 ` [PATCH 27/56] ocfs2: Enable quota accounting on mount, disable on umount Mark Fasheh
2008-12-22 21:48 ` [PATCH 28/56] jbd2: Add BH_JBDPrivateStart Mark Fasheh
2008-12-22 21:48 ` [PATCH 29/56] ocfs2: Use BH_JBDPrivateStart instead of BH_Unshadow Mark Fasheh
2008-12-22 21:48 ` [PATCH 30/56] ocfs2: Add missing initialization Mark Fasheh
2008-12-22 21:48 ` [PATCH 31/56] ocfs2: Fix ocfs2_read_quota_block() error handling Mark Fasheh
2008-12-22 21:48 ` [PATCH 32/56] ocfs2: Fix oops when extending quota files Mark Fasheh
2008-12-22 21:48 ` [PATCH 33/56] ocfs2: Make ocfs2_get_quota_block() consistent with ocfs2_read_quota_block() Mark Fasheh
2008-12-22 21:48 ` [PATCH 34/56] ocfs2: Fix build warnings (64-bit types vs long long) Mark Fasheh
2008-12-22 21:48 ` [PATCH 35/56] quota: Unexport dqblk_v1.h and dqblk_v2.h Mark Fasheh
2008-12-22 21:48 ` [PATCH 36/56] quota: Export dquot_alloc() and dquot_destroy() functions Mark Fasheh
2008-12-22 21:48 ` [PATCH 37/56] reiserfs: Add default allocation routines for quota structures Mark Fasheh
2008-12-22 21:48 ` [PATCH 38/56] ext3: " Mark Fasheh
2008-12-22 21:48 ` [PATCH 39/56] ext4: " Mark Fasheh
2008-12-22 21:48 ` [PATCH 40/56] ocfs2: fix indendation in ocfs2_dquot_drop_slow Mark Fasheh
2008-12-22 21:48 ` [PATCH 41/56] ocfs2/quota: sparse fixes for quota Mark Fasheh
2008-12-22 21:48 ` [PATCH 42/56] ocfs2: Dirty the entire bucket in ocfs2_bucket_value_truncate() Mark Fasheh
2008-12-22 21:48 ` [PATCH 43/56] ocfs2: Narrow the transaction for deleting xattrs from a bucket Mark Fasheh
2008-12-22 21:48 ` [PATCH 44/56] ocfs2: Dirty the entire first bucket in ocfs2_extend_xattr_bucket() Mark Fasheh
2008-12-22 21:48 ` [PATCH 45/56] ocfs2: Dirty the entire first bucket in ocfs2_cp_xattr_cluster() Mark Fasheh
2008-12-22 21:48 ` [PATCH 46/56] ocfs2: Explain t_is_new " Mark Fasheh
2008-12-22 21:48 ` [PATCH 47/56] ocfs2: Use ocfs2_cp_xattr_bucket() in ocfs2_mv_xattr_bucket_cross_cluster() Mark Fasheh
2008-12-22 21:48 ` [PATCH 48/56] ocfs2: Rename ocfs2_cp_xattr_cluster() to ocfs2_mv_xattr_buckets() Mark Fasheh
2008-12-22 21:48 ` [PATCH 49/56] ocfs2: ocfs2_mv_xattr_buckets() can handle a partial cluster now Mark Fasheh
2008-12-22 21:48 ` [PATCH 50/56] ocfs2: Use ocfs2_mv_xattr_buckets() in ocfs2_mv_xattr_bucket_cross_cluster() Mark Fasheh
2008-12-22 21:48 ` [PATCH 51/56] ocfs2: Start using buckets in ocfs2_adjust_xattr_cross_cluster() Mark Fasheh
2008-12-22 21:48 ` [PATCH 52/56] ocfs2: Pass buckets into ocfs2_mv_xattr_bucket_cross_cluster() Mark Fasheh
2008-12-22 21:48 ` [PATCH 53/56] ocfs2: Move buckets up into ocfs2_add_new_xattr_cluster() Mark Fasheh
2008-12-22 21:48 ` [PATCH 54/56] ocfs2: Move buckets up into ocfs2_add_new_xattr_bucket() Mark Fasheh
2008-12-22 21:48 ` [PATCH 55/56] ocfs2: Pass xs->bucket " Mark Fasheh
2008-12-22 21:48 ` [PATCH 56/56] ocfs2/quota: Add QUOTA in mlog_attribute Mark Fasheh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081222161138.779cbffa.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=jack@suse.cz \
    --cc=joel.becker@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mfasheh@suse.com \
    --cc=ocfs2-devel@oss.oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox