diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-19 16:44:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-19 16:44:12 -0500 |
commit | 020ecbba0548cefc91c3c5de32c28a62bcf37ed9 (patch) | |
tree | 2e6ba63b7332e15b30a2d7f7d930cde2ae4bfefe | |
parent | ce6b71432d42afe5c3ae25ab2980304c32ecb915 (diff) | |
parent | 74dae4278546b897eb81784fdfcce872ddd8b2b8 (diff) |
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bugfixes from Ted Ts'o:
"Miscellaneous ext4 bug fixes for v4.5"
* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix crashes in dioread_nolock mode
ext4: fix bh->b_state corruption
ext4: fix memleak in ext4_readdir()
ext4: remove unused parameter "newblock" in convert_initialized_extent()
ext4: don't read blocks from disk after extents being swapped
ext4: fix potential integer overflow
ext4: add a line break for proc mb_groups display
ext4: ioctl: fix erroneous return value
ext4: fix scheduling in atomic on group checksum failure
ext4 crypto: move context consistency check to ext4_file_open()
ext4 crypto: revalidate dentry after adding or removing the key
-rw-r--r-- | fs/ext4/balloc.c | 7 | ||||
-rw-r--r-- | fs/ext4/crypto.c | 56 | ||||
-rw-r--r-- | fs/ext4/dir.c | 13 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/extents.c | 4 | ||||
-rw-r--r-- | fs/ext4/file.c | 9 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 6 | ||||
-rw-r--r-- | fs/ext4/inode.c | 72 | ||||
-rw-r--r-- | fs/ext4/ioctl.c | 2 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 2 | ||||
-rw-r--r-- | fs/ext4/move_extent.c | 15 | ||||
-rw-r--r-- | fs/ext4/namei.c | 26 | ||||
-rw-r--r-- | fs/ext4/resize.c | 2 |
13 files changed, 176 insertions, 39 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index ec0668a60678..fe1f50fe764f 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -191,7 +191,6 @@ static int ext4_init_block_bitmap(struct super_block *sb, | |||
191 | /* If checksum is bad mark all blocks used to prevent allocation | 191 | /* If checksum is bad mark all blocks used to prevent allocation |
192 | * essentially implementing a per-group read-only flag. */ | 192 | * essentially implementing a per-group read-only flag. */ |
193 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { | 193 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { |
194 | ext4_error(sb, "Checksum bad for group %u", block_group); | ||
195 | grp = ext4_get_group_info(sb, block_group); | 194 | grp = ext4_get_group_info(sb, block_group); |
196 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | 195 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) |
197 | percpu_counter_sub(&sbi->s_freeclusters_counter, | 196 | percpu_counter_sub(&sbi->s_freeclusters_counter, |
@@ -442,14 +441,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
442 | } | 441 | } |
443 | ext4_lock_group(sb, block_group); | 442 | ext4_lock_group(sb, block_group); |
444 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 443 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
445 | |||
446 | err = ext4_init_block_bitmap(sb, bh, block_group, desc); | 444 | err = ext4_init_block_bitmap(sb, bh, block_group, desc); |
447 | set_bitmap_uptodate(bh); | 445 | set_bitmap_uptodate(bh); |
448 | set_buffer_uptodate(bh); | 446 | set_buffer_uptodate(bh); |
449 | ext4_unlock_group(sb, block_group); | 447 | ext4_unlock_group(sb, block_group); |
450 | unlock_buffer(bh); | 448 | unlock_buffer(bh); |
451 | if (err) | 449 | if (err) { |
450 | ext4_error(sb, "Failed to init block bitmap for group " | ||
451 | "%u: %d", block_group, err); | ||
452 | goto out; | 452 | goto out; |
453 | } | ||
453 | goto verify; | 454 | goto verify; |
454 | } | 455 | } |
455 | ext4_unlock_group(sb, block_group); | 456 | ext4_unlock_group(sb, block_group); |
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index c8021208a7eb..38f7562489bb 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c | |||
@@ -467,3 +467,59 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size) | |||
467 | return size; | 467 | return size; |
468 | return 0; | 468 | return 0; |
469 | } | 469 | } |
470 | |||
471 | /* | ||
472 | * Validate dentries for encrypted directories to make sure we aren't | ||
473 | * potentially caching stale data after a key has been added or | ||
474 | * removed. | ||
475 | */ | ||
476 | static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags) | ||
477 | { | ||
478 | struct inode *dir = d_inode(dentry->d_parent); | ||
479 | struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info; | ||
480 | int dir_has_key, cached_with_key; | ||
481 | |||
482 | if (!ext4_encrypted_inode(dir)) | ||
483 | return 0; | ||
484 | |||
485 | if (ci && ci->ci_keyring_key && | ||
486 | (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | | ||
487 | (1 << KEY_FLAG_REVOKED) | | ||
488 | (1 << KEY_FLAG_DEAD)))) | ||
489 | ci = NULL; | ||
490 | |||
491 | /* this should eventually be an flag in d_flags */ | ||
492 | cached_with_key = dentry->d_fsdata != NULL; | ||
493 | dir_has_key = (ci != NULL); | ||
494 | |||
495 | /* | ||
496 | * If the dentry was cached without the key, and it is a | ||
497 | * negative dentry, it might be a valid name. We can't check | ||
498 | * if the key has since been made available due to locking | ||
499 | * reasons, so we fail the validation so ext4_lookup() can do | ||
500 | * this check. | ||
501 | * | ||
502 | * We also fail the validation if the dentry was created with | ||
503 | * the key present, but we no longer have the key, or vice versa. | ||
504 | */ | ||
505 | if ((!cached_with_key && d_is_negative(dentry)) || | ||
506 | (!cached_with_key && dir_has_key) || | ||
507 | (cached_with_key && !dir_has_key)) { | ||
508 | #if 0 /* Revalidation debug */ | ||
509 | char buf[80]; | ||
510 | char *cp = simple_dname(dentry, buf, sizeof(buf)); | ||
511 | |||
512 | if (IS_ERR(cp)) | ||
513 | cp = (char *) "???"; | ||
514 | pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata, | ||
515 | cached_with_key, d_is_negative(dentry), | ||
516 | dir_has_key); | ||
517 | #endif | ||
518 | return 0; | ||
519 | } | ||
520 | return 1; | ||
521 | } | ||
522 | |||
523 | const struct dentry_operations ext4_encrypted_d_ops = { | ||
524 | .d_revalidate = ext4_d_revalidate, | ||
525 | }; | ||
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 1d1bca74f844..33f5e2a50cf8 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -111,6 +111,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) | |||
111 | int dir_has_error = 0; | 111 | int dir_has_error = 0; |
112 | struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; | 112 | struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; |
113 | 113 | ||
114 | if (ext4_encrypted_inode(inode)) { | ||
115 | err = ext4_get_encryption_info(inode); | ||
116 | if (err && err != -ENOKEY) | ||
117 | return err; | ||
118 | } | ||
119 | |||
114 | if (is_dx_dir(inode)) { | 120 | if (is_dx_dir(inode)) { |
115 | err = ext4_dx_readdir(file, ctx); | 121 | err = ext4_dx_readdir(file, ctx); |
116 | if (err != ERR_BAD_DX_DIR) { | 122 | if (err != ERR_BAD_DX_DIR) { |
@@ -157,8 +163,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) | |||
157 | index, 1); | 163 | index, 1); |
158 | file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; | 164 | file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; |
159 | bh = ext4_bread(NULL, inode, map.m_lblk, 0); | 165 | bh = ext4_bread(NULL, inode, map.m_lblk, 0); |
160 | if (IS_ERR(bh)) | 166 | if (IS_ERR(bh)) { |
161 | return PTR_ERR(bh); | 167 | err = PTR_ERR(bh); |
168 | bh = NULL; | ||
169 | goto errout; | ||
170 | } | ||
162 | } | 171 | } |
163 | 172 | ||
164 | if (!bh) { | 173 | if (!bh) { |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0662b285dc8a..157b458a69d4 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2302,6 +2302,7 @@ struct page *ext4_encrypt(struct inode *inode, | |||
2302 | int ext4_decrypt(struct page *page); | 2302 | int ext4_decrypt(struct page *page); |
2303 | int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk, | 2303 | int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk, |
2304 | ext4_fsblk_t pblk, ext4_lblk_t len); | 2304 | ext4_fsblk_t pblk, ext4_lblk_t len); |
2305 | extern const struct dentry_operations ext4_encrypted_d_ops; | ||
2305 | 2306 | ||
2306 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | 2307 | #ifdef CONFIG_EXT4_FS_ENCRYPTION |
2307 | int ext4_init_crypto(void); | 2308 | int ext4_init_crypto(void); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 0ffabaf90aa5..3753ceb0b0dd 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3928,7 +3928,7 @@ static int | |||
3928 | convert_initialized_extent(handle_t *handle, struct inode *inode, | 3928 | convert_initialized_extent(handle_t *handle, struct inode *inode, |
3929 | struct ext4_map_blocks *map, | 3929 | struct ext4_map_blocks *map, |
3930 | struct ext4_ext_path **ppath, int flags, | 3930 | struct ext4_ext_path **ppath, int flags, |
3931 | unsigned int allocated, ext4_fsblk_t newblock) | 3931 | unsigned int allocated) |
3932 | { | 3932 | { |
3933 | struct ext4_ext_path *path = *ppath; | 3933 | struct ext4_ext_path *path = *ppath; |
3934 | struct ext4_extent *ex; | 3934 | struct ext4_extent *ex; |
@@ -4347,7 +4347,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
4347 | (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) { | 4347 | (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) { |
4348 | allocated = convert_initialized_extent( | 4348 | allocated = convert_initialized_extent( |
4349 | handle, inode, map, &path, | 4349 | handle, inode, map, &path, |
4350 | flags, allocated, newblock); | 4350 | flags, allocated); |
4351 | goto out2; | 4351 | goto out2; |
4352 | } else if (!ext4_ext_is_unwritten(ex)) | 4352 | } else if (!ext4_ext_is_unwritten(ex)) |
4353 | goto out; | 4353 | goto out; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 1126436dada1..474f1a4d2ca8 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -350,6 +350,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
350 | struct super_block *sb = inode->i_sb; | 350 | struct super_block *sb = inode->i_sb; |
351 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 351 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
352 | struct vfsmount *mnt = filp->f_path.mnt; | 352 | struct vfsmount *mnt = filp->f_path.mnt; |
353 | struct inode *dir = filp->f_path.dentry->d_parent->d_inode; | ||
353 | struct path path; | 354 | struct path path; |
354 | char buf[64], *cp; | 355 | char buf[64], *cp; |
355 | int ret; | 356 | int ret; |
@@ -393,6 +394,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
393 | if (ext4_encryption_info(inode) == NULL) | 394 | if (ext4_encryption_info(inode) == NULL) |
394 | return -ENOKEY; | 395 | return -ENOKEY; |
395 | } | 396 | } |
397 | if (ext4_encrypted_inode(dir) && | ||
398 | !ext4_is_child_context_consistent_with_parent(dir, inode)) { | ||
399 | ext4_warning(inode->i_sb, | ||
400 | "Inconsistent encryption contexts: %lu/%lu\n", | ||
401 | (unsigned long) dir->i_ino, | ||
402 | (unsigned long) inode->i_ino); | ||
403 | return -EPERM; | ||
404 | } | ||
396 | /* | 405 | /* |
397 | * Set up the jbd2_inode if we are opening the inode for | 406 | * Set up the jbd2_inode if we are opening the inode for |
398 | * writing and the journal is present | 407 | * writing and the journal is present |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 3fcfd50a2e8a..acc0ad56bf2f 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -76,7 +76,6 @@ static int ext4_init_inode_bitmap(struct super_block *sb, | |||
76 | /* If checksum is bad mark all blocks and inodes use to prevent | 76 | /* If checksum is bad mark all blocks and inodes use to prevent |
77 | * allocation, essentially implementing a per-group read-only flag. */ | 77 | * allocation, essentially implementing a per-group read-only flag. */ |
78 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { | 78 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { |
79 | ext4_error(sb, "Checksum bad for group %u", block_group); | ||
80 | grp = ext4_get_group_info(sb, block_group); | 79 | grp = ext4_get_group_info(sb, block_group); |
81 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | 80 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) |
82 | percpu_counter_sub(&sbi->s_freeclusters_counter, | 81 | percpu_counter_sub(&sbi->s_freeclusters_counter, |
@@ -191,8 +190,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
191 | set_buffer_verified(bh); | 190 | set_buffer_verified(bh); |
192 | ext4_unlock_group(sb, block_group); | 191 | ext4_unlock_group(sb, block_group); |
193 | unlock_buffer(bh); | 192 | unlock_buffer(bh); |
194 | if (err) | 193 | if (err) { |
194 | ext4_error(sb, "Failed to init inode bitmap for group " | ||
195 | "%u: %d", block_group, err); | ||
195 | goto out; | 196 | goto out; |
197 | } | ||
196 | return bh; | 198 | return bh; |
197 | } | 199 | } |
198 | ext4_unlock_group(sb, block_group); | 200 | ext4_unlock_group(sb, block_group); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 83bc8bfb3bea..9cc57c3b4661 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -686,6 +686,34 @@ out_sem: | |||
686 | return retval; | 686 | return retval; |
687 | } | 687 | } |
688 | 688 | ||
689 | /* | ||
690 | * Update EXT4_MAP_FLAGS in bh->b_state. For buffer heads attached to pages | ||
691 | * we have to be careful as someone else may be manipulating b_state as well. | ||
692 | */ | ||
693 | static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags) | ||
694 | { | ||
695 | unsigned long old_state; | ||
696 | unsigned long new_state; | ||
697 | |||
698 | flags &= EXT4_MAP_FLAGS; | ||
699 | |||
700 | /* Dummy buffer_head? Set non-atomically. */ | ||
701 | if (!bh->b_page) { | ||
702 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | flags; | ||
703 | return; | ||
704 | } | ||
705 | /* | ||
706 | * Someone else may be modifying b_state. Be careful! This is ugly but | ||
707 | * once we get rid of using bh as a container for mapping information | ||
708 | * to pass to / from get_block functions, this can go away. | ||
709 | */ | ||
710 | do { | ||
711 | old_state = READ_ONCE(bh->b_state); | ||
712 | new_state = (old_state & ~EXT4_MAP_FLAGS) | flags; | ||
713 | } while (unlikely( | ||
714 | cmpxchg(&bh->b_state, old_state, new_state) != old_state)); | ||
715 | } | ||
716 | |||
689 | /* Maximum number of blocks we map for direct IO at once. */ | 717 | /* Maximum number of blocks we map for direct IO at once. */ |
690 | #define DIO_MAX_BLOCKS 4096 | 718 | #define DIO_MAX_BLOCKS 4096 |
691 | 719 | ||
@@ -722,7 +750,7 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock, | |||
722 | ext4_io_end_t *io_end = ext4_inode_aio(inode); | 750 | ext4_io_end_t *io_end = ext4_inode_aio(inode); |
723 | 751 | ||
724 | map_bh(bh, inode->i_sb, map.m_pblk); | 752 | map_bh(bh, inode->i_sb, map.m_pblk); |
725 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; | 753 | ext4_update_bh_state(bh, map.m_flags); |
726 | if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN) | 754 | if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN) |
727 | set_buffer_defer_completion(bh); | 755 | set_buffer_defer_completion(bh); |
728 | bh->b_size = inode->i_sb->s_blocksize * map.m_len; | 756 | bh->b_size = inode->i_sb->s_blocksize * map.m_len; |
@@ -1685,7 +1713,7 @@ int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
1685 | return ret; | 1713 | return ret; |
1686 | 1714 | ||
1687 | map_bh(bh, inode->i_sb, map.m_pblk); | 1715 | map_bh(bh, inode->i_sb, map.m_pblk); |
1688 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; | 1716 | ext4_update_bh_state(bh, map.m_flags); |
1689 | 1717 | ||
1690 | if (buffer_unwritten(bh)) { | 1718 | if (buffer_unwritten(bh)) { |
1691 | /* A delayed write to unwritten bh should be marked | 1719 | /* A delayed write to unwritten bh should be marked |
@@ -3253,29 +3281,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter, | |||
3253 | * case, we allocate an io_end structure to hook to the iocb. | 3281 | * case, we allocate an io_end structure to hook to the iocb. |
3254 | */ | 3282 | */ |
3255 | iocb->private = NULL; | 3283 | iocb->private = NULL; |
3256 | ext4_inode_aio_set(inode, NULL); | ||
3257 | if (!is_sync_kiocb(iocb)) { | ||
3258 | io_end = ext4_init_io_end(inode, GFP_NOFS); | ||
3259 | if (!io_end) { | ||
3260 | ret = -ENOMEM; | ||
3261 | goto retake_lock; | ||
3262 | } | ||
3263 | /* | ||
3264 | * Grab reference for DIO. Will be dropped in ext4_end_io_dio() | ||
3265 | */ | ||
3266 | iocb->private = ext4_get_io_end(io_end); | ||
3267 | /* | ||
3268 | * we save the io structure for current async direct | ||
3269 | * IO, so that later ext4_map_blocks() could flag the | ||
3270 | * io structure whether there is a unwritten extents | ||
3271 | * needs to be converted when IO is completed. | ||
3272 | */ | ||
3273 | ext4_inode_aio_set(inode, io_end); | ||
3274 | } | ||
3275 | |||
3276 | if (overwrite) { | 3284 | if (overwrite) { |
3277 | get_block_func = ext4_get_block_overwrite; | 3285 | get_block_func = ext4_get_block_overwrite; |
3278 | } else { | 3286 | } else { |
3287 | ext4_inode_aio_set(inode, NULL); | ||
3288 | if (!is_sync_kiocb(iocb)) { | ||
3289 | io_end = ext4_init_io_end(inode, GFP_NOFS); | ||
3290 | if (!io_end) { | ||
3291 | ret = -ENOMEM; | ||
3292 | goto retake_lock; | ||
3293 | } | ||
3294 | /* | ||
3295 | * Grab reference for DIO. Will be dropped in | ||
3296 | * ext4_end_io_dio() | ||
3297 | */ | ||
3298 | iocb->private = ext4_get_io_end(io_end); | ||
3299 | /* | ||
3300 | * we save the io structure for current async direct | ||
3301 | * IO, so that later ext4_map_blocks() could flag the | ||
3302 | * io structure whether there is a unwritten extents | ||
3303 | * needs to be converted when IO is completed. | ||
3304 | */ | ||
3305 | ext4_inode_aio_set(inode, io_end); | ||
3306 | } | ||
3279 | get_block_func = ext4_get_block_write; | 3307 | get_block_func = ext4_get_block_write; |
3280 | dio_flags = DIO_LOCKING; | 3308 | dio_flags = DIO_LOCKING; |
3281 | } | 3309 | } |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 0f6c36922c24..a99b010e2194 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -208,7 +208,7 @@ static int ext4_ioctl_setflags(struct inode *inode, | |||
208 | { | 208 | { |
209 | struct ext4_inode_info *ei = EXT4_I(inode); | 209 | struct ext4_inode_info *ei = EXT4_I(inode); |
210 | handle_t *handle = NULL; | 210 | handle_t *handle = NULL; |
211 | int err = EPERM, migrate = 0; | 211 | int err = -EPERM, migrate = 0; |
212 | struct ext4_iloc iloc; | 212 | struct ext4_iloc iloc; |
213 | unsigned int oldflags, mask, i; | 213 | unsigned int oldflags, mask, i; |
214 | unsigned int jflag; | 214 | unsigned int jflag; |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 61eaf74dca37..4424b7bf8ac6 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2285,7 +2285,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) | |||
2285 | if (group == 0) | 2285 | if (group == 0) |
2286 | seq_puts(seq, "#group: free frags first [" | 2286 | seq_puts(seq, "#group: free frags first [" |
2287 | " 2^0 2^1 2^2 2^3 2^4 2^5 2^6 " | 2287 | " 2^0 2^1 2^2 2^3 2^4 2^5 2^6 " |
2288 | " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]"); | 2288 | " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]\n"); |
2289 | 2289 | ||
2290 | i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) + | 2290 | i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) + |
2291 | sizeof(struct ext4_group_info); | 2291 | sizeof(struct ext4_group_info); |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index fb6f11709ae6..e032a0423e35 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -265,11 +265,12 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, | |||
265 | ext4_lblk_t orig_blk_offset, donor_blk_offset; | 265 | ext4_lblk_t orig_blk_offset, donor_blk_offset; |
266 | unsigned long blocksize = orig_inode->i_sb->s_blocksize; | 266 | unsigned long blocksize = orig_inode->i_sb->s_blocksize; |
267 | unsigned int tmp_data_size, data_size, replaced_size; | 267 | unsigned int tmp_data_size, data_size, replaced_size; |
268 | int err2, jblocks, retries = 0; | 268 | int i, err2, jblocks, retries = 0; |
269 | int replaced_count = 0; | 269 | int replaced_count = 0; |
270 | int from = data_offset_in_page << orig_inode->i_blkbits; | 270 | int from = data_offset_in_page << orig_inode->i_blkbits; |
271 | int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; | 271 | int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; |
272 | struct super_block *sb = orig_inode->i_sb; | 272 | struct super_block *sb = orig_inode->i_sb; |
273 | struct buffer_head *bh = NULL; | ||
273 | 274 | ||
274 | /* | 275 | /* |
275 | * It needs twice the amount of ordinary journal buffers because | 276 | * It needs twice the amount of ordinary journal buffers because |
@@ -380,8 +381,16 @@ data_copy: | |||
380 | } | 381 | } |
381 | /* Perform all necessary steps similar write_begin()/write_end() | 382 | /* Perform all necessary steps similar write_begin()/write_end() |
382 | * but keeping in mind that i_size will not change */ | 383 | * but keeping in mind that i_size will not change */ |
383 | *err = __block_write_begin(pagep[0], from, replaced_size, | 384 | if (!page_has_buffers(pagep[0])) |
384 | ext4_get_block); | 385 | create_empty_buffers(pagep[0], 1 << orig_inode->i_blkbits, 0); |
386 | bh = page_buffers(pagep[0]); | ||
387 | for (i = 0; i < data_offset_in_page; i++) | ||
388 | bh = bh->b_this_page; | ||
389 | for (i = 0; i < block_len_in_page; i++) { | ||
390 | *err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0); | ||
391 | if (*err < 0) | ||
392 | break; | ||
393 | } | ||
385 | if (!*err) | 394 | if (!*err) |
386 | *err = block_commit_write(pagep[0], from, from + replaced_size); | 395 | *err = block_commit_write(pagep[0], from, from + replaced_size); |
387 | 396 | ||
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 06574dd77614..48e4b8907826 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1558,6 +1558,24 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi | |||
1558 | struct ext4_dir_entry_2 *de; | 1558 | struct ext4_dir_entry_2 *de; |
1559 | struct buffer_head *bh; | 1559 | struct buffer_head *bh; |
1560 | 1560 | ||
1561 | if (ext4_encrypted_inode(dir)) { | ||
1562 | int res = ext4_get_encryption_info(dir); | ||
1563 | |||
1564 | /* | ||
1565 | * This should be a properly defined flag for | ||
1566 | * dentry->d_flags when we uplift this to the VFS. | ||
1567 | * d_fsdata is set to (void *) 1 if if the dentry is | ||
1568 | * created while the directory was encrypted and we | ||
1569 | * don't have access to the key. | ||
1570 | */ | ||
1571 | dentry->d_fsdata = NULL; | ||
1572 | if (ext4_encryption_info(dir)) | ||
1573 | dentry->d_fsdata = (void *) 1; | ||
1574 | d_set_d_op(dentry, &ext4_encrypted_d_ops); | ||
1575 | if (res && res != -ENOKEY) | ||
1576 | return ERR_PTR(res); | ||
1577 | } | ||
1578 | |||
1561 | if (dentry->d_name.len > EXT4_NAME_LEN) | 1579 | if (dentry->d_name.len > EXT4_NAME_LEN) |
1562 | return ERR_PTR(-ENAMETOOLONG); | 1580 | return ERR_PTR(-ENAMETOOLONG); |
1563 | 1581 | ||
@@ -1585,11 +1603,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi | |||
1585 | return ERR_PTR(-EFSCORRUPTED); | 1603 | return ERR_PTR(-EFSCORRUPTED); |
1586 | } | 1604 | } |
1587 | if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && | 1605 | if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && |
1588 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 1606 | (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && |
1589 | S_ISLNK(inode->i_mode)) && | ||
1590 | !ext4_is_child_context_consistent_with_parent(dir, | 1607 | !ext4_is_child_context_consistent_with_parent(dir, |
1591 | inode)) { | 1608 | inode)) { |
1609 | int nokey = ext4_encrypted_inode(inode) && | ||
1610 | !ext4_encryption_info(inode); | ||
1611 | |||
1592 | iput(inode); | 1612 | iput(inode); |
1613 | if (nokey) | ||
1614 | return ERR_PTR(-ENOKEY); | ||
1593 | ext4_warning(inode->i_sb, | 1615 | ext4_warning(inode->i_sb, |
1594 | "Inconsistent encryption contexts: %lu/%lu\n", | 1616 | "Inconsistent encryption contexts: %lu/%lu\n", |
1595 | (unsigned long) dir->i_ino, | 1617 | (unsigned long) dir->i_ino, |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index ad62d7acc315..34038e3598d5 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -198,7 +198,7 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size) | |||
198 | if (flex_gd == NULL) | 198 | if (flex_gd == NULL) |
199 | goto out3; | 199 | goto out3; |
200 | 200 | ||
201 | if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data)) | 201 | if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_group_data)) |
202 | goto out2; | 202 | goto out2; |
203 | flex_gd->count = flexbg_size; | 203 | flex_gd->count = flexbg_size; |
204 | 204 | ||