From: Dmitry Monakhov <dmonakhov@openvz.org>
To: linux-fsdevel@vger.kernel.org
Cc: jack@suse.cz, hch@infradead.org, Dmitry Monakhov <dmonakhov@openvz.org>
Subject: [PATCH 03/19] quota: mode quota internals from sb to quota_info
Date: Fri, 22 Oct 2010 21:34:48 +0400 [thread overview]
Message-ID: <1287768904-27810-4-git-send-email-dmonakhov@openvz.org> (raw)
In-Reply-To: <1287768904-27810-1-git-send-email-dmonakhov@openvz.org>
Obviously most super_blocks don't use quota. So it is reasonable
to hide it inside pointer. The only fields are steel on sb are:
*flags indicate state, checked without locks
*onoff_mutex
*dq_op
*qcop
We can hide dq_op/qcop inside pointer too, but IMHO it is not necessary.
The only superfluous field is dqptr_sem, but currently it is accessed
from all charge/claim/free code without lock. So it is not easy to
serialize it with quotaon/quotaoff at that stage. But this lock
will be removed in later patches anyway, so let's keep it for awhile.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/ext2/super.c | 4 +-
fs/ext3/super.c | 4 +-
fs/ext4/super.c | 4 +-
fs/gfs2/ops_fstype.c | 4 +-
fs/jfs/super.c | 4 +-
fs/ocfs2/quota_local.c | 4 +-
fs/ocfs2/super.c | 6 +-
fs/quota/dquot.c | 243 +++++++++++++++++++++++++-----------------
fs/quota/quota.c | 62 ++++++------
fs/reiserfs/super.c | 4 +-
fs/super.c | 1 -
fs/sync.c | 4 +-
fs/xfs/linux-2.6/xfs_super.c | 2 +-
include/linux/fs.h | 4 +-
include/linux/quota.h | 17 ++-
include/linux/quotaops.h | 15 ++-
16 files changed, 218 insertions(+), 164 deletions(-)
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 7727491..de8d2c4 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1055,8 +1055,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
sb->s_xattr = ext2_xattr_handlers;
#ifdef CONFIG_QUOTA
- sb->dq_op = &dquot_operations;
- sb->s_qcop = &dquot_quotactl_ops;
+ dqctl(sb)->dq_op = &dquot_operations;
+ dqctl(sb)->qcop = &dquot_quotactl_ops;
#endif
root = ext2_iget(sb, EXT2_ROOT_INO);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9740ca2..7a5c6e5 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1929,8 +1929,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sb->s_export_op = &ext3_export_ops;
sb->s_xattr = ext3_xattr_handlers;
#ifdef CONFIG_QUOTA
- sb->s_qcop = &ext3_qctl_operations;
- sb->dq_op = &ext3_quota_operations;
+ dqctl(sb)->qcop = &ext3_qctl_operations;
+ dqctl(sb)->dq_op = &ext3_quota_operations;
#endif
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
mutex_init(&sbi->s_orphan_lock);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e59eb37..e3f4d92 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2938,8 +2938,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_export_op = &ext4_export_ops;
sb->s_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA
- sb->s_qcop = &ext4_qctl_operations;
- sb->dq_op = &ext4_quota_operations;
+ dqctl(sb)->qcop = &ext4_qctl_operations;
+ dqctl(sb)->dq_op = &ext4_quota_operations;
#endif
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
mutex_init(&sbi->s_orphan_lock);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 1e52207..43d0a24 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1167,8 +1167,8 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
sb->s_op = &gfs2_super_ops;
sb->s_export_op = &gfs2_export_ops;
sb->s_xattr = gfs2_xattr_handlers;
- sb->s_qcop = &gfs2_quotactl_ops;
- dqopts(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
+ dqctl(sb)->qcop = &gfs2_quotactl_ops;
+ dqctl(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
sb->s_time_gran = 1;
sb->s_maxbytes = MAX_LFS_FILESIZE;
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index b612adf..a8a94e6 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -477,8 +477,8 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &jfs_super_operations;
sb->s_export_op = &jfs_export_operations;
#ifdef CONFIG_QUOTA
- sb->dq_op = &dquot_operations;
- sb->s_qcop = &dquot_quotactl_ops;
+ dqctl(sb)->dq_op = &dquot_operations;
+ dqctl(sb)->qcop = &dquot_quotactl_ops;
#endif
/*
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 056cb24..7c30ba3 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -596,7 +596,7 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
unsigned int flags;
mlog(ML_NOTICE, "Finishing quota recovery in slot %u\n", slot_num);
- mutex_lock(&dqopts(sb)->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
for (type = 0; type < MAXQUOTAS; type++) {
if (list_empty(&(rec->r_list[type])))
continue;
@@ -672,7 +672,7 @@ out_put:
break;
}
out:
- mutex_unlock(&dqopts(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
kfree(rec);
return status;
}
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index dc5d1ab..3ebb43c 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -907,7 +907,7 @@ static int ocfs2_enable_quotas(struct ocfs2_super *osb)
int status;
int type;
- dqopts(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE;
+ dqctl(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE;
for (type = 0; type < MAXQUOTAS; type++) {
if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
continue;
@@ -2014,8 +2014,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
sb->s_fs_info = osb;
sb->s_op = &ocfs2_sops;
sb->s_export_op = &ocfs2_export_ops;
- sb->s_qcop = &ocfs2_quotactl_ops;
- sb->dq_op = &ocfs2_quota_operations;
+ dqctl(sb)->qcop = &ocfs2_quotactl_ops;
+ dqctl(sb)->dq_op = &ocfs2_quota_operations;
sb->s_xattr = ocfs2_xattr_handlers;
sb->s_time_gran = 1;
sb->s_flags |= MS_NOATIME;
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index fe45466..b87435d 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -332,7 +332,7 @@ static inline int dquot_dirty(struct dquot *dquot)
static inline int mark_dquot_dirty(struct dquot *dquot)
{
- return dquot->dq_sb->dq_op->mark_dirty(dquot);
+ return dqctl(dquot->dq_sb)->dq_op->mark_dirty(dquot);
}
/* Mark dquot dirty in atomic manner, and return it's old dirty flag state */
@@ -406,16 +406,16 @@ int dquot_acquire(struct dquot *dquot)
mutex_lock(&dquot->dq_lock);
mutex_lock(&dqopt->dqio_mutex);
if (!test_bit(DQ_READ_B, &dquot->dq_flags))
- ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
+ ret = dqopt->fmt_ops[dquot->dq_type]->read_dqblk(dquot);
if (ret < 0)
goto out_iolock;
set_bit(DQ_READ_B, &dquot->dq_flags);
/* Instantiate dquot if needed */
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {
- ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
+ ret = dqopt->fmt_ops[dquot->dq_type]->commit_dqblk(dquot);
/* Write the info if needed */
if (info_dirty(&dqopt->info[dquot->dq_type])) {
- ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
+ ret2 = dqopt->fmt_ops[dquot->dq_type]->write_file_info(
dquot->dq_sb, dquot->dq_type);
}
if (ret < 0)
@@ -451,9 +451,9 @@ int dquot_commit(struct dquot *dquot)
/* Inactive dquot can be only if there was error during read/init
* => we have better not writing it */
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
- ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
+ ret = dqopt->fmt_ops[dquot->dq_type]->commit_dqblk(dquot);
if (info_dirty(&dqopt->info[dquot->dq_type])) {
- ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
+ ret2 = dqopt->fmt_ops[dquot->dq_type]->write_file_info(
dquot->dq_sb, dquot->dq_type);
}
if (ret >= 0)
@@ -478,11 +478,11 @@ int dquot_release(struct dquot *dquot)
if (atomic_read(&dquot->dq_count) > 1)
goto out_dqlock;
mutex_lock(&dqopt->dqio_mutex);
- if (dqopt->ops[dquot->dq_type]->release_dqblk) {
- ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot);
+ if (dqopt->fmt_ops[dquot->dq_type]->release_dqblk) {
+ ret = dqopt->fmt_ops[dquot->dq_type]->release_dqblk(dquot);
/* Write the info */
if (info_dirty(&dqopt->info[dquot->dq_type])) {
- ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
+ ret2 = dqopt->fmt_ops[dquot->dq_type]->write_file_info(
dquot->dq_sb, dquot->dq_type);
}
if (ret >= 0)
@@ -504,7 +504,7 @@ EXPORT_SYMBOL(dquot_destroy);
static inline void do_destroy_dquot(struct dquot *dquot)
{
- dquot->dq_sb->dq_op->destroy_dquot(dquot);
+ dqctl(dquot->dq_sb)->dq_op->destroy_dquot(dquot);
}
/* Invalidate all dquots on the list. Note that this function is called after
@@ -568,7 +568,7 @@ int dquot_scan_active(struct super_block *sb,
struct dquot *dquot, *old_dquot = NULL;
int ret = 0;
- mutex_lock(&dqopts(sb)->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
spin_lock(&dq_list_lock);
list_for_each_entry(dquot, &inuse_list, dq_inuse) {
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
@@ -591,7 +591,7 @@ int dquot_scan_active(struct super_block *sb,
spin_unlock(&dq_list_lock);
out:
dqput(old_dquot);
- mutex_unlock(&dqopts(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return ret;
}
EXPORT_SYMBOL(dquot_scan_active);
@@ -600,10 +600,11 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
{
struct list_head *dirty;
struct dquot *dquot;
- struct quota_info *dqopt = dqopts(sb);
+ struct quota_info *dqopt;
int cnt;
- mutex_lock(&dqopt->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
+ dqopt = dqopts(sb);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
@@ -625,7 +626,7 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
atomic_inc(&dquot->dq_count);
spin_unlock(&dq_list_lock);
dqstats_inc(DQST_LOOKUPS);
- sb->dq_op->write_dquot(dquot);
+ dqctl(sb)->dq_op->write_dquot(dquot);
dqput(dquot);
spin_lock(&dq_list_lock);
}
@@ -635,11 +636,11 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if ((cnt == type || type == -1) && sb_has_quota_active(sb, cnt)
&& info_dirty(&dqopt->info[cnt]))
- sb->dq_op->write_info(sb, cnt);
+ dqctl(sb)->dq_op->write_info(sb, cnt);
dqstats_inc(DQST_SYNCS);
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
- if (!wait || (dqopts(sb)->flags & DQUOT_QUOTA_SYS_FILE))
+ if (!wait || (dqctl(sb)->flags & DQUOT_QUOTA_SYS_FILE))
return 0;
/* This is not very clever (and fast) but currently I don't know about
@@ -653,18 +654,19 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
* Now when everything is written we can discard the pagecache so
* that userspace sees the changes.
*/
- mutex_lock(&dqopts(sb)->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
+ dqopt = dqopts(sb);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
if (!sb_has_quota_active(sb, cnt))
continue;
- mutex_lock_nested(&dqopts(sb)->files[cnt]->i_mutex,
+ mutex_lock_nested(&dqopt->files[cnt]->i_mutex,
I_MUTEX_QUOTA);
- truncate_inode_pages(&dqopts(sb)->files[cnt]->i_data, 0);
- mutex_unlock(&dqopts(sb)->files[cnt]->i_mutex);
+ truncate_inode_pages(&dqopt->files[cnt]->i_data, 0);
+ mutex_unlock(&dqopt->files[cnt]->i_mutex);
}
- mutex_unlock(&dqopts(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return 0;
}
@@ -743,7 +745,7 @@ we_slept:
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) {
spin_unlock(&dq_list_lock);
/* Commit dquot before releasing */
- ret = dquot->dq_sb->dq_op->write_dquot(dquot);
+ ret = dqctl(dquot->dq_sb)->dq_op->write_dquot(dquot);
if (ret < 0) {
quota_error(dquot->dq_sb, "Can't write quota structure"
" (error %d). Quota may get out of sync!",
@@ -762,7 +764,7 @@ we_slept:
clear_dquot_dirty(dquot);
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
spin_unlock(&dq_list_lock);
- dquot->dq_sb->dq_op->release_dquot(dquot);
+ dqctl(dquot->dq_sb)->dq_op->release_dquot(dquot);
goto we_slept;
}
atomic_dec(&dquot->dq_count);
@@ -785,7 +787,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
{
struct dquot *dquot;
- dquot = sb->dq_op->alloc_dquot(sb, type);
+ dquot = dqctl(sb)->dq_op->alloc_dquot(sb, type);
if(!dquot)
return NULL;
@@ -858,7 +860,7 @@ we_slept:
wait_on_dquot(dquot);
/* Read the dquot / allocate space in quota file */
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) &&
- sb->dq_op->acquire_dquot(dquot) < 0) {
+ dqctl(sb)->dq_op->acquire_dquot(dquot) < 0) {
dqput(dquot);
dquot = NULL;
goto out;
@@ -1032,10 +1034,10 @@ static void drop_dquot_ref(struct super_block *sb, int type)
{
LIST_HEAD(tofree_head);
- if (sb->dq_op) {
- down_write(&dqopts(sb)->dqptr_sem);
+ if (dqctl(sb)->dq_op) {
+ down_write(&dqctl(sb)->dqptr_sem);
remove_dquot_ref(sb, type, &tofree_head);
- up_write(&dqopts(sb)->dqptr_sem);
+ up_write(&dqctl(sb)->dqptr_sem);
put_dquot_list(&tofree_head);
}
}
@@ -1081,7 +1083,7 @@ void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
static void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
{
- if (sb_dqopts(dquot)->flags & DQUOT_NEGATIVE_USAGE ||
+ if (dqctl(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
dquot->dq_dqb.dqb_curinodes >= number)
dquot->dq_dqb.dqb_curinodes -= number;
else
@@ -1093,7 +1095,7 @@ static void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
static void dquot_decr_space(struct dquot *dquot, qsize_t number)
{
- if (sb_dqopts(dquot)->flags & DQUOT_NEGATIVE_USAGE ||
+ if (dqctl(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
dquot->dq_dqb.dqb_curspace >= number)
dquot->dq_dqb.dqb_curspace -= number;
else
@@ -1377,7 +1379,7 @@ static void __dquot_initialize(struct inode *inode, int type)
got[cnt] = dqget(sb, id, cnt);
}
- down_write(&dqopts(sb)->dqptr_sem);
+ down_write(&dqctl(sb)->dqptr_sem);
if (IS_NOQUOTA(inode))
goto out_err;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1402,7 +1404,7 @@ static void __dquot_initialize(struct inode *inode, int type)
}
}
out_err:
- up_write(&dqopts(sb)->dqptr_sem);
+ up_write(&dqctl(sb)->dqptr_sem);
/* Drop unused references */
dqput_all(got);
}
@@ -1421,12 +1423,12 @@ static void __dquot_drop(struct inode *inode)
int cnt;
struct dquot *put[MAXQUOTAS];
- down_write(&dqopts(inode->i_sb)->dqptr_sem);
+ down_write(&dqctl(inode->i_sb)->dqptr_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
put[cnt] = inode->i_dquot[cnt];
inode->i_dquot[cnt] = NULL;
}
- up_write(&dqopts(inode->i_sb)->dqptr_sem);
+ up_write(&dqctl(inode->i_sb)->dqptr_sem);
dqput_all(put);
}
@@ -1462,8 +1464,8 @@ static qsize_t *inode_reserved_space(struct inode * inode)
{
/* Filesystem must explicitly define it's own method in order to use
* quota reservation interface */
- BUG_ON(!inode->i_sb->dq_op->get_reserved_space);
- return inode->i_sb->dq_op->get_reserved_space(inode);
+ BUG_ON(!dqctl(inode->i_sb)->dq_op->get_reserved_space);
+ return dqctl(inode->i_sb)->dq_op->get_reserved_space(inode);
}
void inode_add_rsv_space(struct inode *inode, qsize_t number)
@@ -1495,7 +1497,7 @@ static qsize_t inode_get_rsv_space(struct inode *inode)
{
qsize_t ret;
- if (!inode->i_sb->dq_op->get_reserved_space)
+ if (!dqctl(inode->i_sb)->dq_op->get_reserved_space)
return 0;
spin_lock(&inode->i_lock);
ret = *inode_reserved_space(inode);
@@ -1550,7 +1552,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
goto out;
}
- down_read(&dqopts(inode->i_sb)->dqptr_sem);
+ down_read(&dqctl(inode->i_sb)->dqptr_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
warntype[cnt] = QUOTA_NL_NOWARN;
@@ -1581,7 +1583,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
mark_all_dquot_dirty(inode->i_dquot);
out_flush_warn:
flush_warnings(inode->i_dquot, warntype);
- up_read(&dqopts(inode->i_sb)->dqptr_sem);
+ up_read(&dqctl(inode->i_sb)->dqptr_sem);
out:
return ret;
}
@@ -1601,7 +1603,7 @@ int dquot_alloc_inode(const struct inode *inode)
return 0;
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
warntype[cnt] = QUOTA_NL_NOWARN;
- down_read(&dqopts(inode->i_sb)->dqptr_sem);
+ down_read(&dqctl(inode->i_sb)->dqptr_sem);
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (!inode->i_dquot[cnt])
@@ -1622,7 +1624,7 @@ warn_put_all:
if (ret == 0)
mark_all_dquot_dirty(inode->i_dquot);
flush_warnings(inode->i_dquot, warntype);
- up_read(&dqopts(inode->i_sb)->dqptr_sem);
+ up_read(&dqctl(inode->i_sb)->dqptr_sem);
return ret;
}
EXPORT_SYMBOL(dquot_alloc_inode);
@@ -1639,7 +1641,7 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
return 0;
}
- down_read(&dqopts(inode->i_sb)->dqptr_sem);
+ down_read(&dqctl(inode->i_sb)->dqptr_sem);
spin_lock(&dq_data_lock);
/* Claim reserved quotas to allocated quotas */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1651,7 +1653,7 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
inode_claim_rsv_space(inode, number);
spin_unlock(&dq_data_lock);
mark_all_dquot_dirty(inode->i_dquot);
- up_read(&dqopts(inode->i_sb)->dqptr_sem);
+ up_read(&dqctl(inode->i_sb)->dqptr_sem);
return 0;
}
EXPORT_SYMBOL(dquot_claim_space_nodirty);
@@ -1672,7 +1674,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
return;
}
- down_read(&dqopts(inode->i_sb)->dqptr_sem);
+ down_read(&dqctl(inode->i_sb)->dqptr_sem);
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (!inode->i_dquot[cnt])
@@ -1691,7 +1693,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
mark_all_dquot_dirty(inode->i_dquot);
out_unlock:
flush_warnings(inode->i_dquot, warntype);
- up_read(&dqopts(inode->i_sb)->dqptr_sem);
+ up_read(&dqctl(inode->i_sb)->dqptr_sem);
}
EXPORT_SYMBOL(__dquot_free_space);
@@ -1708,7 +1710,7 @@ void dquot_free_inode(const struct inode *inode)
if (!dquot_active(inode))
return;
- down_read(&dqopts(inode->i_sb)->dqptr_sem);
+ down_read(&dqctl(inode->i_sb)->dqptr_sem);
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (!inode->i_dquot[cnt])
@@ -1719,7 +1721,7 @@ void dquot_free_inode(const struct inode *inode)
spin_unlock(&dq_data_lock);
mark_all_dquot_dirty(inode->i_dquot);
flush_warnings(inode->i_dquot, warntype);
- up_read(&dqopts(inode->i_sb)->dqptr_sem);
+ up_read(&dqctl(inode->i_sb)->dqptr_sem);
}
EXPORT_SYMBOL(dquot_free_inode);
@@ -1750,9 +1752,9 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
/* Initialize the arrays */
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
warntype_to[cnt] = QUOTA_NL_NOWARN;
- down_write(&dqopts(inode->i_sb)->dqptr_sem);
+ down_write(&dqctl(inode->i_sb)->dqptr_sem);
if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
- up_write(&dqopts(inode->i_sb)->dqptr_sem);
+ up_write(&dqctl(inode->i_sb)->dqptr_sem);
return 0;
}
spin_lock(&dq_data_lock);
@@ -1804,7 +1806,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
inode->i_dquot[cnt] = transfer_to[cnt];
}
spin_unlock(&dq_data_lock);
- up_write(&dqopts(inode->i_sb)->dqptr_sem);
+ up_write(&dqctl(inode->i_sb)->dqptr_sem);
mark_all_dquot_dirty(transfer_from);
mark_all_dquot_dirty(transfer_to);
@@ -1818,7 +1820,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
return 0;
over_quota:
spin_unlock(&dq_data_lock);
- up_write(&dqopts(inode->i_sb)->dqptr_sem);
+ up_write(&dqctl(inode->i_sb)->dqptr_sem);
flush_warnings(transfer_to, warntype_to);
return ret;
}
@@ -1856,7 +1858,7 @@ int dquot_commit_info(struct super_block *sb, int type)
struct quota_info *dqopt = dqopts(sb);
mutex_lock(&dqopt->dqio_mutex);
- ret = dqopt->ops[type]->write_file_info(sb, type);
+ ret = dqopt->fmt_ops[type]->write_file_info(sb, type);
mutex_unlock(&dqopt->dqio_mutex);
return ret;
}
@@ -1890,13 +1892,37 @@ int dquot_file_open(struct inode *inode, struct file *file)
}
EXPORT_SYMBOL(dquot_file_open);
+/* Next two helpers called with dqonoff_mutex held */
+static int alloc_quota_info(struct quota_ctl_info *dqctl) {
+ int err = -ENOMEM;
+ struct quota_info *dqopt;
+ BUG_ON(dqctl->dq_opt);
+
+ dqopt = kzalloc(sizeof(*dqopt), GFP_NOFS);
+ if (!dqopt)
+ return err;
+
+ mutex_init(&dqopt->dqio_mutex);
+ dqctl->dq_opt = dqopt;
+ return 0;
+}
+
+static void free_quota_info(struct quota_ctl_info *dqctl)
+{
+ if (dqctl->dq_opt) {
+ kfree(dqctl->dq_opt);
+ dqctl->dq_opt = NULL;
+ }
+}
+
/*
* Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
*/
int dquot_disable(struct super_block *sb, int type, unsigned int flags)
{
int cnt, ret = 0;
- struct quota_info *dqopt = dqopts(sb);
+ struct quota_ctl_info *qctl = dqctl(sb);
+ struct quota_info *dqopt;
struct inode *toputinode[MAXQUOTAS];
/* Cannot turn off usage accounting without turning off limits, or
@@ -1907,15 +1933,15 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
return -EINVAL;
/* We need to serialize quota_off() for device */
- mutex_lock(&dqopt->dqonoff_mutex);
-
+ mutex_lock(&qctl->dqonoff_mutex);
+ dqopt = dqopts(sb);
/*
* Skip everything if there's nothing to do. We have to do this because
* sometimes we are called when fill_super() failed and calling
* sync_fs() in such cases does no good.
*/
if (!sb_any_quota_loaded(sb)) {
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
return 0;
}
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1927,16 +1953,16 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
if (flags & DQUOT_SUSPENDED) {
spin_lock(&dq_state_lock);
- dqopt->flags |=
+ qctl->flags |=
dquot_state_flag(DQUOT_SUSPENDED, cnt);
spin_unlock(&dq_state_lock);
} else {
spin_lock(&dq_state_lock);
- dqopt->flags &= ~dquot_state_flag(flags, cnt);
+ qctl->flags &= ~dquot_state_flag(flags, cnt);
/* Turning off suspended quotas? */
if (!sb_has_quota_loaded(sb, cnt) &&
sb_has_quota_suspended(sb, cnt)) {
- dqopt->flags &= ~dquot_state_flag(
+ qctl->flags &= ~dquot_state_flag(
DQUOT_SUSPENDED, cnt);
spin_unlock(&dq_state_lock);
iput(dqopt->files[cnt]);
@@ -1958,9 +1984,9 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
* should be only users of the info. No locks needed.
*/
if (info_dirty(&dqopt->info[cnt]))
- sb->dq_op->write_info(sb, cnt);
- if (dqopt->ops[cnt]->free_file_info)
- dqopt->ops[cnt]->free_file_info(sb, cnt);
+ qctl->dq_op->write_info(sb, cnt);
+ if (dqopt->fmt_ops[cnt]->free_file_info)
+ dqopt->fmt_ops[cnt]->free_file_info(sb, cnt);
put_quota_format(dqopt->info[cnt].dqi_format);
toputinode[cnt] = dqopt->files[cnt];
@@ -1969,12 +1995,12 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
dqopt->info[cnt].dqi_flags = 0;
dqopt->info[cnt].dqi_igrace = 0;
dqopt->info[cnt].dqi_bgrace = 0;
- dqopt->ops[cnt] = NULL;
+ dqopt->fmt_ops[cnt] = NULL;
}
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
/* Skip syncing and setting flags if quota files are hidden */
- if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
+ if (qctl->flags & DQUOT_QUOTA_SYS_FILE)
goto put_inodes;
/* Sync the superblock so that buffers with quota data are written to
@@ -1989,7 +2015,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
* changes done by userspace on the next quotaon() */
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (toputinode[cnt]) {
- mutex_lock(&dqopt->dqonoff_mutex);
+ mutex_lock(&qctl->dqonoff_mutex);
/* If quota was reenabled in the meantime, we have
* nothing to do */
if (!sb_has_quota_loaded(sb, cnt)) {
@@ -2002,7 +2028,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
mutex_unlock(&toputinode[cnt]->i_mutex);
mark_inode_dirty_sync(toputinode[cnt]);
}
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
}
if (sb->s_bdev)
invalidate_bdev(sb->s_bdev);
@@ -2021,6 +2047,11 @@ put_inodes:
else if (!toputinode[cnt]->i_nlink)
ret = -EBUSY;
}
+ if (!sb_any_quota_loaded(sb)) {
+ mutex_lock(&qctl->dqonoff_mutex);
+ free_quota_info(qctl);
+ mutex_unlock(&qctl->dqonoff_mutex);
+ }
return ret;
}
EXPORT_SYMBOL(dquot_disable);
@@ -2045,7 +2076,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
{
struct quota_format_type *fmt = find_quota_format(format_id);
struct super_block *sb = inode->i_sb;
- struct quota_info *dqopt = dqopts(sb);
+ struct quota_info *dqopt;
int error;
int oldflags = -1;
@@ -2069,7 +2100,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
goto out_fmt;
}
- if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
+ if (!(dqctl(sb)->flags & DQUOT_QUOTA_SYS_FILE)) {
/* As we bypass the pagecache we must now flush all the
* dirty data and invalidate caches so that kernel sees
* changes from userspace. It is not enough to just flush
@@ -2079,13 +2110,14 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
sync_filesystem(sb);
invalidate_bdev(sb->s_bdev);
}
- mutex_lock(&dqopt->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
+ dqopt = dqopts(sb);
if (sb_has_quota_loaded(sb, type)) {
error = -EBUSY;
goto out_lock;
}
- if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
+ if (!(dqctl(sb)->flags & DQUOT_QUOTA_SYS_FILE)) {
/* We don't want quota and atime on quota files (deadlocks
* possible) Also nobody should write to the file - we use
* special IO operations which ignore the immutable bit. */
@@ -2109,23 +2141,23 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
if (!fmt->qf_ops->check_quota_file(sb, type))
goto out_file_init;
- dqopt->ops[type] = fmt->qf_ops;
+ dqopt->fmt_ops[type] = fmt->qf_ops;
dqopt->info[type].dqi_format = fmt;
dqopt->info[type].dqi_fmt_id = format_id;
INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
mutex_lock(&dqopt->dqio_mutex);
- error = dqopt->ops[type]->read_file_info(sb, type);
+ error = dqopt->fmt_ops[type]->read_file_info(sb, type);
if (error < 0) {
mutex_unlock(&dqopt->dqio_mutex);
goto out_file_init;
}
mutex_unlock(&dqopt->dqio_mutex);
spin_lock(&dq_state_lock);
- dqopt->flags |= dquot_state_flag(flags, type);
+ dqctl(sb)->flags |= dquot_state_flag(flags, type);
spin_unlock(&dq_state_lock);
add_dquot_ref(sb, type);
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return 0;
@@ -2141,7 +2173,7 @@ out_lock:
inode->i_flags |= oldflags;
mutex_unlock(&inode->i_mutex);
}
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
out_fmt:
put_quota_format(fmt);
@@ -2151,7 +2183,7 @@ out_fmt:
/* Reenable quotas on remount RW */
int dquot_resume(struct super_block *sb, int type)
{
- struct quota_info *dqopt = dqopts(sb);
+ struct quota_ctl_info *qctl = dqctl(sb);
struct inode *inode;
int ret = 0, cnt;
unsigned int flags;
@@ -2160,24 +2192,24 @@ int dquot_resume(struct super_block *sb, int type)
if (type != -1 && cnt != type)
continue;
- mutex_lock(&dqopt->dqonoff_mutex);
+ mutex_lock(&qctl->dqonoff_mutex);
if (!sb_has_quota_suspended(sb, cnt)) {
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
continue;
}
- inode = dqopt->files[cnt];
- dqopt->files[cnt] = NULL;
+ inode = qctl->dq_opt->files[cnt];
+ qctl->dq_opt->files[cnt] = NULL;
spin_lock(&dq_state_lock);
- flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
+ flags = qctl->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
DQUOT_LIMITS_ENABLED,
cnt);
- dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt);
+ qctl->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt);
spin_unlock(&dq_state_lock);
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
flags = dquot_generic_flag(flags, cnt);
ret = vfs_load_quota_inode(inode, cnt,
- dqopt->info[cnt].dqi_fmt_id, flags);
+ dqopts(sb)->info[cnt].dqi_fmt_id, flags);
iput(inode);
}
@@ -2188,9 +2220,18 @@ EXPORT_SYMBOL(dquot_resume);
int dquot_quota_on(struct super_block *sb, int type, int format_id,
struct path *path)
{
+ struct quota_ctl_info *qctl = dqctl(sb);
int error = security_quota_on(path->dentry);
if (error)
return error;
+
+ mutex_lock(&qctl->dqonoff_mutex);
+ if (!sb_any_quota_loaded(sb))
+ error = alloc_quota_info(qctl);
+ mutex_unlock(&qctl->dqonoff_mutex);
+ if (error)
+ goto out;
+
/* Quota file not on the same filesystem? */
if (path->mnt->mnt_sb != sb)
error = -EXDEV;
@@ -2198,6 +2239,12 @@ int dquot_quota_on(struct super_block *sb, int type, int format_id,
error = vfs_load_quota_inode(path->dentry->d_inode, type,
format_id, DQUOT_USAGE_ENABLED |
DQUOT_LIMITS_ENABLED);
+out:
+ if (!sb_any_quota_loaded(sb)) {
+ mutex_lock(&qctl->dqonoff_mutex);
+ free_quota_info(qctl);
+ mutex_unlock(&qctl->dqonoff_mutex);
+ }
return error;
}
EXPORT_SYMBOL(dquot_quota_on);
@@ -2211,7 +2258,7 @@ int dquot_enable(struct inode *inode, int type, int format_id,
{
int ret = 0;
struct super_block *sb = inode->i_sb;
- struct quota_info *dqopt = dqopts(sb);
+ struct quota_ctl_info *qctl = dqctl(sb);
/* Just unsuspend quotas? */
BUG_ON(flags & DQUOT_SUSPENDED);
@@ -2220,10 +2267,10 @@ int dquot_enable(struct inode *inode, int type, int format_id,
return 0;
/* Just updating flags needed? */
if (sb_has_quota_loaded(sb, type)) {
- mutex_lock(&dqopt->dqonoff_mutex);
+ mutex_lock(&qctl->dqonoff_mutex);
/* Now do a reliable test... */
if (!sb_has_quota_loaded(sb, type)) {
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
goto load_quota;
}
if (flags & DQUOT_USAGE_ENABLED &&
@@ -2237,10 +2284,10 @@ int dquot_enable(struct inode *inode, int type, int format_id,
goto out_lock;
}
spin_lock(&dq_state_lock);
- dqopts(sb)->flags |= dquot_state_flag(flags, type);
+ qctl->flags |= dquot_state_flag(flags, type);
spin_unlock(&dq_state_lock);
out_lock:
- mutex_unlock(&dqopt->dqonoff_mutex);
+ mutex_unlock(&qctl->dqonoff_mutex);
return ret;
}
@@ -2449,9 +2496,9 @@ int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
{
struct mem_dqinfo *mi;
- mutex_lock(&dqopts(sb)->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
if (!sb_has_quota_active(sb, type)) {
- mutex_unlock(&dqopts(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return -ESRCH;
}
mi = dqopts(sb)->info + type;
@@ -2461,7 +2508,7 @@ int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
ii->dqi_flags = mi->dqi_flags & DQF_MASK;
ii->dqi_valid = IIF_ALL;
spin_unlock(&dq_data_lock);
- mutex_unlock(&dqopts(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return 0;
}
EXPORT_SYMBOL(dquot_get_dqinfo);
@@ -2472,7 +2519,7 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
struct mem_dqinfo *mi;
int err = 0;
- mutex_lock(&dqopts(sb)->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
if (!sb_has_quota_active(sb, type)) {
err = -ESRCH;
goto out;
@@ -2489,9 +2536,9 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
spin_unlock(&dq_data_lock);
mark_info_dirty(sb, type);
/* Force write to disk */
- sb->dq_op->write_info(sb, type);
+ dqctl(sb)->dq_op->write_info(sb, type);
out:
- mutex_unlock(&dqopts(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return err;
}
EXPORT_SYMBOL(dquot_set_dqinfo);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index ce8db30..5a79e09 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -47,8 +47,8 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
static void quota_sync_one(struct super_block *sb, void *arg)
{
- if (sb->s_qcop && sb->s_qcop->quota_sync)
- sb->s_qcop->quota_sync(sb, *(int *)arg, 1);
+ if (dqctl(sb)->qcop && dqctl(sb)->qcop->quota_sync)
+ dqctl(sb)->qcop->quota_sync(sb, *(int *)arg, 1);
}
static int quota_sync_all(int type)
@@ -66,26 +66,26 @@ static int quota_sync_all(int type)
static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
struct path *path)
{
- if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta)
+ if (!dqctl(sb)->qcop->quota_on && !dqctl(sb)->qcop->quota_on_meta)
return -ENOSYS;
- if (sb->s_qcop->quota_on_meta)
- return sb->s_qcop->quota_on_meta(sb, type, id);
+ if (dqctl(sb)->qcop->quota_on_meta)
+ return dqctl(sb)->qcop->quota_on_meta(sb, type, id);
if (IS_ERR(path))
return PTR_ERR(path);
- return sb->s_qcop->quota_on(sb, type, id, path);
+ return dqctl(sb)->qcop->quota_on(sb, type, id, path);
}
static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
{
__u32 fmt;
- mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+ mutex_lock(&dqctl(sb)->dqonoff_mutex);
if (!sb_has_quota_active(sb, type)) {
- mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
return -ESRCH;
}
- fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
- mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+ fmt = dqopts(sb)->info[type].dqi_format->qf_fmt_id;
+ mutex_unlock(&dqctl(sb)->dqonoff_mutex);
if (copy_to_user(addr, &fmt, sizeof(fmt)))
return -EFAULT;
return 0;
@@ -96,9 +96,9 @@ static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
struct if_dqinfo info;
int ret;
- if (!sb->s_qcop->get_info)
+ if (!dqctl(sb)->qcop->get_info)
return -ENOSYS;
- ret = sb->s_qcop->get_info(sb, type, &info);
+ ret = dqctl(sb)->qcop->get_info(sb, type, &info);
if (!ret && copy_to_user(addr, &info, sizeof(info)))
return -EFAULT;
return ret;
@@ -110,9 +110,9 @@ static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
if (copy_from_user(&info, addr, sizeof(info)))
return -EFAULT;
- if (!sb->s_qcop->set_info)
+ if (!dqctl(sb)->qcop->set_info)
return -ENOSYS;
- return sb->s_qcop->set_info(sb, type, &info);
+ return dqctl(sb)->qcop->set_info(sb, type, &info);
}
static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
@@ -135,9 +135,9 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
struct if_dqblk idq;
int ret;
- if (!sb->s_qcop->get_dqblk)
+ if (!dqctl(sb)->qcop->get_dqblk)
return -ENOSYS;
- ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq);
+ ret = dqctl(sb)->qcop->get_dqblk(sb, type, id, &fdq);
if (ret)
return ret;
copy_to_if_dqblk(&idq, &fdq);
@@ -180,10 +180,10 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id,
if (copy_from_user(&idq, addr, sizeof(idq)))
return -EFAULT;
- if (!sb->s_qcop->set_dqblk)
+ if (!dqctl(sb)->qcop->set_dqblk)
return -ENOSYS;
copy_from_if_dqblk(&fdq, &idq);
- return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
+ return dqctl(sb)->qcop->set_dqblk(sb, type, id, &fdq);
}
static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
@@ -192,9 +192,9 @@ static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
if (copy_from_user(&flags, addr, sizeof(flags)))
return -EFAULT;
- if (!sb->s_qcop->set_xstate)
+ if (!dqctl(sb)->qcop->set_xstate)
return -ENOSYS;
- return sb->s_qcop->set_xstate(sb, flags, cmd);
+ return dqctl(sb)->qcop->set_xstate(sb, flags, cmd);
}
static int quota_getxstate(struct super_block *sb, void __user *addr)
@@ -202,9 +202,9 @@ static int quota_getxstate(struct super_block *sb, void __user *addr)
struct fs_quota_stat fqs;
int ret;
- if (!sb->s_qcop->get_xstate)
+ if (!dqctl(sb)->qcop->get_xstate)
return -ENOSYS;
- ret = sb->s_qcop->get_xstate(sb, &fqs);
+ ret = dqctl(sb)->qcop->get_xstate(sb, &fqs);
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
return -EFAULT;
return ret;
@@ -217,9 +217,9 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
if (copy_from_user(&fdq, addr, sizeof(fdq)))
return -EFAULT;
- if (!sb->s_qcop->set_dqblk)
+ if (!dqctl(sb)->qcop->set_dqblk)
return -ENOSYS;
- return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
+ return dqctl(sb)->qcop->set_dqblk(sb, type, id, &fdq);
}
static int quota_getxquota(struct super_block *sb, int type, qid_t id,
@@ -228,9 +228,9 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id,
struct fs_disk_quota fdq;
int ret;
- if (!sb->s_qcop->get_dqblk)
+ if (!dqctl(sb)->qcop->get_dqblk)
return -ENOSYS;
- ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq);
+ ret = dqctl(sb)->qcop->get_dqblk(sb, type, id, &fdq);
if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
return -EFAULT;
return ret;
@@ -244,7 +244,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
return -EINVAL;
- if (!sb->s_qcop)
+ if (!dqctl(sb)->qcop)
return -ENOSYS;
ret = check_quotactl_permission(sb, type, cmd, id);
@@ -255,9 +255,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
case Q_QUOTAON:
return quota_quotaon(sb, type, cmd, id, path);
case Q_QUOTAOFF:
- if (!sb->s_qcop->quota_off)
+ if (!dqctl(sb)->qcop->quota_off)
return -ENOSYS;
- return sb->s_qcop->quota_off(sb, type);
+ return dqctl(sb)->qcop->quota_off(sb, type);
case Q_GETFMT:
return quota_getfmt(sb, type, addr);
case Q_GETINFO:
@@ -269,9 +269,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
case Q_SETQUOTA:
return quota_setquota(sb, type, id, addr);
case Q_SYNC:
- if (!sb->s_qcop->quota_sync)
+ if (!dqctl(sb)->qcop->quota_sync)
return -ENOSYS;
- return sb->s_qcop->quota_sync(sb, type, 1);
+ return dqctl(sb)->qcop->quota_sync(sb, type, 1);
case Q_XQUOTAON:
case Q_XQUOTAOFF:
case Q_XQUOTARM:
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 707f9dc..4a51677 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1407,8 +1407,8 @@ static int read_super_block(struct super_block *s, int offset)
s->s_op = &reiserfs_sops;
s->s_export_op = &reiserfs_export_ops;
#ifdef CONFIG_QUOTA
- s->s_qcop = &reiserfs_qctl_operations;
- s->dq_op = &reiserfs_quota_operations;
+ dqctl(s)->qcop = &reiserfs_qctl_operations;
+ dqctl(s)->dq_op = &reiserfs_quota_operations;
#endif
/* new format is limited by the 32 bit wide i_blocks field, want to
diff --git a/fs/super.c b/fs/super.c
index 8819e3a..9eea8e9 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -103,7 +103,6 @@ static struct super_block *alloc_super(struct file_system_type *type)
atomic_set(&s->s_active, 1);
mutex_init(&s->s_vfs_rename_mutex);
lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
- mutex_init(&s->s_dquot.dqio_mutex);
mutex_init(&s->s_dquot.dqonoff_mutex);
init_rwsem(&s->s_dquot.dqptr_sem);
init_waitqueue_head(&s->s_wait_unfrozen);
diff --git a/fs/sync.c b/fs/sync.c
index ba76b96..891e8ef 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -36,8 +36,8 @@ static int __sync_filesystem(struct super_block *sb, int wait)
if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info)
return 0;
- if (sb->s_qcop && sb->s_qcop->quota_sync)
- sb->s_qcop->quota_sync(sb, -1, wait);
+ if (sb->s_dquot.qcop && sb->s_dquot.qcop->quota_sync)
+ sb->s_dquot.qcop->quota_sync(sb, -1, wait);
if (wait)
sync_inodes_sb(sb);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index a4e0797..4e59a08 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1510,7 +1510,7 @@ xfs_fs_fill_super(
sb->s_xattr = xfs_xattr_handlers;
sb->s_export_op = &xfs_export_operations;
#ifdef CONFIG_XFS_QUOTA
- sb->s_qcop = &xfs_quotactl_operations;
+ sb->s_dquot.qcop = &xfs_quotactl_operations;
#endif
sb->s_op = &xfs_super_operations;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 63d069b..e87694a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1324,8 +1324,6 @@ struct super_block {
loff_t s_maxbytes; /* Max file size */
struct file_system_type *s_type;
const struct super_operations *s_op;
- const struct dquot_operations *dq_op;
- const struct quotactl_ops *s_qcop;
const struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
@@ -1354,7 +1352,7 @@ struct super_block {
struct backing_dev_info *s_bdi;
struct mtd_info *s_mtd;
struct list_head s_instances;
- struct quota_info s_dquot; /* Diskquota specific options */
+ struct quota_ctl_info s_dquot; /* Diskquota specific options */
int s_frozen;
wait_queue_head_t s_wait_unfrozen;
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 00e1b3d..6803834 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -324,7 +324,7 @@ struct dquot_operations {
};
struct path;
-
+struct quota_info;
/* Operations handling requests from userspace */
struct quotactl_ops {
int (*quota_on)(struct super_block *, int, int, struct path *);
@@ -392,15 +392,20 @@ static inline void quota_send_warning(short type, unsigned int id, dev_t dev,
return;
}
#endif /* CONFIG_QUOTA_NETLINK_INTERFACE */
+struct quota_ctl_info {
+ unsigned int flags; /* Flags for diskquotas on this device */
+ struct mutex dqonoff_mutex; /* Serialize quotaon & quotaoff */
+ struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
+ const struct quotactl_ops *qcop;
+ const struct dquot_operations *dq_op;
+ struct quota_info *dq_opt;
+};
struct quota_info {
- unsigned int flags; /* Flags for diskquotas on this device */
struct mutex dqio_mutex; /* lock device while I/O in progress */
- struct mutex dqonoff_mutex; /* Serialize quotaon & quotaoff */
- struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
- struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
- const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
+ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
+ const struct quota_format_ops *fmt_ops[MAXQUOTAS]; /* Operations for each type */
};
int register_quota_format(struct quota_format_type *fmt);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index b154d52..6f4cc74 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -13,15 +13,20 @@
#define DQUOT_SPACE_RESERVE 0x2
#define DQUOT_SPACE_NOFAIL 0x4
-static inline struct quota_info *dqopts(struct super_block *sb)
+static inline struct quota_ctl_info* dqctl( struct super_block *sb)
{
return &sb->s_dquot;
}
-static inline struct quota_info* sb_dqopts(struct dquot *dq)
+static inline struct quota_info *dqopts(const struct super_block *sb)
+{
+ return sb->s_dquot.dq_opt;
+}
+static inline struct quota_info* sb_dqopts(const struct dquot *dq)
{
return dqopts(dq->dq_sb);
}
+
/* i_mutex must being held */
static inline bool is_quota_modification(struct inode *inode, struct iattr *ia)
{
@@ -108,19 +113,19 @@ static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
static inline bool sb_has_quota_usage_enabled(struct super_block *sb, int type)
{
- return dqopts(sb)->flags &
+ return dqctl(sb)->flags &
dquot_state_flag(DQUOT_USAGE_ENABLED, type);
}
static inline bool sb_has_quota_limits_enabled(struct super_block *sb, int type)
{
- return dqopts(sb)->flags &
+ return dqctl(sb)->flags &
dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
}
static inline bool sb_has_quota_suspended(struct super_block *sb, int type)
{
- return dqopts(sb)->flags &
+ return dqctl(sb)->flags &
dquot_state_flag(DQUOT_SUSPENDED, type);
}
--
1.6.5.2
next prev parent reply other threads:[~2010-10-22 17:35 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-22 17:34 [PATCH 00/19] quota: RFC SMP improvements for generic quota V2 Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 01/19] quota: protect getfmt call with dqonoff_mutex lock Dmitry Monakhov
2010-10-28 14:27 ` Christoph Hellwig
2010-10-22 17:34 ` [PATCH 02/19] quota: Wrap common expression to helper function Dmitry Monakhov
2010-10-22 17:34 ` Dmitry Monakhov [this message]
2010-10-22 17:34 ` [PATCH 04/19] quota: Convert dq_state_lock to per-sb dq_state_lock Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 05/19] quota: add quota format lock Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 06/19] quota: make dquot lists per-sb Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 07/19] quota: make per-sb hash array Dmitry Monakhov
2010-10-27 19:31 ` Al Viro
2010-10-28 10:58 ` Dmitry
2010-10-22 17:34 ` [PATCH 08/19] quota: remove global dq_list_lock Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 09/19] quota: rename dq_lock Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 10/19] quota: make per-sb dq_data_lock Dmitry Monakhov
2010-10-26 17:38 ` Dmitry
2010-10-22 17:34 ` [PATCH 11/19] quota: protect dquot mem info with object's lock Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 12/19] quota: drop dq_data_lock where possible Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 13/19] quota: relax dq_data_lock dq_lock locking consistency Dmitry Monakhov
2010-10-22 17:34 ` [PATCH 14/19] quota: protect dqget() from parallels quotaoff via RCU Dmitry Monakhov
2010-10-22 17:35 ` [PATCH 15/19] quota: remove dq_state_lock Dmitry Monakhov
2010-10-22 17:35 ` [PATCH 16/19] fs: add unlocked helpers Dmitry Monakhov
2010-10-22 17:35 ` [PATCH 17/19] quota: Some stylistic cleanup for dquot interface Dmitry Monakhov
2010-10-22 17:35 ` [PATCH 18/19] quota: remove dqptr_sem Dmitry Monakhov
2010-10-22 17:35 ` [PATCH 19/19] quota: redesign dquot reference counting Dmitry Monakhov
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=1287768904-27810-4-git-send-email-dmonakhov@openvz.org \
--to=dmonakhov@openvz.org \
--cc=hch@infradead.org \
--cc=jack@suse.cz \
--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).