Commit ac0e9c30 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  jbd2: update transaction t_state to T_COMMIT fix
  ext4: Retry block allocation if new blocks are allocated from system zone.
  ext4: mballoc fix mb_normalize_request algorithm for 1KB block size filesystems
  ext4: fix typos in messages and comments (journalled -> journaled)
  ext4: fix synchronization of quota files in journal=data mode
  ext4: Fix mount messages when quota disabled
  ext4: correct mount option parsing to detect when quota options can be changed
parents a76bfd0d 02c471cb
...@@ -287,11 +287,11 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group) ...@@ -287,11 +287,11 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
(int)block_group, (unsigned long long)bitmap_blk); (int)block_group, (unsigned long long)bitmap_blk);
return NULL; return NULL;
} }
if (!ext4_valid_block_bitmap(sb, desc, block_group, bh)) { ext4_valid_block_bitmap(sb, desc, block_group, bh);
put_bh(bh); /*
return NULL; * file system mounted not to panic on error,
} * continue with corrupt bitmap
*/
return bh; return bh;
} }
/* /*
...@@ -1770,7 +1770,12 @@ ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode, ...@@ -1770,7 +1770,12 @@ ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
"Allocating block in system zone - " "Allocating block in system zone - "
"blocks from %llu, length %lu", "blocks from %llu, length %lu",
ret_block, num); ret_block, num);
goto out; /*
* claim_block marked the blocks we allocated
* as in use. So we may want to selectively
* mark some of the blocks as free
*/
goto retry_alloc;
} }
performed_allocation = 1; performed_allocation = 1;
......
...@@ -2736,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, ...@@ -2736,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
struct ext4_sb_info *sbi; struct ext4_sb_info *sbi;
struct super_block *sb; struct super_block *sb;
ext4_fsblk_t block; ext4_fsblk_t block;
int err; int err, len;
BUG_ON(ac->ac_status != AC_STATUS_FOUND); BUG_ON(ac->ac_status != AC_STATUS_FOUND);
BUG_ON(ac->ac_b_ex.fe_len <= 0); BUG_ON(ac->ac_b_ex.fe_len <= 0);
...@@ -2770,14 +2770,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, ...@@ -2770,14 +2770,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ ac->ac_b_ex.fe_start + ac->ac_b_ex.fe_start
+ le32_to_cpu(es->s_first_data_block); + le32_to_cpu(es->s_first_data_block);
if (block == ext4_block_bitmap(sb, gdp) || len = ac->ac_b_ex.fe_len;
block == ext4_inode_bitmap(sb, gdp) || if (in_range(ext4_block_bitmap(sb, gdp), block, len) ||
in_range(ext4_inode_bitmap(sb, gdp), block, len) ||
in_range(block, ext4_inode_table(sb, gdp), in_range(block, ext4_inode_table(sb, gdp),
EXT4_SB(sb)->s_itb_per_group) ||
in_range(block + len - 1, ext4_inode_table(sb, gdp),
EXT4_SB(sb)->s_itb_per_group)) { EXT4_SB(sb)->s_itb_per_group)) {
ext4_error(sb, __func__, ext4_error(sb, __func__,
"Allocating block in system zone - block = %llu", "Allocating block in system zone - block = %llu",
block); block);
/* File system mounted not to panic on error
* Fix the bitmap and repeat the block allocation
* We leak some of the blocks here.
*/
mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group),
bitmap_bh->b_data, ac->ac_b_ex.fe_start,
ac->ac_b_ex.fe_len);
err = ext4_journal_dirty_metadata(handle, bitmap_bh);
if (!err)
err = -EAGAIN;
goto out_err;
} }
#ifdef AGGRESSIVE_CHECK #ifdef AGGRESSIVE_CHECK
{ {
...@@ -2880,12 +2893,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, ...@@ -2880,12 +2893,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
if (size < i_size_read(ac->ac_inode)) if (size < i_size_read(ac->ac_inode))
size = i_size_read(ac->ac_inode); size = i_size_read(ac->ac_inode);
/* max available blocks in a free group */ /* max size of free chunks */
max = EXT4_BLOCKS_PER_GROUP(ac->ac_sb) - 1 - 1 - max = 2 << bsbits;
EXT4_SB(ac->ac_sb)->s_itb_per_group;
#define NRL_CHECK_SIZE(req, size, max,bits) \ #define NRL_CHECK_SIZE(req, size, max, chunk_size) \
(req <= (size) || max <= ((size) >> bits)) (req <= (size) || max <= (chunk_size))
/* first, try to predict filesize */ /* first, try to predict filesize */
/* XXX: should this table be tunable? */ /* XXX: should this table be tunable? */
...@@ -2904,16 +2916,16 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, ...@@ -2904,16 +2916,16 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
size = 512 * 1024; size = 512 * 1024;
} else if (size <= 1024 * 1024) { } else if (size <= 1024 * 1024) {
size = 1024 * 1024; size = 1024 * 1024;
} else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, bsbits)) { } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, 2 * 1024)) {
start_off = ((loff_t)ac->ac_o_ex.fe_logical >> start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
(20 - bsbits)) << 20; (21 - bsbits)) << 21;
size = 1024 * 1024; size = 2 * 1024 * 1024;
} else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, bsbits)) { } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, 4 * 1024)) {
start_off = ((loff_t)ac->ac_o_ex.fe_logical >> start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
(22 - bsbits)) << 22; (22 - bsbits)) << 22;
size = 4 * 1024 * 1024; size = 4 * 1024 * 1024;
} else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len,
(8<<20)>>bsbits, max, bsbits)) { (8<<20)>>bsbits, max, 8 * 1024)) {
start_off = ((loff_t)ac->ac_o_ex.fe_logical >> start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
(23 - bsbits)) << 23; (23 - bsbits)) << 23;
size = 8 * 1024 * 1024; size = 8 * 1024 * 1024;
...@@ -4033,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, ...@@ -4033,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
ac->ac_op = EXT4_MB_HISTORY_ALLOC; ac->ac_op = EXT4_MB_HISTORY_ALLOC;
ext4_mb_normalize_request(ac, ar); ext4_mb_normalize_request(ac, ar);
repeat: repeat:
/* allocate space in core */ /* allocate space in core */
ext4_mb_regular_allocator(ac); ext4_mb_regular_allocator(ac);
...@@ -4047,10 +4058,21 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, ...@@ -4047,10 +4058,21 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
} }
if (likely(ac->ac_status == AC_STATUS_FOUND)) { if (likely(ac->ac_status == AC_STATUS_FOUND)) {
ext4_mb_mark_diskspace_used(ac, handle); *errp = ext4_mb_mark_diskspace_used(ac, handle);
*errp = 0; if (*errp == -EAGAIN) {
ac->ac_b_ex.fe_group = 0;
ac->ac_b_ex.fe_start = 0;
ac->ac_b_ex.fe_len = 0;
ac->ac_status = AC_STATUS_CONTINUE;
goto repeat;
} else if (*errp) {
ac->ac_b_ex.fe_len = 0;
ar->len = 0;
ext4_mb_show_ac(ac);
} else {
block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
ar->len = ac->ac_b_ex.fe_len; ar->len = ac->ac_b_ex.fe_len;
}
} else { } else {
freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len); freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len);
if (freed) if (freed)
...@@ -4237,6 +4259,8 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, ...@@ -4237,6 +4259,8 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
ext4_error(sb, __func__, ext4_error(sb, __func__,
"Freeing blocks in system zone - " "Freeing blocks in system zone - "
"Block = %lu, count = %lu", block, count); "Block = %lu, count = %lu", block, count);
/* err = 0. ext4_std_error should be a no op */
goto error_return;
} }
BUFFER_TRACE(bitmap_bh, "getting write access"); BUFFER_TRACE(bitmap_bh, "getting write access");
......
...@@ -979,7 +979,7 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -979,7 +979,7 @@ static int parse_options (char *options, struct super_block *sb,
int data_opt = 0; int data_opt = 0;
int option; int option;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
int qtype; int qtype, qfmt;
char *qname; char *qname;
#endif #endif
...@@ -1162,9 +1162,11 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1162,9 +1162,11 @@ static int parse_options (char *options, struct super_block *sb,
case Opt_grpjquota: case Opt_grpjquota:
qtype = GRPQUOTA; qtype = GRPQUOTA;
set_qf_name: set_qf_name:
if (sb_any_quota_enabled(sb)) { if ((sb_any_quota_enabled(sb) ||
sb_any_quota_suspended(sb)) &&
!sbi->s_qf_names[qtype]) {
printk(KERN_ERR printk(KERN_ERR
"EXT4-fs: Cannot change journalled " "EXT4-fs: Cannot change journaled "
"quota options when quota turned on.\n"); "quota options when quota turned on.\n");
return 0; return 0;
} }
...@@ -1200,9 +1202,11 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1200,9 +1202,11 @@ static int parse_options (char *options, struct super_block *sb,
case Opt_offgrpjquota: case Opt_offgrpjquota:
qtype = GRPQUOTA; qtype = GRPQUOTA;
clear_qf_name: clear_qf_name:
if (sb_any_quota_enabled(sb)) { if ((sb_any_quota_enabled(sb) ||
sb_any_quota_suspended(sb)) &&
sbi->s_qf_names[qtype]) {
printk(KERN_ERR "EXT4-fs: Cannot change " printk(KERN_ERR "EXT4-fs: Cannot change "
"journalled quota options when " "journaled quota options when "
"quota turned on.\n"); "quota turned on.\n");
return 0; return 0;
} }
...@@ -1213,10 +1217,20 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1213,10 +1217,20 @@ static int parse_options (char *options, struct super_block *sb,
sbi->s_qf_names[qtype] = NULL; sbi->s_qf_names[qtype] = NULL;
break; break;
case Opt_jqfmt_vfsold: case Opt_jqfmt_vfsold:
sbi->s_jquota_fmt = QFMT_VFS_OLD; qfmt = QFMT_VFS_OLD;
break; goto set_qf_format;
case Opt_jqfmt_vfsv0: case Opt_jqfmt_vfsv0:
sbi->s_jquota_fmt = QFMT_VFS_V0; qfmt = QFMT_VFS_V0;
set_qf_format:
if ((sb_any_quota_enabled(sb) ||
sb_any_quota_suspended(sb)) &&
sbi->s_jquota_fmt != qfmt) {
printk(KERN_ERR "EXT4-fs: Cannot change "
"journaled quota options when "
"quota turned on.\n");
return 0;
}
sbi->s_jquota_fmt = qfmt;
break; break;
case Opt_quota: case Opt_quota:
case Opt_usrquota: case Opt_usrquota:
...@@ -1241,6 +1255,9 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1241,6 +1255,9 @@ static int parse_options (char *options, struct super_block *sb,
case Opt_quota: case Opt_quota:
case Opt_usrquota: case Opt_usrquota:
case Opt_grpquota: case Opt_grpquota:
printk(KERN_ERR
"EXT4-fs: quota options not supported.\n");
break;
case Opt_usrjquota: case Opt_usrjquota:
case Opt_grpjquota: case Opt_grpjquota:
case Opt_offusrjquota: case Opt_offusrjquota:
...@@ -1248,7 +1265,7 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1248,7 +1265,7 @@ static int parse_options (char *options, struct super_block *sb,
case Opt_jqfmt_vfsold: case Opt_jqfmt_vfsold:
case Opt_jqfmt_vfsv0: case Opt_jqfmt_vfsv0:
printk(KERN_ERR printk(KERN_ERR
"EXT4-fs: journalled quota options not " "EXT4-fs: journaled quota options not "
"supported.\n"); "supported.\n");
break; break;
case Opt_noquota: case Opt_noquota:
...@@ -1333,14 +1350,14 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1333,14 +1350,14 @@ static int parse_options (char *options, struct super_block *sb,
} }
if (!sbi->s_jquota_fmt) { if (!sbi->s_jquota_fmt) {
printk(KERN_ERR "EXT4-fs: journalled quota format " printk(KERN_ERR "EXT4-fs: journaled quota format "
"not specified.\n"); "not specified.\n");
return 0; return 0;
} }
} else { } else {
if (sbi->s_jquota_fmt) { if (sbi->s_jquota_fmt) {
printk(KERN_ERR "EXT4-fs: journalled quota format " printk(KERN_ERR "EXT4-fs: journaled quota format "
"specified with no journalling " "specified with no journaling "
"enabled.\n"); "enabled.\n");
return 0; return 0;
} }
...@@ -1581,7 +1598,7 @@ static void ext4_orphan_cleanup (struct super_block * sb, ...@@ -1581,7 +1598,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
int ret = ext4_quota_on_mount(sb, i); int ret = ext4_quota_on_mount(sb, i);
if (ret < 0) if (ret < 0)
printk(KERN_ERR printk(KERN_ERR
"EXT4-fs: Cannot turn on journalled " "EXT4-fs: Cannot turn on journaled "
"quota: error %d\n", ret); "quota: error %d\n", ret);
} }
} }
...@@ -3106,7 +3123,7 @@ static int ext4_release_dquot(struct dquot *dquot) ...@@ -3106,7 +3123,7 @@ static int ext4_release_dquot(struct dquot *dquot)
static int ext4_mark_dquot_dirty(struct dquot *dquot) static int ext4_mark_dquot_dirty(struct dquot *dquot)
{ {
/* Are we journalling quotas? */ /* Are we journaling quotas? */
if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
dquot_mark_dquot_dirty(dquot); dquot_mark_dquot_dirty(dquot);
...@@ -3153,23 +3170,42 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, ...@@ -3153,23 +3170,42 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
if (!test_opt(sb, QUOTA)) if (!test_opt(sb, QUOTA))
return -EINVAL; return -EINVAL;
/* Not journalling quota? */ /* When remounting, no checks are needed and in fact, path is NULL */
if ((!EXT4_SB(sb)->s_qf_names[USRQUOTA] && if (remount)
!EXT4_SB(sb)->s_qf_names[GRPQUOTA]) || remount)
return vfs_quota_on(sb, type, format_id, path, remount); return vfs_quota_on(sb, type, format_id, path, remount);
err = path_lookup(path, LOOKUP_FOLLOW, &nd); err = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (err) if (err)
return err; return err;
/* Quotafile not on the same filesystem? */ /* Quotafile not on the same filesystem? */
if (nd.path.mnt->mnt_sb != sb) { if (nd.path.mnt->mnt_sb != sb) {
path_put(&nd.path); path_put(&nd.path);
return -EXDEV; return -EXDEV;
} }
/* Journaling quota? */
if (EXT4_SB(sb)->s_qf_names[type]) {
/* Quotafile not of fs root? */ /* Quotafile not of fs root? */
if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
printk(KERN_WARNING printk(KERN_WARNING
"EXT4-fs: Quota file not on filesystem root. " "EXT4-fs: Quota file not on filesystem root. "
"Journalled quota will not work.\n"); "Journaled quota will not work.\n");
}
/*
* When we journal data on quota file, we have to flush journal to see
* all updates to the file when we bypass pagecache...
*/
if (ext4_should_journal_data(nd.path.dentry->d_inode)) {
/*
* We don't need to lock updates but journal_flush() could
* otherwise be livelocked...
*/
jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
jbd2_journal_flush(EXT4_SB(sb)->s_journal);
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
}
path_put(&nd.path); path_put(&nd.path);
return vfs_quota_on(sb, type, format_id, path, remount); return vfs_quota_on(sb, type, format_id, path, remount);
} }
......
...@@ -560,7 +560,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) ...@@ -560,7 +560,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
* transaction! Now comes the tricky part: we need to write out * transaction! Now comes the tricky part: we need to write out
* metadata. Loop over the transaction's entire buffer list: * metadata. Loop over the transaction's entire buffer list:
*/ */
spin_lock(&journal->j_state_lock);
commit_transaction->t_state = T_COMMIT; commit_transaction->t_state = T_COMMIT;
spin_unlock(&journal->j_state_lock);
stats.u.run.rs_logging = jiffies; stats.u.run.rs_logging = jiffies;
stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing, stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
......
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