Ext4 bug fixes (including a regression fix) for 5.5
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAl3/fDEACgkQ8vlZVpUN gaMZ6Qf/f973waBpA1E9GgAvB4AymRvGbqPJhW2lDDhEl36oXVpUw6EgIKWgNQPS HP6NhYXZakrpEak6Uk2MtiTmcm+6lqDJ+bCslCMylNh9/Y1yUrED2r8l7S3nGv4g hVB7Eah7E+sutDyrDQhYhcQo3GJjt8CbwRLgo8fbhSVrZ7qdfb0lWQmVnruc+72b 3VAeMzPJb0wRY6myxLN4Pw6oEMR1WKVsXm3I9gNXboE2XvgVvnNn2tJxP+xml8rW uGxzWTo7QQNN2bUyjZBa6Mm44lMpHr7JT0nMwkIGV5v3eAYuBgeSwIXUskfw29q7 sP9xNP2voU3M6TyWuT0+cHpoeZasPg== =K63f -----END PGP SIGNATURE----- Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 bug fixes from Ted Ts'o: "Ext4 bug fixes, including a regression fix" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: clarify impact of 'commit' mount option ext4: fix unused-but-set-variable warning in ext4_add_entry() jbd2: fix kernel-doc notation warning ext4: use RCU API in debug_print_tree ext4: validate the debug_want_extra_isize mount option at parse time ext4: reserve revoke credits in __ext4_new_inode ext4: unlock on error in ext4_expand_extra_isize() ext4: optimize __ext4_check_dir_entry() ext4: check for directory entries too close to block end ext4: fix ext4_empty_dir() for directories with holesalistair/sunxi64-5.5-dsi
commit
a396560706
|
@ -181,14 +181,17 @@ When mounting an ext4 filesystem, the following option are accepted:
|
||||||
system after its metadata has been committed to the journal.
|
system after its metadata has been committed to the journal.
|
||||||
|
|
||||||
commit=nrsec (*)
|
commit=nrsec (*)
|
||||||
Ext4 can be told to sync all its data and metadata every 'nrsec'
|
This setting limits the maximum age of the running transaction to
|
||||||
seconds. The default value is 5 seconds. This means that if you lose
|
'nrsec' seconds. The default value is 5 seconds. This means that if
|
||||||
your power, you will lose as much as the latest 5 seconds of work (your
|
you lose your power, you will lose as much as the latest 5 seconds of
|
||||||
filesystem will not be damaged though, thanks to the journaling). This
|
metadata changes (your filesystem will not be damaged though, thanks
|
||||||
default value (or any low value) will hurt performance, but it's good
|
to the journaling). This default value (or any low value) will hurt
|
||||||
for data-safety. Setting it to 0 will have the same effect as leaving
|
performance, but it's good for data-safety. Setting it to 0 will have
|
||||||
it at the default (5 seconds). Setting it to very large values will
|
the same effect as leaving it at the default (5 seconds). Setting it
|
||||||
improve performance.
|
to very large values will improve performance. Note that due to
|
||||||
|
delayed allocation even older data can be lost on power failure since
|
||||||
|
writeback of those data begins only after time set in
|
||||||
|
/proc/sys/vm/dirty_expire_centisecs.
|
||||||
|
|
||||||
barrier=<0|1(*)>, barrier(*), nobarrier
|
barrier=<0|1(*)>, barrier(*), nobarrier
|
||||||
This enables/disables the use of write barriers in the jbd code.
|
This enables/disables the use of write barriers in the jbd code.
|
||||||
|
|
|
@ -133,10 +133,13 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
|
||||||
{
|
{
|
||||||
struct rb_node *node;
|
struct rb_node *node;
|
||||||
struct ext4_system_zone *entry;
|
struct ext4_system_zone *entry;
|
||||||
|
struct ext4_system_blocks *system_blks;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
|
|
||||||
printk(KERN_INFO "System zones: ");
|
printk(KERN_INFO "System zones: ");
|
||||||
node = rb_first(&sbi->system_blks->root);
|
rcu_read_lock();
|
||||||
|
system_blks = rcu_dereference(sbi->system_blks);
|
||||||
|
node = rb_first(&system_blks->root);
|
||||||
while (node) {
|
while (node) {
|
||||||
entry = rb_entry(node, struct ext4_system_zone, node);
|
entry = rb_entry(node, struct ext4_system_zone, node);
|
||||||
printk(KERN_CONT "%s%llu-%llu", first ? "" : ", ",
|
printk(KERN_CONT "%s%llu-%llu", first ? "" : ", ",
|
||||||
|
@ -144,6 +147,7 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
|
||||||
first = 0;
|
first = 0;
|
||||||
node = rb_next(node);
|
node = rb_next(node);
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
printk(KERN_CONT "\n");
|
printk(KERN_CONT "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
|
||||||
const char *error_msg = NULL;
|
const char *error_msg = NULL;
|
||||||
const int rlen = ext4_rec_len_from_disk(de->rec_len,
|
const int rlen = ext4_rec_len_from_disk(de->rec_len,
|
||||||
dir->i_sb->s_blocksize);
|
dir->i_sb->s_blocksize);
|
||||||
|
const int next_offset = ((char *) de - buf) + rlen;
|
||||||
|
|
||||||
if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
|
if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
|
||||||
error_msg = "rec_len is smaller than minimal";
|
error_msg = "rec_len is smaller than minimal";
|
||||||
|
@ -79,8 +80,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
|
||||||
error_msg = "rec_len % 4 != 0";
|
error_msg = "rec_len % 4 != 0";
|
||||||
else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
|
else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
|
||||||
error_msg = "rec_len is too small for name_len";
|
error_msg = "rec_len is too small for name_len";
|
||||||
else if (unlikely(((char *) de - buf) + rlen > size))
|
else if (unlikely(next_offset > size))
|
||||||
error_msg = "directory entry overrun";
|
error_msg = "directory entry overrun";
|
||||||
|
else if (unlikely(next_offset > size - EXT4_DIR_REC_LEN(1) &&
|
||||||
|
next_offset != size))
|
||||||
|
error_msg = "directory entry too close to block end";
|
||||||
else if (unlikely(le32_to_cpu(de->inode) >
|
else if (unlikely(le32_to_cpu(de->inode) >
|
||||||
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
|
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
|
||||||
error_msg = "inode out of bounds";
|
error_msg = "inode out of bounds";
|
||||||
|
|
|
@ -921,8 +921,8 @@ repeat_in_this_group:
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
BUG_ON(nblocks <= 0);
|
BUG_ON(nblocks <= 0);
|
||||||
handle = __ext4_journal_start_sb(dir->i_sb, line_no,
|
handle = __ext4_journal_start_sb(dir->i_sb, line_no,
|
||||||
handle_type, nblocks,
|
handle_type, nblocks, 0,
|
||||||
0, 0);
|
ext4_trans_default_revoke_credits(sb));
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
err = PTR_ERR(handle);
|
err = PTR_ERR(handle);
|
||||||
ext4_std_error(sb, err);
|
ext4_std_error(sb, err);
|
||||||
|
|
|
@ -5692,7 +5692,7 @@ int ext4_expand_extra_isize(struct inode *inode,
|
||||||
error = ext4_journal_get_write_access(handle, iloc->bh);
|
error = ext4_journal_get_write_access(handle, iloc->bh);
|
||||||
if (error) {
|
if (error) {
|
||||||
brelse(iloc->bh);
|
brelse(iloc->bh);
|
||||||
goto out_stop;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = __ext4_expand_extra_isize(inode, new_extra_isize, iloc,
|
error = __ext4_expand_extra_isize(inode, new_extra_isize, iloc,
|
||||||
|
@ -5702,8 +5702,8 @@ int ext4_expand_extra_isize(struct inode *inode,
|
||||||
if (!error)
|
if (!error)
|
||||||
error = rc;
|
error = rc;
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
ext4_write_unlock_xattr(inode, &no_expand);
|
ext4_write_unlock_xattr(inode, &no_expand);
|
||||||
out_stop:
|
|
||||||
ext4_journal_stop(handle);
|
ext4_journal_stop(handle);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2164,7 +2164,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
|
#ifdef CONFIG_UNICODE
|
||||||
struct ext4_sb_info *sbi;
|
struct ext4_sb_info *sbi;
|
||||||
|
#endif
|
||||||
struct ext4_filename fname;
|
struct ext4_filename fname;
|
||||||
int retval;
|
int retval;
|
||||||
int dx_fallback=0;
|
int dx_fallback=0;
|
||||||
|
@ -2176,12 +2178,12 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||||
|
|
||||||
sb = dir->i_sb;
|
sb = dir->i_sb;
|
||||||
sbi = EXT4_SB(sb);
|
|
||||||
blocksize = sb->s_blocksize;
|
blocksize = sb->s_blocksize;
|
||||||
if (!dentry->d_name.len)
|
if (!dentry->d_name.len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
#ifdef CONFIG_UNICODE
|
#ifdef CONFIG_UNICODE
|
||||||
|
sbi = EXT4_SB(sb);
|
||||||
if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
|
if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
|
||||||
sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name))
|
sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2822,7 +2824,7 @@ bool ext4_empty_dir(struct inode *inode)
|
||||||
{
|
{
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct ext4_dir_entry_2 *de, *de1;
|
struct ext4_dir_entry_2 *de;
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
|
|
||||||
if (ext4_has_inline_data(inode)) {
|
if (ext4_has_inline_data(inode)) {
|
||||||
|
@ -2847,19 +2849,25 @@ bool ext4_empty_dir(struct inode *inode)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
||||||
de1 = ext4_next_entry(de, sb->s_blocksize);
|
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
|
||||||
if (le32_to_cpu(de->inode) != inode->i_ino ||
|
0) ||
|
||||||
le32_to_cpu(de1->inode) == 0 ||
|
le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) {
|
||||||
strcmp(".", de->name) || strcmp("..", de1->name)) {
|
ext4_warning_inode(inode, "directory missing '.'");
|
||||||
ext4_warning_inode(inode, "directory missing '.' and/or '..'");
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) +
|
offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
|
||||||
ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize);
|
de = ext4_next_entry(de, sb->s_blocksize);
|
||||||
de = ext4_next_entry(de1, sb->s_blocksize);
|
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
|
||||||
|
offset) ||
|
||||||
|
le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
|
||||||
|
ext4_warning_inode(inode, "directory missing '..'");
|
||||||
|
brelse(bh);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
|
||||||
while (offset < inode->i_size) {
|
while (offset < inode->i_size) {
|
||||||
if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
|
if (!(offset & (sb->s_blocksize - 1))) {
|
||||||
unsigned int lblock;
|
unsigned int lblock;
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
|
lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
|
||||||
|
@ -2870,12 +2878,11 @@ bool ext4_empty_dir(struct inode *inode)
|
||||||
}
|
}
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
return true;
|
return true;
|
||||||
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
|
||||||
}
|
}
|
||||||
|
de = (struct ext4_dir_entry_2 *) (bh->b_data +
|
||||||
|
(offset & (sb->s_blocksize - 1)));
|
||||||
if (ext4_check_dir_entry(inode, NULL, de, bh,
|
if (ext4_check_dir_entry(inode, NULL, de, bh,
|
||||||
bh->b_data, bh->b_size, offset)) {
|
bh->b_data, bh->b_size, offset)) {
|
||||||
de = (struct ext4_dir_entry_2 *)(bh->b_data +
|
|
||||||
sb->s_blocksize);
|
|
||||||
offset = (offset | (sb->s_blocksize - 1)) + 1;
|
offset = (offset | (sb->s_blocksize - 1)) + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2884,7 +2891,6 @@ bool ext4_empty_dir(struct inode *inode)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
|
offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
|
||||||
de = ext4_next_entry(de, sb->s_blocksize);
|
|
||||||
}
|
}
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
return true;
|
return true;
|
||||||
|
|
143
fs/ext4/super.c
143
fs/ext4/super.c
|
@ -1900,6 +1900,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
|
||||||
}
|
}
|
||||||
sbi->s_commit_interval = HZ * arg;
|
sbi->s_commit_interval = HZ * arg;
|
||||||
} else if (token == Opt_debug_want_extra_isize) {
|
} else if (token == Opt_debug_want_extra_isize) {
|
||||||
|
if ((arg & 1) ||
|
||||||
|
(arg < 4) ||
|
||||||
|
(arg > (sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) {
|
||||||
|
ext4_msg(sb, KERN_ERR,
|
||||||
|
"Invalid want_extra_isize %d", arg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
sbi->s_want_extra_isize = arg;
|
sbi->s_want_extra_isize = arg;
|
||||||
} else if (token == Opt_max_batch_time) {
|
} else if (token == Opt_max_batch_time) {
|
||||||
sbi->s_max_batch_time = arg;
|
sbi->s_max_batch_time = arg;
|
||||||
|
@ -3554,40 +3561,6 @@ int ext4_calculate_overhead(struct super_block *sb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ext4_clamp_want_extra_isize(struct super_block *sb)
|
|
||||||
{
|
|
||||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
|
||||||
struct ext4_super_block *es = sbi->s_es;
|
|
||||||
unsigned def_extra_isize = sizeof(struct ext4_inode) -
|
|
||||||
EXT4_GOOD_OLD_INODE_SIZE;
|
|
||||||
|
|
||||||
if (sbi->s_inode_size == EXT4_GOOD_OLD_INODE_SIZE) {
|
|
||||||
sbi->s_want_extra_isize = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sbi->s_want_extra_isize < 4) {
|
|
||||||
sbi->s_want_extra_isize = def_extra_isize;
|
|
||||||
if (ext4_has_feature_extra_isize(sb)) {
|
|
||||||
if (sbi->s_want_extra_isize <
|
|
||||||
le16_to_cpu(es->s_want_extra_isize))
|
|
||||||
sbi->s_want_extra_isize =
|
|
||||||
le16_to_cpu(es->s_want_extra_isize);
|
|
||||||
if (sbi->s_want_extra_isize <
|
|
||||||
le16_to_cpu(es->s_min_extra_isize))
|
|
||||||
sbi->s_want_extra_isize =
|
|
||||||
le16_to_cpu(es->s_min_extra_isize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Check if enough inode space is available */
|
|
||||||
if ((sbi->s_want_extra_isize > sbi->s_inode_size) ||
|
|
||||||
(EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
|
|
||||||
sbi->s_inode_size)) {
|
|
||||||
sbi->s_want_extra_isize = def_extra_isize;
|
|
||||||
ext4_msg(sb, KERN_INFO,
|
|
||||||
"required extra inode space not available");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ext4_set_resv_clusters(struct super_block *sb)
|
static void ext4_set_resv_clusters(struct super_block *sb)
|
||||||
{
|
{
|
||||||
ext4_fsblk_t resv_clusters;
|
ext4_fsblk_t resv_clusters;
|
||||||
|
@ -3795,6 +3768,68 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
*/
|
*/
|
||||||
sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
|
sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
|
||||||
|
|
||||||
|
if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
|
||||||
|
sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
|
||||||
|
sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
|
||||||
|
} else {
|
||||||
|
sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
|
||||||
|
sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
|
||||||
|
if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
|
||||||
|
ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
|
||||||
|
sbi->s_first_ino);
|
||||||
|
goto failed_mount;
|
||||||
|
}
|
||||||
|
if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
|
||||||
|
(!is_power_of_2(sbi->s_inode_size)) ||
|
||||||
|
(sbi->s_inode_size > blocksize)) {
|
||||||
|
ext4_msg(sb, KERN_ERR,
|
||||||
|
"unsupported inode size: %d",
|
||||||
|
sbi->s_inode_size);
|
||||||
|
goto failed_mount;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* i_atime_extra is the last extra field available for
|
||||||
|
* [acm]times in struct ext4_inode. Checking for that
|
||||||
|
* field should suffice to ensure we have extra space
|
||||||
|
* for all three.
|
||||||
|
*/
|
||||||
|
if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
|
||||||
|
sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
|
||||||
|
sb->s_time_gran = 1;
|
||||||
|
sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
|
||||||
|
} else {
|
||||||
|
sb->s_time_gran = NSEC_PER_SEC;
|
||||||
|
sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
|
||||||
|
}
|
||||||
|
sb->s_time_min = EXT4_TIMESTAMP_MIN;
|
||||||
|
}
|
||||||
|
if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
|
||||||
|
sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
|
||||||
|
EXT4_GOOD_OLD_INODE_SIZE;
|
||||||
|
if (ext4_has_feature_extra_isize(sb)) {
|
||||||
|
unsigned v, max = (sbi->s_inode_size -
|
||||||
|
EXT4_GOOD_OLD_INODE_SIZE);
|
||||||
|
|
||||||
|
v = le16_to_cpu(es->s_want_extra_isize);
|
||||||
|
if (v > max) {
|
||||||
|
ext4_msg(sb, KERN_ERR,
|
||||||
|
"bad s_want_extra_isize: %d", v);
|
||||||
|
goto failed_mount;
|
||||||
|
}
|
||||||
|
if (sbi->s_want_extra_isize < v)
|
||||||
|
sbi->s_want_extra_isize = v;
|
||||||
|
|
||||||
|
v = le16_to_cpu(es->s_min_extra_isize);
|
||||||
|
if (v > max) {
|
||||||
|
ext4_msg(sb, KERN_ERR,
|
||||||
|
"bad s_min_extra_isize: %d", v);
|
||||||
|
goto failed_mount;
|
||||||
|
}
|
||||||
|
if (sbi->s_want_extra_isize < v)
|
||||||
|
sbi->s_want_extra_isize = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sbi->s_es->s_mount_opts[0]) {
|
if (sbi->s_es->s_mount_opts[0]) {
|
||||||
char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
|
char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
|
||||||
sizeof(sbi->s_es->s_mount_opts),
|
sizeof(sbi->s_es->s_mount_opts),
|
||||||
|
@ -4033,42 +4068,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
has_huge_files);
|
has_huge_files);
|
||||||
sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
|
sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
|
||||||
|
|
||||||
if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
|
|
||||||
sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
|
|
||||||
sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
|
|
||||||
} else {
|
|
||||||
sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
|
|
||||||
sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
|
|
||||||
if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
|
|
||||||
ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
|
|
||||||
sbi->s_first_ino);
|
|
||||||
goto failed_mount;
|
|
||||||
}
|
|
||||||
if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
|
|
||||||
(!is_power_of_2(sbi->s_inode_size)) ||
|
|
||||||
(sbi->s_inode_size > blocksize)) {
|
|
||||||
ext4_msg(sb, KERN_ERR,
|
|
||||||
"unsupported inode size: %d",
|
|
||||||
sbi->s_inode_size);
|
|
||||||
goto failed_mount;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* i_atime_extra is the last extra field available for [acm]times in
|
|
||||||
* struct ext4_inode. Checking for that field should suffice to ensure
|
|
||||||
* we have extra space for all three.
|
|
||||||
*/
|
|
||||||
if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
|
|
||||||
sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
|
|
||||||
sb->s_time_gran = 1;
|
|
||||||
sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
|
|
||||||
} else {
|
|
||||||
sb->s_time_gran = NSEC_PER_SEC;
|
|
||||||
sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb->s_time_min = EXT4_TIMESTAMP_MIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
|
sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
|
||||||
if (ext4_has_feature_64bit(sb)) {
|
if (ext4_has_feature_64bit(sb)) {
|
||||||
if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
|
if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
|
||||||
|
@ -4517,8 +4516,6 @@ no_journal:
|
||||||
} else if (ret)
|
} else if (ret)
|
||||||
goto failed_mount4a;
|
goto failed_mount4a;
|
||||||
|
|
||||||
ext4_clamp_want_extra_isize(sb);
|
|
||||||
|
|
||||||
ext4_set_resv_clusters(sb);
|
ext4_set_resv_clusters(sb);
|
||||||
|
|
||||||
err = ext4_setup_system_zone(sb);
|
err = ext4_setup_system_zone(sb);
|
||||||
|
@ -5306,8 +5303,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
||||||
goto restore_opts;
|
goto restore_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
ext4_clamp_want_extra_isize(sb);
|
|
||||||
|
|
||||||
if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
|
if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
|
||||||
test_opt(sb, JOURNAL_CHECKSUM)) {
|
test_opt(sb, JOURNAL_CHECKSUM)) {
|
||||||
ext4_msg(sb, KERN_ERR, "changing journal_checksum "
|
ext4_msg(sb, KERN_ERR, "changing journal_checksum "
|
||||||
|
|
|
@ -457,7 +457,7 @@ struct jbd2_revoke_table_s;
|
||||||
* @h_journal: Which journal handle belongs to - used iff h_reserved set.
|
* @h_journal: Which journal handle belongs to - used iff h_reserved set.
|
||||||
* @h_rsv_handle: Handle reserved for finishing the logical operation.
|
* @h_rsv_handle: Handle reserved for finishing the logical operation.
|
||||||
* @h_total_credits: Number of remaining buffers we are allowed to add to
|
* @h_total_credits: Number of remaining buffers we are allowed to add to
|
||||||
journal. These are dirty buffers and revoke descriptor blocks.
|
* journal. These are dirty buffers and revoke descriptor blocks.
|
||||||
* @h_revoke_credits: Number of remaining revoke records available for handle
|
* @h_revoke_credits: Number of remaining revoke records available for handle
|
||||||
* @h_ref: Reference count on this handle.
|
* @h_ref: Reference count on this handle.
|
||||||
* @h_err: Field for caller's use to track errors through large fs operations.
|
* @h_err: Field for caller's use to track errors through large fs operations.
|
||||||
|
|
Loading…
Reference in New Issue