Skip to content

Commit

Permalink
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
Linus Torvalds committed May 19, 2019
2 parents d8848ee + 2c1d0e3 commit c4d36b6
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 65 deletions.
8 changes: 7 additions & 1 deletion fs/ext4/block_validity.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down Expand Up @@ -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 &&
Expand Down
17 changes: 15 additions & 2 deletions fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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))
Expand All @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions fs/ext4/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/fsmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion fs/ext4/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
49 changes: 31 additions & 18 deletions fs/jbd2/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

/*
Expand All @@ -2668,21 +2675,27 @@ 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;
}

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();
}
Expand Down
32 changes: 20 additions & 12 deletions fs/jbd2/revoke.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions fs/jbd2/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
28 changes: 7 additions & 21 deletions fs/unicode/README.utf8data
Original file line number Diff line number Diff line change
Expand Up @@ -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"):

Expand Down
2 changes: 2 additions & 0 deletions fs/unicode/utf8-norm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
8 changes: 5 additions & 3 deletions include/linux/jbd2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

/*
Expand Down Expand Up @@ -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 *);
Expand Down

0 comments on commit c4d36b6

Please sign in to comment.