Commit c4d36b63 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o:
 "Some bug fixes, and an update to the URL's for the final version of
  Unicode 12.1.0"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: avoid panic during forced reboot due to aborted journal
  ext4: fix block validity checks for journal inodes using indirect blocks
  unicode: update to Unicode 12.1.0 final
  unicode: add missing check for an error return from utf8lookup()
  ext4: fix miscellaneous sparse warnings
  ext4: unsigned int compared against zero
  ext4: fix use-after-free in dx_release()
  ext4: fix data corruption caused by overlapping unaligned and aligned IO
  jbd2: fix potential double free
  ext4: zero out the unused memory region in the extent tree block
parents d8848eef 2c1d0e36
......@@ -142,7 +142,8 @@ static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino)
struct inode *inode;
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_map_blocks map;
u32 i = 0, err = 0, num, n;
u32 i = 0, num;
int err = 0, n;
if ((ino < EXT4_ROOT_INO) ||
(ino > le32_to_cpu(sbi->s_es->s_inodes_count)))
......@@ -276,6 +277,11 @@ int ext4_check_blockref(const char *function, unsigned int line,
__le32 *bref = p;
unsigned int blk;
if (ext4_has_feature_journal(inode->i_sb) &&
(inode->i_ino ==
le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
return 0;
while (bref < p+max) {
blk = le32_to_cpu(*bref++);
if (blk &&
......
......@@ -1035,6 +1035,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
__le32 border;
ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */
int err = 0;
size_t ext_size = 0;
/* make decision: where to split? */
/* FIXME: now decision is simplest: at current extent */
......@@ -1126,6 +1127,10 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
le16_add_cpu(&neh->eh_entries, m);
}
/* zero out unused area in the extent block */
ext_size = sizeof(struct ext4_extent_header) +
sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries);
memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size);
ext4_extent_block_csum_set(inode, neh);
set_buffer_uptodate(bh);
unlock_buffer(bh);
......@@ -1205,6 +1210,11 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
sizeof(struct ext4_extent_idx) * m);
le16_add_cpu(&neh->eh_entries, m);
}
/* zero out unused area in the extent block */
ext_size = sizeof(struct ext4_extent_header) +
(sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries));
memset(bh->b_data + ext_size, 0,
inode->i_sb->s_blocksize - ext_size);
ext4_extent_block_csum_set(inode, neh);
set_buffer_uptodate(bh);
unlock_buffer(bh);
......@@ -1270,6 +1280,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
ext4_fsblk_t newblock, goal = 0;
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
int err = 0;
size_t ext_size = 0;
/* Try to prepend new index to old one */
if (ext_depth(inode))
......@@ -1295,9 +1306,11 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
goto out;
}
ext_size = sizeof(EXT4_I(inode)->i_data);
/* move top-level index/leaf into new block */
memmove(bh->b_data, EXT4_I(inode)->i_data,
sizeof(EXT4_I(inode)->i_data));
memmove(bh->b_data, EXT4_I(inode)->i_data, ext_size);
/* zero out unused area in the extent block */
memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size);
/* set size of new block */
neh = ext_block_hdr(bh);
......
......@@ -264,6 +264,13 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
}
ret = __generic_file_write_iter(iocb, from);
/*
* Unaligned direct AIO must be the only IO in flight. Otherwise
* overlapping aligned IO after unaligned might result in data
* corruption.
*/
if (ret == -EIOCBQUEUED && unaligned_aio)
ext4_unwritten_wait(inode);
inode_unlock(inode);
if (ret > 0)
......
......@@ -626,7 +626,7 @@ int ext4_getfsmap(struct super_block *sb, struct ext4_fsmap_head *head,
{
struct ext4_fsmap dkeys[2]; /* per-dev keys */
struct ext4_getfsmap_dev handlers[EXT4_GETFSMAP_DEVS];
struct ext4_getfsmap_info info = {0};
struct ext4_getfsmap_info info = { NULL };
int i;
int error = 0;
......
......@@ -608,7 +608,7 @@ static int ext4_getfsmap_format(struct ext4_fsmap *xfm, void *priv)
static int ext4_ioc_getfsmap(struct super_block *sb,
struct fsmap_head __user *arg)
{
struct getfsmap_info info = {0};
struct getfsmap_info info = { NULL };
struct ext4_fsmap_head xhead = {0};
struct fsmap_head head;
bool aborted = false;
......
......@@ -872,12 +872,15 @@ static void dx_release(struct dx_frame *frames)
{
struct dx_root_info *info;
int i;
unsigned int indirect_levels;
if (frames[0].bh == NULL)
return;
info = &((struct dx_root *)frames[0].bh->b_data)->info;
for (i = 0; i <= info->indirect_levels; i++) {
/* save local copy, "info" may be freed after brelse() */
indirect_levels = info->indirect_levels;
for (i = 0; i <= indirect_levels; i++) {
if (frames[i].bh == NULL)
break;
brelse(frames[i].bh);
......
......@@ -699,7 +699,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
save_error_info(sb, function, line);
}
if (test_opt(sb, ERRORS_PANIC)) {
if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) {
if (EXT4_SB(sb)->s_journal &&
!(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
return;
......@@ -4661,7 +4661,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
for (i = 0; i < EXT4_MAXQUOTAS; i++)
kfree(sbi->s_qf_names[i]);
kfree(get_qf_name(sb, sbi, i));
#endif
ext4_blkdev_remove(sbi);
brelse(bh);
......
......@@ -2375,22 +2375,19 @@ static struct kmem_cache *jbd2_journal_head_cache;
static atomic_t nr_journal_heads = ATOMIC_INIT(0);
#endif
static int jbd2_journal_init_journal_head_cache(void)
static int __init jbd2_journal_init_journal_head_cache(void)
{
int retval;
J_ASSERT(jbd2_journal_head_cache == NULL);
J_ASSERT(!jbd2_journal_head_cache);
jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head",
sizeof(struct journal_head),
0, /* offset */
SLAB_TEMPORARY | SLAB_TYPESAFE_BY_RCU,
NULL); /* ctor */
retval = 0;
if (!jbd2_journal_head_cache) {
retval = -ENOMEM;
printk(KERN_EMERG "JBD2: no memory for journal_head cache\n");
return -ENOMEM;
}
return retval;
return 0;
}
static void jbd2_journal_destroy_journal_head_cache(void)
......@@ -2636,28 +2633,38 @@ static void __exit jbd2_remove_jbd_stats_proc_entry(void)
struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache;
static int __init jbd2_journal_init_inode_cache(void)
{
J_ASSERT(!jbd2_inode_cache);
jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0);
if (!jbd2_inode_cache) {
pr_emerg("JBD2: failed to create inode cache\n");
return -ENOMEM;
}
return 0;
}
static int __init jbd2_journal_init_handle_cache(void)
{
J_ASSERT(!jbd2_handle_cache);
jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY);
if (jbd2_handle_cache == NULL) {
if (!jbd2_handle_cache) {
printk(KERN_EMERG "JBD2: failed to create handle cache\n");
return -ENOMEM;
}
jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0);
if (jbd2_inode_cache == NULL) {
printk(KERN_EMERG "JBD2: failed to create inode cache\n");
kmem_cache_destroy(jbd2_handle_cache);
return -ENOMEM;
}
return 0;
}
static void jbd2_journal_destroy_inode_cache(void)
{
kmem_cache_destroy(jbd2_inode_cache);
jbd2_inode_cache = NULL;
}
static void jbd2_journal_destroy_handle_cache(void)
{
kmem_cache_destroy(jbd2_handle_cache);
jbd2_handle_cache = NULL;
kmem_cache_destroy(jbd2_inode_cache);
jbd2_inode_cache = NULL;
}
/*
......@@ -2668,11 +2675,15 @@ static int __init journal_init_caches(void)
{
int ret;
ret = jbd2_journal_init_revoke_caches();
ret = jbd2_journal_init_revoke_record_cache();
if (ret == 0)
ret = jbd2_journal_init_revoke_table_cache();
if (ret == 0)
ret = jbd2_journal_init_journal_head_cache();
if (ret == 0)
ret = jbd2_journal_init_handle_cache();
if (ret == 0)
ret = jbd2_journal_init_inode_cache();
if (ret == 0)
ret = jbd2_journal_init_transaction_cache();
return ret;
......@@ -2680,9 +2691,11 @@ static int __init journal_init_caches(void)
static void jbd2_journal_destroy_caches(void)
{
jbd2_journal_destroy_revoke_caches();
jbd2_journal_destroy_revoke_record_cache();
jbd2_journal_destroy_revoke_table_cache();
jbd2_journal_destroy_journal_head_cache();
jbd2_journal_destroy_handle_cache();
jbd2_journal_destroy_inode_cache();
jbd2_journal_destroy_transaction_cache();
jbd2_journal_destroy_slabs();
}
......
......@@ -178,33 +178,41 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal,
return NULL;
}
void jbd2_journal_destroy_revoke_caches(void)
void jbd2_journal_destroy_revoke_record_cache(void)
{
kmem_cache_destroy(jbd2_revoke_record_cache);
jbd2_revoke_record_cache = NULL;
}
void jbd2_journal_destroy_revoke_table_cache(void)
{
kmem_cache_destroy(jbd2_revoke_table_cache);
jbd2_revoke_table_cache = NULL;
}
int __init jbd2_journal_init_revoke_caches(void)
int __init jbd2_journal_init_revoke_record_cache(void)
{
J_ASSERT(!jbd2_revoke_record_cache);
J_ASSERT(!jbd2_revoke_table_cache);
jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s,
SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY);
if (!jbd2_revoke_record_cache)
goto record_cache_failure;
if (!jbd2_revoke_record_cache) {
pr_emerg("JBD2: failed to create revoke_record cache\n");
return -ENOMEM;
}
return 0;
}
int __init jbd2_journal_init_revoke_table_cache(void)
{
J_ASSERT(!jbd2_revoke_table_cache);
jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s,
SLAB_TEMPORARY);
if (!jbd2_revoke_table_cache)
goto table_cache_failure;
return 0;
table_cache_failure:
jbd2_journal_destroy_revoke_caches();
record_cache_failure:
if (!jbd2_revoke_table_cache) {
pr_emerg("JBD2: failed to create revoke_table cache\n");
return -ENOMEM;
}
return 0;
}
static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size)
......
......@@ -42,9 +42,11 @@ int __init jbd2_journal_init_transaction_cache(void)
0,
SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
NULL);
if (transaction_cache)
return 0;
return -ENOMEM;
if (!transaction_cache) {
pr_emerg("JBD2: failed to create transaction cache\n");
return -ENOMEM;
}
return 0;
}
void jbd2_journal_destroy_transaction_cache(void)
......
......@@ -5,29 +5,15 @@ The full set of files can be found here:
http://www.unicode.org/Public/12.1.0/ucd/
Note!
The URL's listed below are not stable. That's because Unicode 12.1.0
has not been officially released yet; it is scheduled to be released
on May 8, 2019. We taking Unicode 12.1.0 a few weeks early because it
contains a new Japanese character which is required in order to
specify Japenese dates after May 1, 2019, when Crown Prince Naruhito
ascends to the Chrysanthemum Throne. (Isn't internationalization fun?
The abdication of Emperor Akihito of Japan is requiring dozens of
software packages to be updated with only a month's notice. :-)
We will update the URL's (and any needed changes to the checksums)
after the final Unicode 12.1.0 is released.
Individual source links:
https://www.unicode.org/Public/12.1.0/ucd/CaseFolding-12.1.0d2.txt
https://www.unicode.org/Public/12.1.0/ucd/DerivedAge-12.1.0d3.txt
https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass-12.1.0d2.txt
https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties-12.1.0d2.txt
https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections-12.1.0d1.txt
https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest-12.1.0d3.txt
https://www.unicode.org/Public/12.1.0/ucd/UnicodeData-12.1.0d2.txt
https://www.unicode.org/Public/12.1.0/ucd/CaseFolding.txt
https://www.unicode.org/Public/12.1.0/ucd/DerivedAge.txt
https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass.txt
https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties.txt
https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections.txt
https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest.txt
https://www.unicode.org/Public/12.1.0/ucd/UnicodeData.txt
md5sums (verify by running "md5sum -c README.utf8data"):
......
......@@ -714,6 +714,8 @@ int utf8byte(struct utf8cursor *u8c)
}
leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s);
if (!leaf)
return -1;
ccc = LEAF_CCC(leaf);
}
......
......@@ -1318,7 +1318,7 @@ extern void __wait_on_journal (journal_t *);
/* Transaction cache support */
extern void jbd2_journal_destroy_transaction_cache(void);
extern int jbd2_journal_init_transaction_cache(void);
extern int __init jbd2_journal_init_transaction_cache(void);
extern void jbd2_journal_free_transaction(transaction_t *);
/*
......@@ -1446,8 +1446,10 @@ static inline void jbd2_free_inode(struct jbd2_inode *jinode)
/* Primary revoke support */
#define JOURNAL_REVOKE_DEFAULT_HASH 256
extern int jbd2_journal_init_revoke(journal_t *, int);
extern void jbd2_journal_destroy_revoke_caches(void);
extern int jbd2_journal_init_revoke_caches(void);
extern void jbd2_journal_destroy_revoke_record_cache(void);
extern void jbd2_journal_destroy_revoke_table_cache(void);
extern int __init jbd2_journal_init_revoke_record_cache(void);
extern int __init jbd2_journal_init_revoke_table_cache(void);
extern void jbd2_journal_destroy_revoke(journal_t *);
extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *);
......
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