Commit 1f54587b authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds

[PATCH] quota: ext3: Improve quota credit estimates

Use improved credits estimates for quota operations.  Also reserve a space
for a quota operation in a transaction only if filesystem was mounted with
some quota options.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4e5117ba
...@@ -393,7 +393,8 @@ ext3_acl_chmod(struct inode *inode) ...@@ -393,7 +393,8 @@ ext3_acl_chmod(struct inode *inode)
int retries = 0; int retries = 0;
retry: retry:
handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); handle = ext3_journal_start(inode,
EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
error = PTR_ERR(handle); error = PTR_ERR(handle);
ext3_std_error(inode->i_sb, error); ext3_std_error(inode->i_sb, error);
...@@ -503,7 +504,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value, ...@@ -503,7 +504,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
acl = NULL; acl = NULL;
retry: retry:
handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
error = ext3_set_acl(handle, inode, type, acl); error = ext3_set_acl(handle, inode, type, acl);
......
...@@ -128,7 +128,7 @@ static unsigned long blocks_for_truncate(struct inode *inode) ...@@ -128,7 +128,7 @@ static unsigned long blocks_for_truncate(struct inode *inode)
if (needed > EXT3_MAX_TRANS_DATA) if (needed > EXT3_MAX_TRANS_DATA)
needed = EXT3_MAX_TRANS_DATA; needed = EXT3_MAX_TRANS_DATA;
return EXT3_DATA_TRANS_BLOCKS + needed; return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
} }
/* /*
...@@ -2763,7 +2763,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -2763,7 +2763,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
/* (user+group)*(old+new) structure, inode write (sb, /* (user+group)*(old+new) structure, inode write (sb,
* inode block, ? - but truncate inode update has it) */ * inode block, ? - but truncate inode update has it) */
handle = ext3_journal_start(inode, 4*EXT3_QUOTA_INIT_BLOCKS+3); handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
error = PTR_ERR(handle); error = PTR_ERR(handle);
goto err_out; goto err_out;
...@@ -2861,7 +2862,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode) ...@@ -2861,7 +2862,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode)
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
/* We know that structure was already allocated during DQUOT_INIT so /* We know that structure was already allocated during DQUOT_INIT so
* we will be updating only the data blocks + inodes */ * we will be updating only the data blocks + inodes */
ret += 2*EXT3_QUOTA_TRANS_BLOCKS; ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
#endif #endif
return ret; return ret;
......
...@@ -1645,9 +1645,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode, ...@@ -1645,9 +1645,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
int err, retries = 0; int err, retries = 0;
retry: retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
2*EXT3_QUOTA_INIT_BLOCKS); 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -1679,9 +1679,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry, ...@@ -1679,9 +1679,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
return -EINVAL; return -EINVAL;
retry: retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
2*EXT3_QUOTA_INIT_BLOCKS); 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -1715,9 +1715,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) ...@@ -1715,9 +1715,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
return -EMLINK; return -EMLINK;
retry: retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
2*EXT3_QUOTA_INIT_BLOCKS); 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -2006,7 +2006,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) ...@@ -2006,7 +2006,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
/* Initialize quotas before so that eventual writes go in /* Initialize quotas before so that eventual writes go in
* separate transaction */ * separate transaction */
DQUOT_INIT(dentry->d_inode); DQUOT_INIT(dentry->d_inode);
handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -2065,7 +2065,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) ...@@ -2065,7 +2065,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
/* Initialize quotas before so that eventual writes go /* Initialize quotas before so that eventual writes go
* in separate transaction */ * in separate transaction */
DQUOT_INIT(dentry->d_inode); DQUOT_INIT(dentry->d_inode);
handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -2120,9 +2120,9 @@ static int ext3_symlink (struct inode * dir, ...@@ -2120,9 +2120,9 @@ static int ext3_symlink (struct inode * dir,
return -ENAMETOOLONG; return -ENAMETOOLONG;
retry: retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
2*EXT3_QUOTA_INIT_BLOCKS); 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -2174,7 +2174,7 @@ static int ext3_link (struct dentry * old_dentry, ...@@ -2174,7 +2174,7 @@ static int ext3_link (struct dentry * old_dentry,
return -EMLINK; return -EMLINK;
retry: retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS); EXT3_INDEX_EXTRA_TRANS_BLOCKS);
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
...@@ -2216,7 +2216,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, ...@@ -2216,7 +2216,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
* in separate transaction */ * in separate transaction */
if (new_dentry->d_inode) if (new_dentry->d_inode)
DQUOT_INIT(new_dentry->d_inode); DQUOT_INIT(new_dentry->d_inode);
handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + handle = ext3_journal_start(old_dir, 2 *
EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
......
...@@ -589,7 +589,7 @@ enum { ...@@ -589,7 +589,7 @@ enum {
Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_commit, Opt_journal_update, Opt_journal_inum,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
}; };
...@@ -634,10 +634,10 @@ static match_table_t tokens = { ...@@ -634,10 +634,10 @@ static match_table_t tokens = {
{Opt_grpjquota, "grpjquota=%s"}, {Opt_grpjquota, "grpjquota=%s"},
{Opt_jqfmt_vfsold, "jqfmt=vfsold"}, {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
{Opt_ignore, "grpquota"}, {Opt_quota, "grpquota"},
{Opt_ignore, "noquota"}, {Opt_noquota, "noquota"},
{Opt_ignore, "quota"}, {Opt_quota, "quota"},
{Opt_ignore, "usrquota"}, {Opt_quota, "usrquota"},
{Opt_barrier, "barrier=%u"}, {Opt_barrier, "barrier=%u"},
{Opt_err, NULL}, {Opt_err, NULL},
{Opt_resize, "resize"}, {Opt_resize, "resize"},
...@@ -876,6 +876,7 @@ set_qf_name: ...@@ -876,6 +876,7 @@ set_qf_name:
sbi->s_qf_names[qtype] = NULL; sbi->s_qf_names[qtype] = NULL;
return 0; return 0;
} }
set_opt(sbi->s_mount_opt, QUOTA);
break; break;
case Opt_offusrjquota: case Opt_offusrjquota:
qtype = USRQUOTA; qtype = USRQUOTA;
...@@ -898,6 +899,17 @@ clear_qf_name: ...@@ -898,6 +899,17 @@ clear_qf_name:
case Opt_jqfmt_vfsv0: case Opt_jqfmt_vfsv0:
sbi->s_jquota_fmt = QFMT_VFS_V0; sbi->s_jquota_fmt = QFMT_VFS_V0;
break; break;
case Opt_quota:
set_opt(sbi->s_mount_opt, QUOTA);
break;
case Opt_noquota:
if (sb_any_quota_enabled(sb)) {
printk(KERN_ERR "EXT3-fs: Cannot change quota "
"options when quota turned on.\n");
return 0;
}
clear_opt(sbi->s_mount_opt, QUOTA);
break;
#else #else
case Opt_usrjquota: case Opt_usrjquota:
case Opt_grpjquota: case Opt_grpjquota:
...@@ -909,6 +921,9 @@ clear_qf_name: ...@@ -909,6 +921,9 @@ clear_qf_name:
"EXT3-fs: journalled quota options not " "EXT3-fs: journalled quota options not "
"supported.\n"); "supported.\n");
break; break;
case Opt_quota:
case Opt_noquota:
break;
#endif #endif
case Opt_abort: case Opt_abort:
set_opt(sbi->s_mount_opt, ABORT); set_opt(sbi->s_mount_opt, ABORT);
...@@ -2238,7 +2253,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type) ...@@ -2238,7 +2253,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type)
int ret, err; int ret, err;
/* We may create quota structure so we need to reserve enough blocks */ /* We may create quota structure so we need to reserve enough blocks */
handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
ret = dquot_initialize(inode, type); ret = dquot_initialize(inode, type);
...@@ -2254,7 +2269,7 @@ static int ext3_dquot_drop(struct inode *inode) ...@@ -2254,7 +2269,7 @@ static int ext3_dquot_drop(struct inode *inode)
int ret, err; int ret, err;
/* We may delete quota structure so we need to reserve enough blocks */ /* We may delete quota structure so we need to reserve enough blocks */
handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
ret = dquot_drop(inode); ret = dquot_drop(inode);
...@@ -2272,7 +2287,7 @@ static int ext3_write_dquot(struct dquot *dquot) ...@@ -2272,7 +2287,7 @@ static int ext3_write_dquot(struct dquot *dquot)
inode = dquot_to_inode(dquot); inode = dquot_to_inode(dquot);
handle = ext3_journal_start(inode, handle = ext3_journal_start(inode,
EXT3_QUOTA_TRANS_BLOCKS); EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
ret = dquot_commit(dquot); ret = dquot_commit(dquot);
...@@ -2288,7 +2303,7 @@ static int ext3_acquire_dquot(struct dquot *dquot) ...@@ -2288,7 +2303,7 @@ static int ext3_acquire_dquot(struct dquot *dquot)
handle_t *handle; handle_t *handle;
handle = ext3_journal_start(dquot_to_inode(dquot), handle = ext3_journal_start(dquot_to_inode(dquot),
EXT3_QUOTA_INIT_BLOCKS); EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
ret = dquot_acquire(dquot); ret = dquot_acquire(dquot);
...@@ -2304,7 +2319,7 @@ static int ext3_release_dquot(struct dquot *dquot) ...@@ -2304,7 +2319,7 @@ static int ext3_release_dquot(struct dquot *dquot)
handle_t *handle; handle_t *handle;
handle = ext3_journal_start(dquot_to_inode(dquot), handle = ext3_journal_start(dquot_to_inode(dquot),
EXT3_QUOTA_INIT_BLOCKS); EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
if (IS_ERR(handle)) if (IS_ERR(handle))
return PTR_ERR(handle); return PTR_ERR(handle);
ret = dquot_release(dquot); ret = dquot_release(dquot);
...@@ -2361,6 +2376,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, ...@@ -2361,6 +2376,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
int err; int err;
struct nameidata nd; struct nameidata nd;
if (!test_opt(sb, QUOTA))
return -EINVAL;
/* Not journalling quota? */ /* Not journalling quota? */
if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
!EXT3_SB(sb)->s_qf_names[GRPQUOTA]) !EXT3_SB(sb)->s_qf_names[GRPQUOTA])
......
...@@ -1044,7 +1044,7 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name, ...@@ -1044,7 +1044,7 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
int error, retries = 0; int error, retries = 0;
retry: retry:
handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
error = PTR_ERR(handle); error = PTR_ERR(handle);
} else { } else {
......
...@@ -358,6 +358,7 @@ struct ext3_inode { ...@@ -358,6 +358,7 @@ struct ext3_inode {
#define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */ #define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */
#define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */ #define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */
#define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */ #define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */
#define EXT3_MOUNT_QUOTA 0x80000 /* Some quota option set */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H #ifndef _LINUX_EXT2_FS_H
......
...@@ -42,15 +42,15 @@ ...@@ -42,15 +42,15 @@
* superblock only gets updated once, of course, so don't bother * superblock only gets updated once, of course, so don't bother
* counting that again for the quota updates. */ * counting that again for the quota updates. */
#define EXT3_DATA_TRANS_BLOCKS (EXT3_SINGLEDATA_TRANS_BLOCKS + \ #define EXT3_DATA_TRANS_BLOCKS(sb) (EXT3_SINGLEDATA_TRANS_BLOCKS + \
EXT3_XATTR_TRANS_BLOCKS - 2 + \ EXT3_XATTR_TRANS_BLOCKS - 2 + \
2*EXT3_QUOTA_TRANS_BLOCKS) 2*EXT3_QUOTA_TRANS_BLOCKS(sb))
/* Delete operations potentially hit one directory's namespace plus an /* Delete operations potentially hit one directory's namespace plus an
* entire inode, plus arbitrary amounts of bitmap/indirection data. Be * entire inode, plus arbitrary amounts of bitmap/indirection data. Be
* generous. We can grow the delete transaction later if necessary. */ * generous. We can grow the delete transaction later if necessary. */
#define EXT3_DELETE_TRANS_BLOCKS (2 * EXT3_DATA_TRANS_BLOCKS + 64) #define EXT3_DELETE_TRANS_BLOCKS(sb) (2 * EXT3_DATA_TRANS_BLOCKS(sb) + 64)
/* Define an arbitrary limit for the amount of data we will anticipate /* Define an arbitrary limit for the amount of data we will anticipate
* writing to any given transaction. For unbounded transactions such as * writing to any given transaction. For unbounded transactions such as
...@@ -74,14 +74,17 @@ ...@@ -74,14 +74,17 @@
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
/* Amount of blocks needed for quota update - we know that the structure was /* Amount of blocks needed for quota update - we know that the structure was
* allocated so we need to update only inode+data */ * allocated so we need to update only inode+data */
#define EXT3_QUOTA_TRANS_BLOCKS 2 #define EXT3_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
/* Amount of blocks needed for quota insert/delete - we do some block writes /* Amount of blocks needed for quota insert/delete - we do some block writes
* but inode, sb and group updates are done only once */ * but inode, sb and group updates are done only once */
#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\ #define EXT3_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
(EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3) (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_INIT_REWRITE) : 0)
#define EXT3_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
(EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_DEL_REWRITE) : 0)
#else #else
#define EXT3_QUOTA_TRANS_BLOCKS 0 #define EXT3_QUOTA_TRANS_BLOCKS(sb) 0
#define EXT3_QUOTA_INIT_BLOCKS 0 #define EXT3_QUOTA_INIT_BLOCKS(sb) 0
#define EXT3_QUOTA_DEL_BLOCKS(sb) 0
#endif #endif
int int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment