From: Jan Kara <jack@suse.cz>
To: Dmitry Monakhov <dmonakhov@openvz.org>
Cc: linux-fsdevel@vger.kernel.org, jack@suse.cz, hch@infradead.org,
Dmitry Monakhov <dmonakhov@gmail.com>
Subject: Re: [PATCH 09/11] quota: protect dquot mem info with objects's lock
Date: Wed, 6 Oct 2010 15:30:18 +0200 [thread overview]
Message-ID: <20101006133018.GM3676@quack.suse.cz> (raw)
In-Reply-To: <1286302827-31043-10-git-send-email-dmonakhov@gmail.com>
On Tue 05-10-10 22:20:25, Dmitry Monakhov wrote:
> @@ -1762,14 +1810,16 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
> return 0;
> }
> spin_lock(&sb_dqopt(inode->i_sb)->dq_data_lock);
> + inode_dquot_lock(inode, transfer_from);
> cur_space = inode_get_bytes(inode);
> rsv_space = inode_get_rsv_space(inode);
> space = cur_space + rsv_space;
> + dquot_lock_all(transfer_to);
One more problem I've spotted - here you cannot lock new and old dquot
structures in an arbitrary order as that would lead to deadlocks when two
dquot_transfers run in parallel. So you have to establish some ordering and
follow that while locking...
Honza
> /* Build the transfer_from list and check the limits */
> +
> for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
> if (!transfer_to[cnt])
> continue;
> - transfer_from[cnt] = inode->i_dquot[cnt];
> ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt);
> if (ret)
> goto over_quota;
> @@ -1806,6 +1856,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
>
> inode->i_dquot[cnt] = transfer_to[cnt];
> }
> + dquot_unlock_all(transfer_to);
> + dquot_unlock_all(transfer_from);
> spin_unlock(&sb_dqopt(inode->i_sb)->dq_data_lock);
> up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
>
> @@ -1820,6 +1872,8 @@ warn:
> flush_warnings(transfer_from, warntype_from_space);
> return ret;
> over_quota:
> + dquot_unlock_all(transfer_to);
> + dquot_unlock_all(transfer_from);
> spin_unlock(&sb_dqopt(inode->i_sb)->dq_data_lock);
> up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
> goto warn;
> @@ -2363,6 +2417,7 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
> di->d_id = dquot->dq_id;
>
> spin_lock(&dq_opt(dquot)->dq_data_lock);
> + spin_lock(&dquot->dq_lock);
> di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit);
> di->d_blk_softlimit = stoqb(dm->dqb_bsoftlimit);
> di->d_ino_hardlimit = dm->dqb_ihardlimit;
> @@ -2371,6 +2426,7 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
> di->d_icount = dm->dqb_curinodes;
> di->d_btimer = dm->dqb_btime;
> di->d_itimer = dm->dqb_itime;
> + spin_unlock(&dquot->dq_lock);
> spin_unlock(&dq_opt(dquot)->dq_data_lock);
> }
>
> @@ -2415,6 +2471,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
> return -ERANGE;
>
> spin_lock(&dq_opt(dquot)->dq_data_lock);
> + spin_lock(&dquot->dq_lock);
> if (di->d_fieldmask & FS_DQ_BCOUNT) {
> dm->dqb_curspace = di->d_bcount - dm->dqb_rsvspace;
> check_blim = 1;
> @@ -2480,6 +2537,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
> clear_bit(DQ_FAKE_B, &dquot->dq_flags);
> else
> set_bit(DQ_FAKE_B, &dquot->dq_flags);
> + spin_unlock(&dquot->dq_lock);
> spin_unlock(&dq_opt(dquot)->dq_data_lock);
> mark_dquot_dirty(dquot);
>
> diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c
> index 8b04f24..1643c30 100644
> --- a/fs/quota/quota_tree.c
> +++ b/fs/quota/quota_tree.c
> @@ -376,7 +376,9 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
> }
> }
> spin_lock(&sb_dqopt(sb)->dq_data_lock);
> + spin_lock(&dquot->dq_lock);
> info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
> + spin_unlock(&dquot->dq_lock);
> spin_unlock(&sb_dqopt(sb)->dq_data_lock);
> ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size,
> dquot->dq_off);
> @@ -632,12 +634,14 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
> goto out;
> }
> spin_lock(&sb_dqopt(sb)->dq_data_lock);
> + spin_lock(&dquot->dq_lock);
> info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
> if (!dquot->dq_dqb.dqb_bhardlimit &&
> !dquot->dq_dqb.dqb_bsoftlimit &&
> !dquot->dq_dqb.dqb_ihardlimit &&
> !dquot->dq_dqb.dqb_isoftlimit)
> set_bit(DQ_FAKE_B, &dquot->dq_flags);
> + spin_unlock(&dquot->dq_lock);
> spin_unlock(&sb_dqopt(sb)->dq_data_lock);
> kfree(ddquot);
> out:
> diff --git a/include/linux/quota.h b/include/linux/quota.h
> index 9e7a102..197660f 100644
> --- a/include/linux/quota.h
> +++ b/include/linux/quota.h
> @@ -294,6 +294,7 @@ struct dquot {
> unsigned long dq_flags; /* See DQ_* */
> short dq_type; /* Type of quota */
> struct mem_dqblk dq_dqb; /* Diskquota usage */
> + spinlock_t dq_lock; /* protect in mem_dqblk */
> };
>
> /* Operations which must be implemented by each quota format */
> --
> 1.6.6.1
>
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
next prev parent reply other threads:[~2010-10-06 13:31 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-05 18:20 (unknown), Dmitry Monakhov
2010-10-05 18:20 ` [PATCH 01/11] quota: add wrapper function Dmitry Monakhov
2010-10-06 8:56 ` Christoph Hellwig
2010-10-06 10:01 ` Jan Kara
2010-10-05 18:20 ` [PATCH 02/11] quota: Convert dq_state_lock to per-sb dq_state_lock Dmitry Monakhov
2010-10-06 10:04 ` Jan Kara
2010-10-05 18:20 ` [PATCH 03/11] quota: add quota format lock Dmitry Monakhov
2010-10-06 10:05 ` Jan Kara
2010-10-05 18:20 ` [PATCH 04/11] quota: make dquot lists per-sb Dmitry Monakhov
2010-10-06 8:57 ` Christoph Hellwig
2010-10-06 9:39 ` Dmitry
2010-10-06 10:22 ` Jan Kara
2010-10-06 10:40 ` Dmitry
2010-10-06 10:54 ` Jan Kara
2010-10-05 18:20 ` [PATCH 05/11] quota: make per-sb hash array Dmitry Monakhov
2010-10-06 10:38 ` Jan Kara
2010-10-05 18:20 ` [PATCH 06/11] quota: remove global dq_list_lock Dmitry Monakhov
2010-10-05 18:20 ` [PATCH 07/11] quota: rename dq_lock Dmitry Monakhov
2010-10-05 18:20 ` [PATCH 08/11] quota: make per-sb dq_data_lock Dmitry Monakhov
2010-10-06 11:01 ` Jan Kara
2010-10-05 18:20 ` [PATCH 09/11] quota: protect dquot mem info with objects's lock Dmitry Monakhov
2010-10-06 12:37 ` Jan Kara
2010-10-06 13:17 ` Dmitry
2010-10-06 13:41 ` Jan Kara
2010-10-06 14:19 ` Dmitry
2010-10-06 13:30 ` Jan Kara [this message]
2010-10-06 13:41 ` Dmitry
2010-10-05 18:20 ` [PATCH 10/11] quota: drop dq_data_lock where possible Dmitry Monakhov
2010-10-05 18:20 ` [PATCH 11/11] quota: relax dq_data_lock dq_lock locking consistency Dmitry Monakhov
2010-10-06 11:56 ` Jan Kara
2010-10-06 7:08 ` [PATCH 0/11] RFC quota scalability V1 Dmitry
2010-10-06 9:44 ` Jan Kara
2010-10-06 10:15 ` Dmitry
2010-10-06 10:47 ` Jan Kara
2010-10-10 3:50 ` Brad Boyer
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=20101006133018.GM3676@quack.suse.cz \
--to=jack@suse.cz \
--cc=dmonakhov@gmail.com \
--cc=dmonakhov@openvz.org \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
/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;
as well as URLs for NNTP newsgroup(s).