diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 21:24:39 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 21:24:39 -0500 |
| commit | cab7076a185e1e27f6879325e4da762424c3f1c9 (patch) | |
| tree | eb9274ba3b306bce14c581368579677775814088 | |
| parent | 6c24337f22115d669e24ce990842dab667371b4d (diff) | |
| parent | e9be2ac7c09cabcbbbb12b0869e49b7a715d6fb5 (diff) | |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o:
"For this cycle we add support for the shutdown ioctl, which is
primarily used for testing, but which can be useful on production
systems when a scratch volume is being destroyed and the data on it
doesn't need to be saved.
This found (and we fixed) a number of bugs with ext4's recovery to
corrupted file system --- the bugs increased the amount of data that
could be potentially lost, and in the case of the inline data feature,
could cause the kernel to BUG.
Also included are a number of other bug fixes, including in ext4's
fscrypt, DAX, inline data support"
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (26 commits)
ext4: rename EXT4_IOC_GOINGDOWN to EXT4_IOC_SHUTDOWN
ext4: fix fencepost in s_first_meta_bg validation
ext4: don't BUG when truncating encrypted inodes on the orphan list
ext4: do not use stripe_width if it is not set
ext4: fix stripe-unaligned allocations
dax: assert that i_rwsem is held exclusive for writes
ext4: fix DAX write locking
ext4: add EXT4_IOC_GOINGDOWN ioctl
ext4: add shutdown bit and check for it
ext4: rename s_resize_flags to s_ext4_flags
ext4: return EROFS if device is r/o and journal replay is needed
ext4: preserve the needs_recovery flag when the journal is aborted
jbd2: don't leak modified metadata buffers on an aborted journal
ext4: fix inline data error paths
ext4: move halfmd4 into hash.c directly
ext4: fix use-after-iput when fscrypt contexts are inconsistent
jbd2: fix use after free in kjournald2()
ext4: fix data corruption in data=journal mode
ext4: trim allocation requests to group size
ext4: replace BUG_ON with WARN_ON in mb_find_extent()
...
| -rw-r--r-- | fs/dax.c | 6 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 28 | ||||
| -rw-r--r-- | fs/ext4/ext4_jbd2.c | 11 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 27 | ||||
| -rw-r--r-- | fs/ext4/file.c | 22 | ||||
| -rw-r--r-- | fs/ext4/fsync.c | 3 | ||||
| -rw-r--r-- | fs/ext4/hash.c | 71 | ||||
| -rw-r--r-- | fs/ext4/ialloc.c | 3 | ||||
| -rw-r--r-- | fs/ext4/inline.c | 123 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 79 | ||||
| -rw-r--r-- | fs/ext4/ioctl.c | 50 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 25 | ||||
| -rw-r--r-- | fs/ext4/namei.c | 18 | ||||
| -rw-r--r-- | fs/ext4/page-io.c | 2 | ||||
| -rw-r--r-- | fs/ext4/resize.c | 5 | ||||
| -rw-r--r-- | fs/ext4/super.c | 47 | ||||
| -rw-r--r-- | fs/ext4/xattr.c | 33 | ||||
| -rw-r--r-- | fs/ext4/xattr.h | 32 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 2 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 4 | ||||
| -rw-r--r-- | include/linux/cryptohash.h | 2 | ||||
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/halfmd4.c | 67 |
23 files changed, 456 insertions, 206 deletions
| @@ -1086,8 +1086,12 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 1086 | loff_t pos = iocb->ki_pos, ret = 0, done = 0; | 1086 | loff_t pos = iocb->ki_pos, ret = 0, done = 0; |
| 1087 | unsigned flags = 0; | 1087 | unsigned flags = 0; |
| 1088 | 1088 | ||
| 1089 | if (iov_iter_rw(iter) == WRITE) | 1089 | if (iov_iter_rw(iter) == WRITE) { |
| 1090 | lockdep_assert_held_exclusive(&inode->i_rwsem); | ||
| 1090 | flags |= IOMAP_WRITE; | 1091 | flags |= IOMAP_WRITE; |
| 1092 | } else { | ||
| 1093 | lockdep_assert_held(&inode->i_rwsem); | ||
| 1094 | } | ||
| 1091 | 1095 | ||
| 1092 | while (iov_iter_count(iter)) { | 1096 | while (iov_iter_count(iter)) { |
| 1093 | ret = iomap_apply(inode, pos, iov_iter_count(iter), flags, ops, | 1097 | ret = iomap_apply(inode, pos, iov_iter_count(iter), flags, ops, |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index a5c756b80b7d..01d52b98f9a7 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -683,6 +683,16 @@ struct fsxattr { | |||
| 683 | #define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR | 683 | #define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR |
| 684 | #define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR | 684 | #define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR |
| 685 | 685 | ||
| 686 | #define EXT4_IOC_SHUTDOWN _IOR ('X', 125, __u32) | ||
| 687 | |||
| 688 | /* | ||
| 689 | * Flags for going down operation | ||
| 690 | */ | ||
| 691 | #define EXT4_GOING_FLAGS_DEFAULT 0x0 /* going down */ | ||
| 692 | #define EXT4_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */ | ||
| 693 | #define EXT4_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */ | ||
| 694 | |||
| 695 | |||
| 686 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) | 696 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) |
| 687 | /* | 697 | /* |
| 688 | * ioctl commands in 32 bit emulation | 698 | * ioctl commands in 32 bit emulation |
| @@ -1403,8 +1413,7 @@ struct ext4_sb_info { | |||
| 1403 | struct journal_s *s_journal; | 1413 | struct journal_s *s_journal; |
| 1404 | struct list_head s_orphan; | 1414 | struct list_head s_orphan; |
| 1405 | struct mutex s_orphan_lock; | 1415 | struct mutex s_orphan_lock; |
| 1406 | unsigned long s_resize_flags; /* Flags indicating if there | 1416 | unsigned long s_ext4_flags; /* Ext4 superblock flags */ |
| 1407 | is a resizer */ | ||
| 1408 | unsigned long s_commit_interval; | 1417 | unsigned long s_commit_interval; |
| 1409 | u32 s_max_batch_time; | 1418 | u32 s_max_batch_time; |
| 1410 | u32 s_min_batch_time; | 1419 | u32 s_min_batch_time; |
| @@ -1838,6 +1847,18 @@ static inline bool ext4_has_incompat_features(struct super_block *sb) | |||
| 1838 | } | 1847 | } |
| 1839 | 1848 | ||
| 1840 | /* | 1849 | /* |
| 1850 | * Superblock flags | ||
| 1851 | */ | ||
| 1852 | #define EXT4_FLAGS_RESIZING 0 | ||
| 1853 | #define EXT4_FLAGS_SHUTDOWN 1 | ||
| 1854 | |||
| 1855 | static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi) | ||
| 1856 | { | ||
| 1857 | return test_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); | ||
| 1858 | } | ||
| 1859 | |||
| 1860 | |||
| 1861 | /* | ||
| 1841 | * Default values for user and/or group using reserved blocks | 1862 | * Default values for user and/or group using reserved blocks |
| 1842 | */ | 1863 | */ |
| 1843 | #define EXT4_DEF_RESUID 0 | 1864 | #define EXT4_DEF_RESUID 0 |
| @@ -3005,7 +3026,7 @@ extern int ext4_inline_data_fiemap(struct inode *inode, | |||
| 3005 | extern int ext4_try_to_evict_inline_data(handle_t *handle, | 3026 | extern int ext4_try_to_evict_inline_data(handle_t *handle, |
| 3006 | struct inode *inode, | 3027 | struct inode *inode, |
| 3007 | int needed); | 3028 | int needed); |
| 3008 | extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline); | 3029 | extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline); |
| 3009 | 3030 | ||
| 3010 | extern int ext4_convert_inline_data(struct inode *inode); | 3031 | extern int ext4_convert_inline_data(struct inode *inode); |
| 3011 | 3032 | ||
| @@ -3199,7 +3220,6 @@ static inline void ext4_inode_resume_unlocked_dio(struct inode *inode) | |||
| 3199 | EXT4_WQ_HASH_SZ]) | 3220 | EXT4_WQ_HASH_SZ]) |
| 3200 | extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; | 3221 | extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; |
| 3201 | 3222 | ||
| 3202 | #define EXT4_RESIZING 0 | ||
| 3203 | extern int ext4_resize_begin(struct super_block *sb); | 3223 | extern int ext4_resize_begin(struct super_block *sb); |
| 3204 | extern void ext4_resize_end(struct super_block *sb); | 3224 | extern void ext4_resize_end(struct super_block *sb); |
| 3205 | 3225 | ||
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index e770c1ee4613..dd106b1d5d89 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
| @@ -43,6 +43,10 @@ static int ext4_journal_check_start(struct super_block *sb) | |||
| 43 | journal_t *journal; | 43 | journal_t *journal; |
| 44 | 44 | ||
| 45 | might_sleep(); | 45 | might_sleep(); |
| 46 | |||
| 47 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) | ||
| 48 | return -EIO; | ||
| 49 | |||
| 46 | if (sb->s_flags & MS_RDONLY) | 50 | if (sb->s_flags & MS_RDONLY) |
| 47 | return -EROFS; | 51 | return -EROFS; |
| 48 | WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); | 52 | WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); |
| @@ -161,6 +165,13 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line, | |||
| 161 | might_sleep(); | 165 | might_sleep(); |
| 162 | 166 | ||
| 163 | if (ext4_handle_valid(handle)) { | 167 | if (ext4_handle_valid(handle)) { |
| 168 | struct super_block *sb; | ||
| 169 | |||
| 170 | sb = handle->h_transaction->t_journal->j_private; | ||
| 171 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) { | ||
| 172 | jbd2_journal_abort_handle(handle); | ||
| 173 | return -EIO; | ||
| 174 | } | ||
| 164 | err = jbd2_journal_get_write_access(handle, bh); | 175 | err = jbd2_journal_get_write_access(handle, bh); |
| 165 | if (err) | 176 | if (err) |
| 166 | ext4_journal_abort_handle(where, line, __func__, bh, | 177 | ext4_journal_abort_handle(where, line, __func__, bh, |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 3e295d3350a9..2a97dff87b96 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -5334,7 +5334,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, | |||
| 5334 | ext4_lblk_t stop, *iterator, ex_start, ex_end; | 5334 | ext4_lblk_t stop, *iterator, ex_start, ex_end; |
| 5335 | 5335 | ||
| 5336 | /* Let path point to the last extent */ | 5336 | /* Let path point to the last extent */ |
| 5337 | path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0); | 5337 | path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, |
| 5338 | EXT4_EX_NOCACHE); | ||
| 5338 | if (IS_ERR(path)) | 5339 | if (IS_ERR(path)) |
| 5339 | return PTR_ERR(path); | 5340 | return PTR_ERR(path); |
| 5340 | 5341 | ||
| @@ -5343,15 +5344,15 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, | |||
| 5343 | if (!extent) | 5344 | if (!extent) |
| 5344 | goto out; | 5345 | goto out; |
| 5345 | 5346 | ||
| 5346 | stop = le32_to_cpu(extent->ee_block) + | 5347 | stop = le32_to_cpu(extent->ee_block); |
| 5347 | ext4_ext_get_actual_len(extent); | ||
| 5348 | 5348 | ||
| 5349 | /* | 5349 | /* |
| 5350 | * In case of left shift, Don't start shifting extents until we make | 5350 | * In case of left shift, Don't start shifting extents until we make |
| 5351 | * sure the hole is big enough to accommodate the shift. | 5351 | * sure the hole is big enough to accommodate the shift. |
| 5352 | */ | 5352 | */ |
| 5353 | if (SHIFT == SHIFT_LEFT) { | 5353 | if (SHIFT == SHIFT_LEFT) { |
| 5354 | path = ext4_find_extent(inode, start - 1, &path, 0); | 5354 | path = ext4_find_extent(inode, start - 1, &path, |
| 5355 | EXT4_EX_NOCACHE); | ||
| 5355 | if (IS_ERR(path)) | 5356 | if (IS_ERR(path)) |
| 5356 | return PTR_ERR(path); | 5357 | return PTR_ERR(path); |
| 5357 | depth = path->p_depth; | 5358 | depth = path->p_depth; |
| @@ -5383,9 +5384,14 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, | |||
| 5383 | else | 5384 | else |
| 5384 | iterator = &stop; | 5385 | iterator = &stop; |
| 5385 | 5386 | ||
| 5386 | /* Its safe to start updating extents */ | 5387 | /* |
| 5387 | while (start < stop) { | 5388 | * Its safe to start updating extents. Start and stop are unsigned, so |
| 5388 | path = ext4_find_extent(inode, *iterator, &path, 0); | 5389 | * in case of right shift if extent with 0 block is reached, iterator |
| 5390 | * becomes NULL to indicate the end of the loop. | ||
| 5391 | */ | ||
| 5392 | while (iterator && start <= stop) { | ||
| 5393 | path = ext4_find_extent(inode, *iterator, &path, | ||
| 5394 | EXT4_EX_NOCACHE); | ||
| 5389 | if (IS_ERR(path)) | 5395 | if (IS_ERR(path)) |
| 5390 | return PTR_ERR(path); | 5396 | return PTR_ERR(path); |
| 5391 | depth = path->p_depth; | 5397 | depth = path->p_depth; |
| @@ -5412,8 +5418,11 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, | |||
| 5412 | ext4_ext_get_actual_len(extent); | 5418 | ext4_ext_get_actual_len(extent); |
| 5413 | } else { | 5419 | } else { |
| 5414 | extent = EXT_FIRST_EXTENT(path[depth].p_hdr); | 5420 | extent = EXT_FIRST_EXTENT(path[depth].p_hdr); |
| 5415 | *iterator = le32_to_cpu(extent->ee_block) > 0 ? | 5421 | if (le32_to_cpu(extent->ee_block) > 0) |
| 5416 | le32_to_cpu(extent->ee_block) - 1 : 0; | 5422 | *iterator = le32_to_cpu(extent->ee_block) - 1; |
| 5423 | else | ||
| 5424 | /* Beginning is reached, end of the loop */ | ||
| 5425 | iterator = NULL; | ||
| 5417 | /* Update path extent in case we need to stop */ | 5426 | /* Update path extent in case we need to stop */ |
| 5418 | while (le32_to_cpu(extent->ee_block) < start) | 5427 | while (le32_to_cpu(extent->ee_block) < start) |
| 5419 | extent++; | 5428 | extent++; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index d663d3d7c81c..87e11dfe3cde 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
| @@ -57,6 +57,9 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to) | |||
| 57 | 57 | ||
| 58 | static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | 58 | static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to) |
| 59 | { | 59 | { |
| 60 | if (unlikely(ext4_forced_shutdown(EXT4_SB(file_inode(iocb->ki_filp)->i_sb)))) | ||
| 61 | return -EIO; | ||
| 62 | |||
| 60 | if (!iov_iter_count(to)) | 63 | if (!iov_iter_count(to)) |
| 61 | return 0; /* skip atime */ | 64 | return 0; /* skip atime */ |
| 62 | 65 | ||
| @@ -175,7 +178,6 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 175 | { | 178 | { |
| 176 | struct inode *inode = file_inode(iocb->ki_filp); | 179 | struct inode *inode = file_inode(iocb->ki_filp); |
| 177 | ssize_t ret; | 180 | ssize_t ret; |
| 178 | bool overwrite = false; | ||
| 179 | 181 | ||
| 180 | inode_lock(inode); | 182 | inode_lock(inode); |
| 181 | ret = ext4_write_checks(iocb, from); | 183 | ret = ext4_write_checks(iocb, from); |
| @@ -188,16 +190,9 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 188 | if (ret) | 190 | if (ret) |
| 189 | goto out; | 191 | goto out; |
| 190 | 192 | ||
| 191 | if (ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from))) { | ||
| 192 | overwrite = true; | ||
| 193 | downgrade_write(&inode->i_rwsem); | ||
| 194 | } | ||
| 195 | ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops); | 193 | ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops); |
| 196 | out: | 194 | out: |
| 197 | if (!overwrite) | 195 | inode_unlock(inode); |
| 198 | inode_unlock(inode); | ||
| 199 | else | ||
| 200 | inode_unlock_shared(inode); | ||
| 201 | if (ret > 0) | 196 | if (ret > 0) |
| 202 | ret = generic_write_sync(iocb, ret); | 197 | ret = generic_write_sync(iocb, ret); |
| 203 | return ret; | 198 | return ret; |
| @@ -213,6 +208,9 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 213 | int overwrite = 0; | 208 | int overwrite = 0; |
| 214 | ssize_t ret; | 209 | ssize_t ret; |
| 215 | 210 | ||
| 211 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 212 | return -EIO; | ||
| 213 | |||
| 216 | #ifdef CONFIG_FS_DAX | 214 | #ifdef CONFIG_FS_DAX |
| 217 | if (IS_DAX(inode)) | 215 | if (IS_DAX(inode)) |
| 218 | return ext4_dax_write_iter(iocb, from); | 216 | return ext4_dax_write_iter(iocb, from); |
| @@ -348,6 +346,9 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 348 | { | 346 | { |
| 349 | struct inode *inode = file->f_mapping->host; | 347 | struct inode *inode = file->f_mapping->host; |
| 350 | 348 | ||
| 349 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 350 | return -EIO; | ||
| 351 | |||
| 351 | if (ext4_encrypted_inode(inode)) { | 352 | if (ext4_encrypted_inode(inode)) { |
| 352 | int err = fscrypt_get_encryption_info(inode); | 353 | int err = fscrypt_get_encryption_info(inode); |
| 353 | if (err) | 354 | if (err) |
| @@ -375,6 +376,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
| 375 | char buf[64], *cp; | 376 | char buf[64], *cp; |
| 376 | int ret; | 377 | int ret; |
| 377 | 378 | ||
| 379 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 380 | return -EIO; | ||
| 381 | |||
| 378 | if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) && | 382 | if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) && |
| 379 | !(sb->s_flags & MS_RDONLY))) { | 383 | !(sb->s_flags & MS_RDONLY))) { |
| 380 | sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED; | 384 | sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED; |
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 88effb1053c7..9d549608fd30 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c | |||
| @@ -100,6 +100,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 100 | tid_t commit_tid; | 100 | tid_t commit_tid; |
| 101 | bool needs_barrier = false; | 101 | bool needs_barrier = false; |
| 102 | 102 | ||
| 103 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 104 | return -EIO; | ||
| 105 | |||
| 103 | J_ASSERT(ext4_journal_current_handle() == NULL); | 106 | J_ASSERT(ext4_journal_current_handle() == NULL); |
| 104 | 107 | ||
| 105 | trace_ext4_sync_file_enter(file, datasync); | 108 | trace_ext4_sync_file_enter(file, datasync); |
diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c index e026aa941fd5..38b8a96eb97c 100644 --- a/fs/ext4/hash.c +++ b/fs/ext4/hash.c | |||
| @@ -10,7 +10,8 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
| 13 | #include <linux/cryptohash.h> | 13 | #include <linux/compiler.h> |
| 14 | #include <linux/bitops.h> | ||
| 14 | #include "ext4.h" | 15 | #include "ext4.h" |
| 15 | 16 | ||
| 16 | #define DELTA 0x9E3779B9 | 17 | #define DELTA 0x9E3779B9 |
| @@ -32,6 +33,74 @@ static void TEA_transform(__u32 buf[4], __u32 const in[]) | |||
| 32 | buf[1] += b1; | 33 | buf[1] += b1; |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 36 | /* F, G and H are basic MD4 functions: selection, majority, parity */ | ||
| 37 | #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | ||
| 38 | #define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | ||
| 39 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||
| 40 | |||
| 41 | /* | ||
| 42 | * The generic round function. The application is so specific that | ||
| 43 | * we don't bother protecting all the arguments with parens, as is generally | ||
| 44 | * good macro practice, in favor of extra legibility. | ||
| 45 | * Rotation is separate from addition to prevent recomputation | ||
| 46 | */ | ||
| 47 | #define ROUND(f, a, b, c, d, x, s) \ | ||
| 48 | (a += f(b, c, d) + x, a = rol32(a, s)) | ||
| 49 | #define K1 0 | ||
| 50 | #define K2 013240474631UL | ||
| 51 | #define K3 015666365641UL | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Basic cut-down MD4 transform. Returns only 32 bits of result. | ||
| 55 | */ | ||
| 56 | static __u32 half_md4_transform(__u32 buf[4], __u32 const in[8]) | ||
| 57 | { | ||
| 58 | __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | ||
| 59 | |||
| 60 | /* Round 1 */ | ||
| 61 | ROUND(F, a, b, c, d, in[0] + K1, 3); | ||
| 62 | ROUND(F, d, a, b, c, in[1] + K1, 7); | ||
| 63 | ROUND(F, c, d, a, b, in[2] + K1, 11); | ||
| 64 | ROUND(F, b, c, d, a, in[3] + K1, 19); | ||
| 65 | ROUND(F, a, b, c, d, in[4] + K1, 3); | ||
| 66 | ROUND(F, d, a, b, c, in[5] + K1, 7); | ||
| 67 | ROUND(F, c, d, a, b, in[6] + K1, 11); | ||
| 68 | ROUND(F, b, c, d, a, in[7] + K1, 19); | ||
| 69 | |||
| 70 | /* Round 2 */ | ||
| 71 | ROUND(G, a, b, c, d, in[1] + K2, 3); | ||
| 72 | ROUND(G, d, a, b, c, in[3] + K2, 5); | ||
| 73 | ROUND(G, c, d, a, b, in[5] + K2, 9); | ||
| 74 | ROUND(G, b, c, d, a, in[7] + K2, 13); | ||
| 75 | ROUND(G, a, b, c, d, in[0] + K2, 3); | ||
| 76 | ROUND(G, d, a, b, c, in[2] + K2, 5); | ||
| 77 | ROUND(G, c, d, a, b, in[4] + K2, 9); | ||
| 78 | ROUND(G, b, c, d, a, in[6] + K2, 13); | ||
| 79 | |||
| 80 | /* Round 3 */ | ||
| 81 | ROUND(H, a, b, c, d, in[3] + K3, 3); | ||
| 82 | ROUND(H, d, a, b, c, in[7] + K3, 9); | ||
| 83 | ROUND(H, c, d, a, b, in[2] + K3, 11); | ||
| 84 | ROUND(H, b, c, d, a, in[6] + K3, 15); | ||
| 85 | ROUND(H, a, b, c, d, in[1] + K3, 3); | ||
| 86 | ROUND(H, d, a, b, c, in[5] + K3, 9); | ||
| 87 | ROUND(H, c, d, a, b, in[0] + K3, 11); | ||
| 88 | ROUND(H, b, c, d, a, in[4] + K3, 15); | ||
| 89 | |||
| 90 | buf[0] += a; | ||
| 91 | buf[1] += b; | ||
| 92 | buf[2] += c; | ||
| 93 | buf[3] += d; | ||
| 94 | |||
| 95 | return buf[1]; /* "most hashed" word */ | ||
| 96 | } | ||
| 97 | #undef ROUND | ||
| 98 | #undef K1 | ||
| 99 | #undef K2 | ||
| 100 | #undef K3 | ||
| 101 | #undef F | ||
| 102 | #undef G | ||
| 103 | #undef H | ||
| 35 | 104 | ||
| 36 | /* The old legacy hash */ | 105 | /* The old legacy hash */ |
| 37 | static __u32 dx_hack_hash_unsigned(const char *name, int len) | 106 | static __u32 dx_hack_hash_unsigned(const char *name, int len) |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index f372fc431b8e..b14bae2598bc 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -764,6 +764,9 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, | |||
| 764 | if (!dir || !dir->i_nlink) | 764 | if (!dir || !dir->i_nlink) |
| 765 | return ERR_PTR(-EPERM); | 765 | return ERR_PTR(-EPERM); |
| 766 | 766 | ||
| 767 | if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) | ||
| 768 | return ERR_PTR(-EIO); | ||
| 769 | |||
| 767 | if ((ext4_encrypted_inode(dir) || | 770 | if ((ext4_encrypted_inode(dir) || |
| 768 | DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) && | 771 | DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) && |
| 769 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) { | 772 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) { |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 437df6a1a841..30a9f210d1e3 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
| @@ -215,6 +215,9 @@ static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, | |||
| 215 | struct ext4_inode *raw_inode; | 215 | struct ext4_inode *raw_inode; |
| 216 | int cp_len = 0; | 216 | int cp_len = 0; |
| 217 | 217 | ||
| 218 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 219 | return; | ||
| 220 | |||
| 218 | BUG_ON(!EXT4_I(inode)->i_inline_off); | 221 | BUG_ON(!EXT4_I(inode)->i_inline_off); |
| 219 | BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); | 222 | BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); |
| 220 | 223 | ||
| @@ -381,7 +384,7 @@ out: | |||
| 381 | static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, | 384 | static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, |
| 382 | unsigned int len) | 385 | unsigned int len) |
| 383 | { | 386 | { |
| 384 | int ret, size; | 387 | int ret, size, no_expand; |
| 385 | struct ext4_inode_info *ei = EXT4_I(inode); | 388 | struct ext4_inode_info *ei = EXT4_I(inode); |
| 386 | 389 | ||
| 387 | if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) | 390 | if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) |
| @@ -391,15 +394,14 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, | |||
| 391 | if (size < len) | 394 | if (size < len) |
| 392 | return -ENOSPC; | 395 | return -ENOSPC; |
| 393 | 396 | ||
| 394 | down_write(&EXT4_I(inode)->xattr_sem); | 397 | ext4_write_lock_xattr(inode, &no_expand); |
| 395 | 398 | ||
| 396 | if (ei->i_inline_off) | 399 | if (ei->i_inline_off) |
| 397 | ret = ext4_update_inline_data(handle, inode, len); | 400 | ret = ext4_update_inline_data(handle, inode, len); |
| 398 | else | 401 | else |
| 399 | ret = ext4_create_inline_data(handle, inode, len); | 402 | ret = ext4_create_inline_data(handle, inode, len); |
| 400 | 403 | ||
| 401 | up_write(&EXT4_I(inode)->xattr_sem); | 404 | ext4_write_unlock_xattr(inode, &no_expand); |
| 402 | |||
| 403 | return ret; | 405 | return ret; |
| 404 | } | 406 | } |
| 405 | 407 | ||
| @@ -533,7 +535,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping, | |||
| 533 | struct inode *inode, | 535 | struct inode *inode, |
| 534 | unsigned flags) | 536 | unsigned flags) |
| 535 | { | 537 | { |
| 536 | int ret, needed_blocks; | 538 | int ret, needed_blocks, no_expand; |
| 537 | handle_t *handle = NULL; | 539 | handle_t *handle = NULL; |
| 538 | int retries = 0, sem_held = 0; | 540 | int retries = 0, sem_held = 0; |
| 539 | struct page *page = NULL; | 541 | struct page *page = NULL; |
| @@ -573,7 +575,7 @@ retry: | |||
| 573 | goto out; | 575 | goto out; |
| 574 | } | 576 | } |
| 575 | 577 | ||
| 576 | down_write(&EXT4_I(inode)->xattr_sem); | 578 | ext4_write_lock_xattr(inode, &no_expand); |
| 577 | sem_held = 1; | 579 | sem_held = 1; |
| 578 | /* If some one has already done this for us, just exit. */ | 580 | /* If some one has already done this for us, just exit. */ |
| 579 | if (!ext4_has_inline_data(inode)) { | 581 | if (!ext4_has_inline_data(inode)) { |
| @@ -610,7 +612,7 @@ retry: | |||
| 610 | put_page(page); | 612 | put_page(page); |
| 611 | page = NULL; | 613 | page = NULL; |
| 612 | ext4_orphan_add(handle, inode); | 614 | ext4_orphan_add(handle, inode); |
| 613 | up_write(&EXT4_I(inode)->xattr_sem); | 615 | ext4_write_unlock_xattr(inode, &no_expand); |
| 614 | sem_held = 0; | 616 | sem_held = 0; |
| 615 | ext4_journal_stop(handle); | 617 | ext4_journal_stop(handle); |
| 616 | handle = NULL; | 618 | handle = NULL; |
| @@ -636,7 +638,7 @@ out: | |||
| 636 | put_page(page); | 638 | put_page(page); |
| 637 | } | 639 | } |
| 638 | if (sem_held) | 640 | if (sem_held) |
| 639 | up_write(&EXT4_I(inode)->xattr_sem); | 641 | ext4_write_unlock_xattr(inode, &no_expand); |
| 640 | if (handle) | 642 | if (handle) |
| 641 | ext4_journal_stop(handle); | 643 | ext4_journal_stop(handle); |
| 642 | brelse(iloc.bh); | 644 | brelse(iloc.bh); |
| @@ -729,7 +731,7 @@ convert: | |||
| 729 | int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, | 731 | int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, |
| 730 | unsigned copied, struct page *page) | 732 | unsigned copied, struct page *page) |
| 731 | { | 733 | { |
| 732 | int ret; | 734 | int ret, no_expand; |
| 733 | void *kaddr; | 735 | void *kaddr; |
| 734 | struct ext4_iloc iloc; | 736 | struct ext4_iloc iloc; |
| 735 | 737 | ||
| @@ -747,7 +749,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, | |||
| 747 | goto out; | 749 | goto out; |
| 748 | } | 750 | } |
| 749 | 751 | ||
| 750 | down_write(&EXT4_I(inode)->xattr_sem); | 752 | ext4_write_lock_xattr(inode, &no_expand); |
| 751 | BUG_ON(!ext4_has_inline_data(inode)); | 753 | BUG_ON(!ext4_has_inline_data(inode)); |
| 752 | 754 | ||
| 753 | kaddr = kmap_atomic(page); | 755 | kaddr = kmap_atomic(page); |
| @@ -757,7 +759,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, | |||
| 757 | /* clear page dirty so that writepages wouldn't work for us. */ | 759 | /* clear page dirty so that writepages wouldn't work for us. */ |
| 758 | ClearPageDirty(page); | 760 | ClearPageDirty(page); |
| 759 | 761 | ||
| 760 | up_write(&EXT4_I(inode)->xattr_sem); | 762 | ext4_write_unlock_xattr(inode, &no_expand); |
| 761 | brelse(iloc.bh); | 763 | brelse(iloc.bh); |
| 762 | out: | 764 | out: |
| 763 | return copied; | 765 | return copied; |
| @@ -768,7 +770,7 @@ ext4_journalled_write_inline_data(struct inode *inode, | |||
| 768 | unsigned len, | 770 | unsigned len, |
| 769 | struct page *page) | 771 | struct page *page) |
| 770 | { | 772 | { |
| 771 | int ret; | 773 | int ret, no_expand; |
| 772 | void *kaddr; | 774 | void *kaddr; |
| 773 | struct ext4_iloc iloc; | 775 | struct ext4_iloc iloc; |
| 774 | 776 | ||
| @@ -778,11 +780,11 @@ ext4_journalled_write_inline_data(struct inode *inode, | |||
| 778 | return NULL; | 780 | return NULL; |
| 779 | } | 781 | } |
| 780 | 782 | ||
| 781 | down_write(&EXT4_I(inode)->xattr_sem); | 783 | ext4_write_lock_xattr(inode, &no_expand); |
| 782 | kaddr = kmap_atomic(page); | 784 | kaddr = kmap_atomic(page); |
| 783 | ext4_write_inline_data(inode, &iloc, kaddr, 0, len); | 785 | ext4_write_inline_data(inode, &iloc, kaddr, 0, len); |
| 784 | kunmap_atomic(kaddr); | 786 | kunmap_atomic(kaddr); |
| 785 | up_write(&EXT4_I(inode)->xattr_sem); | 787 | ext4_write_unlock_xattr(inode, &no_expand); |
| 786 | 788 | ||
| 787 | return iloc.bh; | 789 | return iloc.bh; |
| 788 | } | 790 | } |
| @@ -944,8 +946,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, | |||
| 944 | struct page *page) | 946 | struct page *page) |
| 945 | { | 947 | { |
| 946 | int i_size_changed = 0; | 948 | int i_size_changed = 0; |
| 949 | int ret; | ||
| 947 | 950 | ||
| 948 | copied = ext4_write_inline_data_end(inode, pos, len, copied, page); | 951 | ret = ext4_write_inline_data_end(inode, pos, len, copied, page); |
| 952 | if (ret < 0) { | ||
| 953 | unlock_page(page); | ||
| 954 | put_page(page); | ||
| 955 | return ret; | ||
| 956 | } | ||
| 957 | copied = ret; | ||
| 949 | 958 | ||
| 950 | /* | 959 | /* |
| 951 | * No need to use i_size_read() here, the i_size | 960 | * No need to use i_size_read() here, the i_size |
| @@ -1043,7 +1052,6 @@ static int ext4_add_dirent_to_inline(handle_t *handle, | |||
| 1043 | dir->i_mtime = dir->i_ctime = current_time(dir); | 1052 | dir->i_mtime = dir->i_ctime = current_time(dir); |
| 1044 | ext4_update_dx_flag(dir); | 1053 | ext4_update_dx_flag(dir); |
| 1045 | dir->i_version++; | 1054 | dir->i_version++; |
| 1046 | ext4_mark_inode_dirty(handle, dir); | ||
| 1047 | return 1; | 1055 | return 1; |
| 1048 | } | 1056 | } |
| 1049 | 1057 | ||
| @@ -1259,7 +1267,7 @@ out: | |||
| 1259 | int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, | 1267 | int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, |
| 1260 | struct inode *dir, struct inode *inode) | 1268 | struct inode *dir, struct inode *inode) |
| 1261 | { | 1269 | { |
| 1262 | int ret, inline_size; | 1270 | int ret, inline_size, no_expand; |
| 1263 | void *inline_start; | 1271 | void *inline_start; |
| 1264 | struct ext4_iloc iloc; | 1272 | struct ext4_iloc iloc; |
| 1265 | 1273 | ||
| @@ -1267,7 +1275,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, | |||
| 1267 | if (ret) | 1275 | if (ret) |
| 1268 | return ret; | 1276 | return ret; |
| 1269 | 1277 | ||
| 1270 | down_write(&EXT4_I(dir)->xattr_sem); | 1278 | ext4_write_lock_xattr(dir, &no_expand); |
| 1271 | if (!ext4_has_inline_data(dir)) | 1279 | if (!ext4_has_inline_data(dir)) |
| 1272 | goto out; | 1280 | goto out; |
| 1273 | 1281 | ||
| @@ -1312,8 +1320,8 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, | |||
| 1312 | ret = ext4_convert_inline_data_nolock(handle, dir, &iloc); | 1320 | ret = ext4_convert_inline_data_nolock(handle, dir, &iloc); |
| 1313 | 1321 | ||
| 1314 | out: | 1322 | out: |
| 1323 | ext4_write_unlock_xattr(dir, &no_expand); | ||
| 1315 | ext4_mark_inode_dirty(handle, dir); | 1324 | ext4_mark_inode_dirty(handle, dir); |
| 1316 | up_write(&EXT4_I(dir)->xattr_sem); | ||
| 1317 | brelse(iloc.bh); | 1325 | brelse(iloc.bh); |
| 1318 | return ret; | 1326 | return ret; |
| 1319 | } | 1327 | } |
| @@ -1673,7 +1681,7 @@ int ext4_delete_inline_entry(handle_t *handle, | |||
| 1673 | struct buffer_head *bh, | 1681 | struct buffer_head *bh, |
| 1674 | int *has_inline_data) | 1682 | int *has_inline_data) |
| 1675 | { | 1683 | { |
| 1676 | int err, inline_size; | 1684 | int err, inline_size, no_expand; |
| 1677 | struct ext4_iloc iloc; | 1685 | struct ext4_iloc iloc; |
| 1678 | void *inline_start; | 1686 | void *inline_start; |
| 1679 | 1687 | ||
| @@ -1681,7 +1689,7 @@ int ext4_delete_inline_entry(handle_t *handle, | |||
| 1681 | if (err) | 1689 | if (err) |
| 1682 | return err; | 1690 | return err; |
| 1683 | 1691 | ||
| 1684 | down_write(&EXT4_I(dir)->xattr_sem); | 1692 | ext4_write_lock_xattr(dir, &no_expand); |
| 1685 | if (!ext4_has_inline_data(dir)) { | 1693 | if (!ext4_has_inline_data(dir)) { |
| 1686 | *has_inline_data = 0; | 1694 | *has_inline_data = 0; |
| 1687 | goto out; | 1695 | goto out; |
| @@ -1709,13 +1717,11 @@ int ext4_delete_inline_entry(handle_t *handle, | |||
| 1709 | if (err) | 1717 | if (err) |
| 1710 | goto out; | 1718 | goto out; |
| 1711 | 1719 | ||
| 1712 | err = ext4_mark_inode_dirty(handle, dir); | ||
| 1713 | if (unlikely(err)) | ||
| 1714 | goto out; | ||
| 1715 | |||
| 1716 | ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); | 1720 | ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); |
| 1717 | out: | 1721 | out: |
| 1718 | up_write(&EXT4_I(dir)->xattr_sem); | 1722 | ext4_write_unlock_xattr(dir, &no_expand); |
| 1723 | if (likely(err == 0)) | ||
| 1724 | err = ext4_mark_inode_dirty(handle, dir); | ||
| 1719 | brelse(iloc.bh); | 1725 | brelse(iloc.bh); |
| 1720 | if (err != -ENOENT) | 1726 | if (err != -ENOENT) |
| 1721 | ext4_std_error(dir->i_sb, err); | 1727 | ext4_std_error(dir->i_sb, err); |
| @@ -1814,11 +1820,11 @@ out: | |||
| 1814 | 1820 | ||
| 1815 | int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) | 1821 | int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) |
| 1816 | { | 1822 | { |
| 1817 | int ret; | 1823 | int ret, no_expand; |
| 1818 | 1824 | ||
| 1819 | down_write(&EXT4_I(inode)->xattr_sem); | 1825 | ext4_write_lock_xattr(inode, &no_expand); |
| 1820 | ret = ext4_destroy_inline_data_nolock(handle, inode); | 1826 | ret = ext4_destroy_inline_data_nolock(handle, inode); |
| 1821 | up_write(&EXT4_I(inode)->xattr_sem); | 1827 | ext4_write_unlock_xattr(inode, &no_expand); |
| 1822 | 1828 | ||
| 1823 | return ret; | 1829 | return ret; |
| 1824 | } | 1830 | } |
| @@ -1900,10 +1906,10 @@ out: | |||
| 1900 | return error; | 1906 | return error; |
| 1901 | } | 1907 | } |
| 1902 | 1908 | ||
| 1903 | void ext4_inline_data_truncate(struct inode *inode, int *has_inline) | 1909 | int ext4_inline_data_truncate(struct inode *inode, int *has_inline) |
| 1904 | { | 1910 | { |
| 1905 | handle_t *handle; | 1911 | handle_t *handle; |
| 1906 | int inline_size, value_len, needed_blocks; | 1912 | int inline_size, value_len, needed_blocks, no_expand, err = 0; |
| 1907 | size_t i_size; | 1913 | size_t i_size; |
| 1908 | void *value = NULL; | 1914 | void *value = NULL; |
| 1909 | struct ext4_xattr_ibody_find is = { | 1915 | struct ext4_xattr_ibody_find is = { |
| @@ -1918,19 +1924,19 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline) | |||
| 1918 | needed_blocks = ext4_writepage_trans_blocks(inode); | 1924 | needed_blocks = ext4_writepage_trans_blocks(inode); |
| 1919 | handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks); | 1925 | handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks); |
| 1920 | if (IS_ERR(handle)) | 1926 | if (IS_ERR(handle)) |
| 1921 | return; | 1927 | return PTR_ERR(handle); |
| 1922 | 1928 | ||
| 1923 | down_write(&EXT4_I(inode)->xattr_sem); | 1929 | ext4_write_lock_xattr(inode, &no_expand); |
| 1924 | if (!ext4_has_inline_data(inode)) { | 1930 | if (!ext4_has_inline_data(inode)) { |
| 1925 | *has_inline = 0; | 1931 | *has_inline = 0; |
| 1926 | ext4_journal_stop(handle); | 1932 | ext4_journal_stop(handle); |
| 1927 | return; | 1933 | return 0; |
| 1928 | } | 1934 | } |
| 1929 | 1935 | ||
| 1930 | if (ext4_orphan_add(handle, inode)) | 1936 | if ((err = ext4_orphan_add(handle, inode)) != 0) |
| 1931 | goto out; | 1937 | goto out; |
| 1932 | 1938 | ||
| 1933 | if (ext4_get_inode_loc(inode, &is.iloc)) | 1939 | if ((err = ext4_get_inode_loc(inode, &is.iloc)) != 0) |
| 1934 | goto out; | 1940 | goto out; |
| 1935 | 1941 | ||
| 1936 | down_write(&EXT4_I(inode)->i_data_sem); | 1942 | down_write(&EXT4_I(inode)->i_data_sem); |
| @@ -1941,24 +1947,29 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline) | |||
| 1941 | if (i_size < inline_size) { | 1947 | if (i_size < inline_size) { |
| 1942 | /* Clear the content in the xattr space. */ | 1948 | /* Clear the content in the xattr space. */ |
| 1943 | if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { | 1949 | if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { |
| 1944 | if (ext4_xattr_ibody_find(inode, &i, &is)) | 1950 | if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) |
| 1945 | goto out_error; | 1951 | goto out_error; |
| 1946 | 1952 | ||
| 1947 | BUG_ON(is.s.not_found); | 1953 | BUG_ON(is.s.not_found); |
| 1948 | 1954 | ||
| 1949 | value_len = le32_to_cpu(is.s.here->e_value_size); | 1955 | value_len = le32_to_cpu(is.s.here->e_value_size); |
| 1950 | value = kmalloc(value_len, GFP_NOFS); | 1956 | value = kmalloc(value_len, GFP_NOFS); |
| 1951 | if (!value) | 1957 | if (!value) { |
| 1958 | err = -ENOMEM; | ||
| 1952 | goto out_error; | 1959 | goto out_error; |
| 1960 | } | ||
| 1953 | 1961 | ||
| 1954 | if (ext4_xattr_ibody_get(inode, i.name_index, i.name, | 1962 | err = ext4_xattr_ibody_get(inode, i.name_index, |
| 1955 | value, value_len)) | 1963 | i.name, value, value_len); |
| 1964 | if (err <= 0) | ||
| 1956 | goto out_error; | 1965 | goto out_error; |
| 1957 | 1966 | ||
| 1958 | i.value = value; | 1967 | i.value = value; |
| 1959 | i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? | 1968 | i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? |
| 1960 | i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; | 1969 | i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; |
| 1961 | if (ext4_xattr_ibody_inline_set(handle, inode, &i, &is)) | 1970 | err = ext4_xattr_ibody_inline_set(handle, inode, |
| 1971 | &i, &is); | ||
| 1972 | if (err) | ||
| 1962 | goto out_error; | 1973 | goto out_error; |
| 1963 | } | 1974 | } |
| 1964 | 1975 | ||
| @@ -1978,23 +1989,24 @@ out_error: | |||
| 1978 | up_write(&EXT4_I(inode)->i_data_sem); | 1989 | up_write(&EXT4_I(inode)->i_data_sem); |
| 1979 | out: | 1990 | out: |
| 1980 | brelse(is.iloc.bh); | 1991 | brelse(is.iloc.bh); |
| 1981 | up_write(&EXT4_I(inode)->xattr_sem); | 1992 | ext4_write_unlock_xattr(inode, &no_expand); |
| 1982 | kfree(value); | 1993 | kfree(value); |
| 1983 | if (inode->i_nlink) | 1994 | if (inode->i_nlink) |
| 1984 | ext4_orphan_del(handle, inode); | 1995 | ext4_orphan_del(handle, inode); |
| 1985 | 1996 | ||
| 1986 | inode->i_mtime = inode->i_ctime = current_time(inode); | 1997 | if (err == 0) { |
| 1987 | ext4_mark_inode_dirty(handle, inode); | 1998 | inode->i_mtime = inode->i_ctime = current_time(inode); |
| 1988 | if (IS_SYNC(inode)) | 1999 | err = ext4_mark_inode_dirty(handle, inode); |
| 1989 | ext4_handle_sync(handle); | 2000 | if (IS_SYNC(inode)) |
| 1990 | 2001 | ext4_handle_sync(handle); | |
| 2002 | } | ||
| 1991 | ext4_journal_stop(handle); | 2003 | ext4_journal_stop(handle); |
| 1992 | return; | 2004 | return err; |
| 1993 | } | 2005 | } |
| 1994 | 2006 | ||
| 1995 | int ext4_convert_inline_data(struct inode *inode) | 2007 | int ext4_convert_inline_data(struct inode *inode) |
| 1996 | { | 2008 | { |
| 1997 | int error, needed_blocks; | 2009 | int error, needed_blocks, no_expand; |
| 1998 | handle_t *handle; | 2010 | handle_t *handle; |
| 1999 | struct ext4_iloc iloc; | 2011 | struct ext4_iloc iloc; |
| 2000 | 2012 | ||
| @@ -2016,15 +2028,10 @@ int ext4_convert_inline_data(struct inode *inode) | |||
| 2016 | goto out_free; | 2028 | goto out_free; |
| 2017 | } | 2029 | } |
| 2018 | 2030 | ||
| 2019 | down_write(&EXT4_I(inode)->xattr_sem); | 2031 | ext4_write_lock_xattr(inode, &no_expand); |
| 2020 | if (!ext4_has_inline_data(inode)) { | 2032 | if (ext4_has_inline_data(inode)) |
| 2021 | up_write(&EXT4_I(inode)->xattr_sem); | 2033 | error = ext4_convert_inline_data_nolock(handle, inode, &iloc); |
| 2022 | goto out; | 2034 | ext4_write_unlock_xattr(inode, &no_expand); |
| 2023 | } | ||
| 2024 | |||
| 2025 | error = ext4_convert_inline_data_nolock(handle, inode, &iloc); | ||
| 2026 | up_write(&EXT4_I(inode)->xattr_sem); | ||
| 2027 | out: | ||
| 2028 | ext4_journal_stop(handle); | 2035 | ext4_journal_stop(handle); |
| 2029 | out_free: | 2036 | out_free: |
| 2030 | brelse(iloc.bh); | 2037 | brelse(iloc.bh); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 88d57af1b516..f622d4a577e3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -1189,6 +1189,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, | |||
| 1189 | pgoff_t index; | 1189 | pgoff_t index; |
| 1190 | unsigned from, to; | 1190 | unsigned from, to; |
| 1191 | 1191 | ||
| 1192 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 1193 | return -EIO; | ||
| 1194 | |||
| 1192 | trace_ext4_write_begin(inode, pos, len, flags); | 1195 | trace_ext4_write_begin(inode, pos, len, flags); |
| 1193 | /* | 1196 | /* |
| 1194 | * Reserve one block more for addition to orphan list in case | 1197 | * Reserve one block more for addition to orphan list in case |
| @@ -1330,8 +1333,11 @@ static int ext4_write_end(struct file *file, | |||
| 1330 | if (ext4_has_inline_data(inode)) { | 1333 | if (ext4_has_inline_data(inode)) { |
| 1331 | ret = ext4_write_inline_data_end(inode, pos, len, | 1334 | ret = ext4_write_inline_data_end(inode, pos, len, |
| 1332 | copied, page); | 1335 | copied, page); |
| 1333 | if (ret < 0) | 1336 | if (ret < 0) { |
| 1337 | unlock_page(page); | ||
| 1338 | put_page(page); | ||
| 1334 | goto errout; | 1339 | goto errout; |
| 1340 | } | ||
| 1335 | copied = ret; | 1341 | copied = ret; |
| 1336 | } else | 1342 | } else |
| 1337 | copied = block_write_end(file, mapping, pos, | 1343 | copied = block_write_end(file, mapping, pos, |
| @@ -1385,7 +1391,9 @@ errout: | |||
| 1385 | * set the buffer to be dirty, since in data=journalled mode we need | 1391 | * set the buffer to be dirty, since in data=journalled mode we need |
| 1386 | * to call ext4_handle_dirty_metadata() instead. | 1392 | * to call ext4_handle_dirty_metadata() instead. |
| 1387 | */ | 1393 | */ |
| 1388 | static void zero_new_buffers(struct page *page, unsigned from, unsigned to) | 1394 | static void ext4_journalled_zero_new_buffers(handle_t *handle, |
| 1395 | struct page *page, | ||
| 1396 | unsigned from, unsigned to) | ||
| 1389 | { | 1397 | { |
| 1390 | unsigned int block_start = 0, block_end; | 1398 | unsigned int block_start = 0, block_end; |
| 1391 | struct buffer_head *head, *bh; | 1399 | struct buffer_head *head, *bh; |
| @@ -1402,7 +1410,7 @@ static void zero_new_buffers(struct page *page, unsigned from, unsigned to) | |||
| 1402 | size = min(to, block_end) - start; | 1410 | size = min(to, block_end) - start; |
| 1403 | 1411 | ||
| 1404 | zero_user(page, start, size); | 1412 | zero_user(page, start, size); |
| 1405 | set_buffer_uptodate(bh); | 1413 | write_end_fn(handle, bh); |
| 1406 | } | 1414 | } |
| 1407 | clear_buffer_new(bh); | 1415 | clear_buffer_new(bh); |
| 1408 | } | 1416 | } |
| @@ -1431,18 +1439,25 @@ static int ext4_journalled_write_end(struct file *file, | |||
| 1431 | 1439 | ||
| 1432 | BUG_ON(!ext4_handle_valid(handle)); | 1440 | BUG_ON(!ext4_handle_valid(handle)); |
| 1433 | 1441 | ||
| 1434 | if (ext4_has_inline_data(inode)) | 1442 | if (ext4_has_inline_data(inode)) { |
| 1435 | copied = ext4_write_inline_data_end(inode, pos, len, | 1443 | ret = ext4_write_inline_data_end(inode, pos, len, |
| 1436 | copied, page); | 1444 | copied, page); |
| 1437 | else { | 1445 | if (ret < 0) { |
| 1438 | if (copied < len) { | 1446 | unlock_page(page); |
| 1439 | if (!PageUptodate(page)) | 1447 | put_page(page); |
| 1440 | copied = 0; | 1448 | goto errout; |
| 1441 | zero_new_buffers(page, from+copied, to); | ||
| 1442 | } | 1449 | } |
| 1443 | 1450 | copied = ret; | |
| 1451 | } else if (unlikely(copied < len) && !PageUptodate(page)) { | ||
| 1452 | copied = 0; | ||
| 1453 | ext4_journalled_zero_new_buffers(handle, page, from, to); | ||
| 1454 | } else { | ||
| 1455 | if (unlikely(copied < len)) | ||
| 1456 | ext4_journalled_zero_new_buffers(handle, page, | ||
| 1457 | from + copied, to); | ||
| 1444 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, | 1458 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, |
| 1445 | to, &partial, write_end_fn); | 1459 | from + copied, &partial, |
| 1460 | write_end_fn); | ||
| 1446 | if (!partial) | 1461 | if (!partial) |
| 1447 | SetPageUptodate(page); | 1462 | SetPageUptodate(page); |
| 1448 | } | 1463 | } |
| @@ -1468,6 +1483,7 @@ static int ext4_journalled_write_end(struct file *file, | |||
| 1468 | */ | 1483 | */ |
| 1469 | ext4_orphan_add(handle, inode); | 1484 | ext4_orphan_add(handle, inode); |
| 1470 | 1485 | ||
| 1486 | errout: | ||
| 1471 | ret2 = ext4_journal_stop(handle); | 1487 | ret2 = ext4_journal_stop(handle); |
| 1472 | if (!ret) | 1488 | if (!ret) |
| 1473 | ret = ret2; | 1489 | ret = ret2; |
| @@ -2034,6 +2050,12 @@ static int ext4_writepage(struct page *page, | |||
| 2034 | struct ext4_io_submit io_submit; | 2050 | struct ext4_io_submit io_submit; |
| 2035 | bool keep_towrite = false; | 2051 | bool keep_towrite = false; |
| 2036 | 2052 | ||
| 2053 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) { | ||
| 2054 | ext4_invalidatepage(page, 0, PAGE_SIZE); | ||
| 2055 | unlock_page(page); | ||
| 2056 | return -EIO; | ||
| 2057 | } | ||
| 2058 | |||
| 2037 | trace_ext4_writepage(page); | 2059 | trace_ext4_writepage(page); |
| 2038 | size = i_size_read(inode); | 2060 | size = i_size_read(inode); |
| 2039 | if (page->index == size >> PAGE_SHIFT) | 2061 | if (page->index == size >> PAGE_SHIFT) |
| @@ -2409,7 +2431,8 @@ static int mpage_map_and_submit_extent(handle_t *handle, | |||
| 2409 | if (err < 0) { | 2431 | if (err < 0) { |
| 2410 | struct super_block *sb = inode->i_sb; | 2432 | struct super_block *sb = inode->i_sb; |
| 2411 | 2433 | ||
| 2412 | if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED) | 2434 | if (ext4_forced_shutdown(EXT4_SB(sb)) || |
| 2435 | EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED) | ||
| 2413 | goto invalidate_dirty_pages; | 2436 | goto invalidate_dirty_pages; |
| 2414 | /* | 2437 | /* |
| 2415 | * Let the uper layers retry transient errors. | 2438 | * Let the uper layers retry transient errors. |
| @@ -2464,8 +2487,8 @@ update_disksize: | |||
| 2464 | disksize = i_size; | 2487 | disksize = i_size; |
| 2465 | if (disksize > EXT4_I(inode)->i_disksize) | 2488 | if (disksize > EXT4_I(inode)->i_disksize) |
| 2466 | EXT4_I(inode)->i_disksize = disksize; | 2489 | EXT4_I(inode)->i_disksize = disksize; |
| 2467 | err2 = ext4_mark_inode_dirty(handle, inode); | ||
| 2468 | up_write(&EXT4_I(inode)->i_data_sem); | 2490 | up_write(&EXT4_I(inode)->i_data_sem); |
| 2491 | err2 = ext4_mark_inode_dirty(handle, inode); | ||
| 2469 | if (err2) | 2492 | if (err2) |
| 2470 | ext4_error(inode->i_sb, | 2493 | ext4_error(inode->i_sb, |
| 2471 | "Failed to mark inode %lu dirty", | 2494 | "Failed to mark inode %lu dirty", |
| @@ -2631,6 +2654,9 @@ static int ext4_writepages(struct address_space *mapping, | |||
| 2631 | struct blk_plug plug; | 2654 | struct blk_plug plug; |
| 2632 | bool give_up_on_write = false; | 2655 | bool give_up_on_write = false; |
| 2633 | 2656 | ||
| 2657 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 2658 | return -EIO; | ||
| 2659 | |||
| 2634 | percpu_down_read(&sbi->s_journal_flag_rwsem); | 2660 | percpu_down_read(&sbi->s_journal_flag_rwsem); |
| 2635 | trace_ext4_writepages(inode, wbc); | 2661 | trace_ext4_writepages(inode, wbc); |
| 2636 | 2662 | ||
| @@ -2667,7 +2693,8 @@ static int ext4_writepages(struct address_space *mapping, | |||
| 2667 | * *never* be called, so if that ever happens, we would want | 2693 | * *never* be called, so if that ever happens, we would want |
| 2668 | * the stack trace. | 2694 | * the stack trace. |
| 2669 | */ | 2695 | */ |
| 2670 | if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) { | 2696 | if (unlikely(ext4_forced_shutdown(EXT4_SB(mapping->host->i_sb)) || |
| 2697 | sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) { | ||
| 2671 | ret = -EROFS; | 2698 | ret = -EROFS; |
| 2672 | goto out_writepages; | 2699 | goto out_writepages; |
| 2673 | } | 2700 | } |
| @@ -2892,6 +2919,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | |||
| 2892 | struct inode *inode = mapping->host; | 2919 | struct inode *inode = mapping->host; |
| 2893 | handle_t *handle; | 2920 | handle_t *handle; |
| 2894 | 2921 | ||
| 2922 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 2923 | return -EIO; | ||
| 2924 | |||
| 2895 | index = pos >> PAGE_SHIFT; | 2925 | index = pos >> PAGE_SHIFT; |
| 2896 | 2926 | ||
| 2897 | if (ext4_nonda_switch(inode->i_sb) || | 2927 | if (ext4_nonda_switch(inode->i_sb) || |
| @@ -3914,6 +3944,10 @@ static int ext4_block_truncate_page(handle_t *handle, | |||
| 3914 | unsigned blocksize; | 3944 | unsigned blocksize; |
| 3915 | struct inode *inode = mapping->host; | 3945 | struct inode *inode = mapping->host; |
| 3916 | 3946 | ||
| 3947 | /* If we are processing an encrypted inode during orphan list handling */ | ||
| 3948 | if (ext4_encrypted_inode(inode) && !fscrypt_has_encryption_key(inode)) | ||
| 3949 | return 0; | ||
| 3950 | |||
| 3917 | blocksize = inode->i_sb->s_blocksize; | 3951 | blocksize = inode->i_sb->s_blocksize; |
| 3918 | length = blocksize - (offset & (blocksize - 1)); | 3952 | length = blocksize - (offset & (blocksize - 1)); |
| 3919 | 3953 | ||
| @@ -4222,7 +4256,9 @@ int ext4_truncate(struct inode *inode) | |||
| 4222 | if (ext4_has_inline_data(inode)) { | 4256 | if (ext4_has_inline_data(inode)) { |
| 4223 | int has_inline = 1; | 4257 | int has_inline = 1; |
| 4224 | 4258 | ||
| 4225 | ext4_inline_data_truncate(inode, &has_inline); | 4259 | err = ext4_inline_data_truncate(inode, &has_inline); |
| 4260 | if (err) | ||
| 4261 | return err; | ||
| 4226 | if (has_inline) | 4262 | if (has_inline) |
| 4227 | return 0; | 4263 | return 0; |
| 4228 | } | 4264 | } |
| @@ -5197,6 +5233,9 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 5197 | int orphan = 0; | 5233 | int orphan = 0; |
| 5198 | const unsigned int ia_valid = attr->ia_valid; | 5234 | const unsigned int ia_valid = attr->ia_valid; |
| 5199 | 5235 | ||
| 5236 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 5237 | return -EIO; | ||
| 5238 | |||
| 5200 | error = setattr_prepare(dentry, attr); | 5239 | error = setattr_prepare(dentry, attr); |
| 5201 | if (error) | 5240 | if (error) |
| 5202 | return error; | 5241 | return error; |
| @@ -5483,6 +5522,9 @@ int ext4_mark_iloc_dirty(handle_t *handle, | |||
| 5483 | { | 5522 | { |
| 5484 | int err = 0; | 5523 | int err = 0; |
| 5485 | 5524 | ||
| 5525 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 5526 | return -EIO; | ||
| 5527 | |||
| 5486 | if (IS_I_VERSION(inode)) | 5528 | if (IS_I_VERSION(inode)) |
| 5487 | inode_inc_iversion(inode); | 5529 | inode_inc_iversion(inode); |
| 5488 | 5530 | ||
| @@ -5506,6 +5548,9 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode, | |||
| 5506 | { | 5548 | { |
| 5507 | int err; | 5549 | int err; |
| 5508 | 5550 | ||
| 5551 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 5552 | return -EIO; | ||
| 5553 | |||
| 5509 | err = ext4_get_inode_loc(inode, iloc); | 5554 | err = ext4_get_inode_loc(inode, iloc); |
| 5510 | if (!err) { | 5555 | if (!err) { |
| 5511 | BUFFER_TRACE(iloc->bh, "get_write_access"); | 5556 | BUFFER_TRACE(iloc->bh, "get_write_access"); |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index d534399cf607..a4273ddb9922 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/quotaops.h> | 16 | #include <linux/quotaops.h> |
| 17 | #include <linux/uuid.h> | 17 | #include <linux/uuid.h> |
| 18 | #include <linux/uaccess.h> | 18 | #include <linux/uaccess.h> |
| 19 | #include <linux/delay.h> | ||
| 19 | #include "ext4_jbd2.h" | 20 | #include "ext4_jbd2.h" |
| 20 | #include "ext4.h" | 21 | #include "ext4.h" |
| 21 | 22 | ||
| @@ -442,6 +443,52 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags) | |||
| 442 | return iflags; | 443 | return iflags; |
| 443 | } | 444 | } |
| 444 | 445 | ||
| 446 | int ext4_shutdown(struct super_block *sb, unsigned long arg) | ||
| 447 | { | ||
| 448 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 449 | __u32 flags; | ||
| 450 | |||
| 451 | if (!capable(CAP_SYS_ADMIN)) | ||
| 452 | return -EPERM; | ||
| 453 | |||
| 454 | if (get_user(flags, (__u32 __user *)arg)) | ||
| 455 | return -EFAULT; | ||
| 456 | |||
| 457 | if (flags > EXT4_GOING_FLAGS_NOLOGFLUSH) | ||
| 458 | return -EINVAL; | ||
| 459 | |||
| 460 | if (ext4_forced_shutdown(sbi)) | ||
| 461 | return 0; | ||
| 462 | |||
| 463 | ext4_msg(sb, KERN_ALERT, "shut down requested (%d)", flags); | ||
| 464 | |||
| 465 | switch (flags) { | ||
| 466 | case EXT4_GOING_FLAGS_DEFAULT: | ||
| 467 | freeze_bdev(sb->s_bdev); | ||
| 468 | set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); | ||
| 469 | thaw_bdev(sb->s_bdev, sb); | ||
| 470 | break; | ||
| 471 | case EXT4_GOING_FLAGS_LOGFLUSH: | ||
| 472 | set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); | ||
| 473 | if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) { | ||
| 474 | (void) ext4_force_commit(sb); | ||
| 475 | jbd2_journal_abort(sbi->s_journal, 0); | ||
| 476 | } | ||
| 477 | break; | ||
| 478 | case EXT4_GOING_FLAGS_NOLOGFLUSH: | ||
| 479 | set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); | ||
| 480 | if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) { | ||
| 481 | msleep(100); | ||
| 482 | jbd2_journal_abort(sbi->s_journal, 0); | ||
| 483 | } | ||
| 484 | break; | ||
| 485 | default: | ||
| 486 | return -EINVAL; | ||
| 487 | } | ||
| 488 | clear_opt(sb, DISCARD); | ||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | |||
| 445 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 492 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
| 446 | { | 493 | { |
| 447 | struct inode *inode = file_inode(filp); | 494 | struct inode *inode = file_inode(filp); |
| @@ -893,6 +940,8 @@ resizefs_out: | |||
| 893 | 940 | ||
| 894 | return 0; | 941 | return 0; |
| 895 | } | 942 | } |
| 943 | case EXT4_IOC_SHUTDOWN: | ||
| 944 | return ext4_shutdown(sb, arg); | ||
| 896 | default: | 945 | default: |
| 897 | return -ENOTTY; | 946 | return -ENOTTY; |
| 898 | } | 947 | } |
| @@ -959,6 +1008,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 959 | case EXT4_IOC_SET_ENCRYPTION_POLICY: | 1008 | case EXT4_IOC_SET_ENCRYPTION_POLICY: |
| 960 | case EXT4_IOC_GET_ENCRYPTION_PWSALT: | 1009 | case EXT4_IOC_GET_ENCRYPTION_PWSALT: |
| 961 | case EXT4_IOC_GET_ENCRYPTION_POLICY: | 1010 | case EXT4_IOC_GET_ENCRYPTION_POLICY: |
| 1011 | case EXT4_IOC_SHUTDOWN: | ||
| 962 | break; | 1012 | break; |
| 963 | default: | 1013 | default: |
| 964 | return -ENOIOCTLCMD; | 1014 | return -ENOIOCTLCMD; |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 7ae43c59bc79..10c62de642c6 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -1556,7 +1556,17 @@ static int mb_find_extent(struct ext4_buddy *e4b, int block, | |||
| 1556 | ex->fe_len += 1 << order; | 1556 | ex->fe_len += 1 << order; |
| 1557 | } | 1557 | } |
| 1558 | 1558 | ||
| 1559 | BUG_ON(ex->fe_start + ex->fe_len > (1 << (e4b->bd_blkbits + 3))); | 1559 | if (ex->fe_start + ex->fe_len > (1 << (e4b->bd_blkbits + 3))) { |
| 1560 | /* Should never happen! (but apparently sometimes does?!?) */ | ||
| 1561 | WARN_ON(1); | ||
| 1562 | ext4_error(e4b->bd_sb, "corruption or bug in mb_find_extent " | ||
| 1563 | "block=%d, order=%d needed=%d ex=%u/%d/%d@%u", | ||
| 1564 | block, order, needed, ex->fe_group, ex->fe_start, | ||
| 1565 | ex->fe_len, ex->fe_logical); | ||
| 1566 | ex->fe_len = 0; | ||
| 1567 | ex->fe_start = 0; | ||
| 1568 | ex->fe_group = 0; | ||
| 1569 | } | ||
| 1560 | return ex->fe_len; | 1570 | return ex->fe_len; |
| 1561 | } | 1571 | } |
| 1562 | 1572 | ||
| @@ -2136,8 +2146,10 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac) | |||
| 2136 | * We search using buddy data only if the order of the request | 2146 | * We search using buddy data only if the order of the request |
| 2137 | * is greater than equal to the sbi_s_mb_order2_reqs | 2147 | * is greater than equal to the sbi_s_mb_order2_reqs |
| 2138 | * You can tune it via /sys/fs/ext4/<partition>/mb_order2_req | 2148 | * You can tune it via /sys/fs/ext4/<partition>/mb_order2_req |
| 2149 | * We also support searching for power-of-two requests only for | ||
| 2150 | * requests upto maximum buddy size we have constructed. | ||
| 2139 | */ | 2151 | */ |
| 2140 | if (i >= sbi->s_mb_order2_reqs) { | 2152 | if (i >= sbi->s_mb_order2_reqs && i <= sb->s_blocksize_bits + 2) { |
| 2141 | /* | 2153 | /* |
| 2142 | * This should tell if fe_len is exactly power of 2 | 2154 | * This should tell if fe_len is exactly power of 2 |
| 2143 | */ | 2155 | */ |
| @@ -2207,7 +2219,7 @@ repeat: | |||
| 2207 | } | 2219 | } |
| 2208 | 2220 | ||
| 2209 | ac->ac_groups_scanned++; | 2221 | ac->ac_groups_scanned++; |
| 2210 | if (cr == 0 && ac->ac_2order < sb->s_blocksize_bits+2) | 2222 | if (cr == 0) |
| 2211 | ext4_mb_simple_scan_group(ac, &e4b); | 2223 | ext4_mb_simple_scan_group(ac, &e4b); |
| 2212 | else if (cr == 1 && sbi->s_stripe && | 2224 | else if (cr == 1 && sbi->s_stripe && |
| 2213 | !(ac->ac_g_ex.fe_len % sbi->s_stripe)) | 2225 | !(ac->ac_g_ex.fe_len % sbi->s_stripe)) |
| @@ -3123,6 +3135,13 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
| 3123 | if (ar->pright && start + size - 1 >= ar->lright) | 3135 | if (ar->pright && start + size - 1 >= ar->lright) |
| 3124 | size -= start + size - ar->lright; | 3136 | size -= start + size - ar->lright; |
| 3125 | 3137 | ||
| 3138 | /* | ||
| 3139 | * Trim allocation request for filesystems with artificially small | ||
| 3140 | * groups. | ||
| 3141 | */ | ||
| 3142 | if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) | ||
| 3143 | size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb); | ||
| 3144 | |||
| 3126 | end = start + size; | 3145 | end = start + size; |
| 3127 | 3146 | ||
| 3128 | /* check we don't cross already preallocated blocks */ | 3147 | /* check we don't cross already preallocated blocks */ |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index bb880c326191..6ad612c576fc 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -1618,13 +1618,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi | |||
| 1618 | !fscrypt_has_permitted_context(dir, inode)) { | 1618 | !fscrypt_has_permitted_context(dir, inode)) { |
| 1619 | int nokey = ext4_encrypted_inode(inode) && | 1619 | int nokey = ext4_encrypted_inode(inode) && |
| 1620 | !fscrypt_has_encryption_key(inode); | 1620 | !fscrypt_has_encryption_key(inode); |
| 1621 | iput(inode); | 1621 | if (nokey) { |
| 1622 | if (nokey) | 1622 | iput(inode); |
| 1623 | return ERR_PTR(-ENOKEY); | 1623 | return ERR_PTR(-ENOKEY); |
| 1624 | } | ||
| 1624 | ext4_warning(inode->i_sb, | 1625 | ext4_warning(inode->i_sb, |
| 1625 | "Inconsistent encryption contexts: %lu/%lu", | 1626 | "Inconsistent encryption contexts: %lu/%lu", |
| 1626 | (unsigned long) dir->i_ino, | 1627 | (unsigned long) dir->i_ino, |
| 1627 | (unsigned long) inode->i_ino); | 1628 | (unsigned long) inode->i_ino); |
| 1629 | iput(inode); | ||
| 1628 | return ERR_PTR(-EPERM); | 1630 | return ERR_PTR(-EPERM); |
| 1629 | } | 1631 | } |
| 1630 | } | 1632 | } |
| @@ -2937,6 +2939,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 2937 | struct ext4_dir_entry_2 *de; | 2939 | struct ext4_dir_entry_2 *de; |
| 2938 | handle_t *handle = NULL; | 2940 | handle_t *handle = NULL; |
| 2939 | 2941 | ||
| 2942 | if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) | ||
| 2943 | return -EIO; | ||
| 2944 | |||
| 2940 | /* Initialize quotas before so that eventual writes go in | 2945 | /* Initialize quotas before so that eventual writes go in |
| 2941 | * separate transaction */ | 2946 | * separate transaction */ |
| 2942 | retval = dquot_initialize(dir); | 2947 | retval = dquot_initialize(dir); |
| @@ -3010,6 +3015,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) | |||
| 3010 | struct ext4_dir_entry_2 *de; | 3015 | struct ext4_dir_entry_2 *de; |
| 3011 | handle_t *handle = NULL; | 3016 | handle_t *handle = NULL; |
| 3012 | 3017 | ||
| 3018 | if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) | ||
| 3019 | return -EIO; | ||
| 3020 | |||
| 3013 | trace_ext4_unlink_enter(dir, dentry); | 3021 | trace_ext4_unlink_enter(dir, dentry); |
| 3014 | /* Initialize quotas before so that eventual writes go | 3022 | /* Initialize quotas before so that eventual writes go |
| 3015 | * in separate transaction */ | 3023 | * in separate transaction */ |
| @@ -3080,6 +3088,9 @@ static int ext4_symlink(struct inode *dir, | |||
| 3080 | struct fscrypt_str disk_link; | 3088 | struct fscrypt_str disk_link; |
| 3081 | struct fscrypt_symlink_data *sd = NULL; | 3089 | struct fscrypt_symlink_data *sd = NULL; |
| 3082 | 3090 | ||
| 3091 | if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) | ||
| 3092 | return -EIO; | ||
| 3093 | |||
| 3083 | disk_link.len = len + 1; | 3094 | disk_link.len = len + 1; |
| 3084 | disk_link.name = (char *) symname; | 3095 | disk_link.name = (char *) symname; |
| 3085 | 3096 | ||
| @@ -3872,6 +3883,9 @@ static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry, | |||
| 3872 | struct inode *new_dir, struct dentry *new_dentry, | 3883 | struct inode *new_dir, struct dentry *new_dentry, |
| 3873 | unsigned int flags) | 3884 | unsigned int flags) |
| 3874 | { | 3885 | { |
| 3886 | if (unlikely(ext4_forced_shutdown(EXT4_SB(old_dir->i_sb)))) | ||
| 3887 | return -EIO; | ||
| 3888 | |||
| 3875 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) | 3889 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) |
| 3876 | return -EINVAL; | 3890 | return -EINVAL; |
| 3877 | 3891 | ||
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index e55624c50898..208241b06662 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
| @@ -157,7 +157,7 @@ static int ext4_end_io(ext4_io_end_t *io) | |||
| 157 | 157 | ||
| 158 | io->handle = NULL; /* Following call will use up the handle */ | 158 | io->handle = NULL; /* Following call will use up the handle */ |
| 159 | ret = ext4_convert_unwritten_extents(handle, inode, offset, size); | 159 | ret = ext4_convert_unwritten_extents(handle, inode, offset, size); |
| 160 | if (ret < 0) { | 160 | if (ret < 0 && !ext4_forced_shutdown(EXT4_SB(inode->i_sb))) { |
| 161 | ext4_msg(inode->i_sb, KERN_EMERG, | 161 | ext4_msg(inode->i_sb, KERN_EMERG, |
| 162 | "failed to convert unwritten extents to written " | 162 | "failed to convert unwritten extents to written " |
| 163 | "extents -- potential data loss! " | 163 | "extents -- potential data loss! " |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index cf681004b196..c3ed9021b781 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -45,7 +45,8 @@ int ext4_resize_begin(struct super_block *sb) | |||
| 45 | return -EPERM; | 45 | return -EPERM; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | if (test_and_set_bit_lock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags)) | 48 | if (test_and_set_bit_lock(EXT4_FLAGS_RESIZING, |
| 49 | &EXT4_SB(sb)->s_ext4_flags)) | ||
| 49 | ret = -EBUSY; | 50 | ret = -EBUSY; |
| 50 | 51 | ||
| 51 | return ret; | 52 | return ret; |
| @@ -53,7 +54,7 @@ int ext4_resize_begin(struct super_block *sb) | |||
| 53 | 54 | ||
| 54 | void ext4_resize_end(struct super_block *sb) | 55 | void ext4_resize_end(struct super_block *sb) |
| 55 | { | 56 | { |
| 56 | clear_bit_unlock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags); | 57 | clear_bit_unlock(EXT4_FLAGS_RESIZING, &EXT4_SB(sb)->s_ext4_flags); |
| 57 | smp_mb__after_atomic(); | 58 | smp_mb__after_atomic(); |
| 58 | } | 59 | } |
| 59 | 60 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 20539c2cd6d8..2e03a0a88d92 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -438,6 +438,9 @@ void __ext4_error(struct super_block *sb, const char *function, | |||
| 438 | struct va_format vaf; | 438 | struct va_format vaf; |
| 439 | va_list args; | 439 | va_list args; |
| 440 | 440 | ||
| 441 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) | ||
| 442 | return; | ||
| 443 | |||
| 441 | if (ext4_error_ratelimit(sb)) { | 444 | if (ext4_error_ratelimit(sb)) { |
| 442 | va_start(args, fmt); | 445 | va_start(args, fmt); |
| 443 | vaf.fmt = fmt; | 446 | vaf.fmt = fmt; |
| @@ -459,6 +462,9 @@ void __ext4_error_inode(struct inode *inode, const char *function, | |||
| 459 | struct va_format vaf; | 462 | struct va_format vaf; |
| 460 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | 463 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; |
| 461 | 464 | ||
| 465 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 466 | return; | ||
| 467 | |||
| 462 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); | 468 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); |
| 463 | es->s_last_error_block = cpu_to_le64(block); | 469 | es->s_last_error_block = cpu_to_le64(block); |
| 464 | if (ext4_error_ratelimit(inode->i_sb)) { | 470 | if (ext4_error_ratelimit(inode->i_sb)) { |
| @@ -491,6 +497,9 @@ void __ext4_error_file(struct file *file, const char *function, | |||
| 491 | struct inode *inode = file_inode(file); | 497 | struct inode *inode = file_inode(file); |
| 492 | char pathname[80], *path; | 498 | char pathname[80], *path; |
| 493 | 499 | ||
| 500 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 501 | return; | ||
| 502 | |||
| 494 | es = EXT4_SB(inode->i_sb)->s_es; | 503 | es = EXT4_SB(inode->i_sb)->s_es; |
| 495 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); | 504 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); |
| 496 | if (ext4_error_ratelimit(inode->i_sb)) { | 505 | if (ext4_error_ratelimit(inode->i_sb)) { |
| @@ -567,6 +576,9 @@ void __ext4_std_error(struct super_block *sb, const char *function, | |||
| 567 | char nbuf[16]; | 576 | char nbuf[16]; |
| 568 | const char *errstr; | 577 | const char *errstr; |
| 569 | 578 | ||
| 579 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) | ||
| 580 | return; | ||
| 581 | |||
| 570 | /* Special case: if the error is EROFS, and we're not already | 582 | /* Special case: if the error is EROFS, and we're not already |
| 571 | * inside a transaction, then there's really no point in logging | 583 | * inside a transaction, then there's really no point in logging |
| 572 | * an error. */ | 584 | * an error. */ |
| @@ -600,6 +612,9 @@ void __ext4_abort(struct super_block *sb, const char *function, | |||
| 600 | struct va_format vaf; | 612 | struct va_format vaf; |
| 601 | va_list args; | 613 | va_list args; |
| 602 | 614 | ||
| 615 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) | ||
| 616 | return; | ||
| 617 | |||
| 603 | save_error_info(sb, function, line); | 618 | save_error_info(sb, function, line); |
| 604 | va_start(args, fmt); | 619 | va_start(args, fmt); |
| 605 | vaf.fmt = fmt; | 620 | vaf.fmt = fmt; |
| @@ -695,6 +710,9 @@ __acquires(bitlock) | |||
| 695 | va_list args; | 710 | va_list args; |
| 696 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 711 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
| 697 | 712 | ||
| 713 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) | ||
| 714 | return; | ||
| 715 | |||
| 698 | es->s_last_error_ino = cpu_to_le32(ino); | 716 | es->s_last_error_ino = cpu_to_le32(ino); |
| 699 | es->s_last_error_block = cpu_to_le64(block); | 717 | es->s_last_error_block = cpu_to_le64(block); |
| 700 | __save_error_info(sb, function, line); | 718 | __save_error_info(sb, function, line); |
| @@ -825,6 +843,7 @@ static void ext4_put_super(struct super_block *sb) | |||
| 825 | { | 843 | { |
| 826 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 844 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 827 | struct ext4_super_block *es = sbi->s_es; | 845 | struct ext4_super_block *es = sbi->s_es; |
| 846 | int aborted = 0; | ||
| 828 | int i, err; | 847 | int i, err; |
| 829 | 848 | ||
| 830 | ext4_unregister_li_request(sb); | 849 | ext4_unregister_li_request(sb); |
| @@ -834,9 +853,10 @@ static void ext4_put_super(struct super_block *sb) | |||
| 834 | destroy_workqueue(sbi->rsv_conversion_wq); | 853 | destroy_workqueue(sbi->rsv_conversion_wq); |
| 835 | 854 | ||
| 836 | if (sbi->s_journal) { | 855 | if (sbi->s_journal) { |
| 856 | aborted = is_journal_aborted(sbi->s_journal); | ||
| 837 | err = jbd2_journal_destroy(sbi->s_journal); | 857 | err = jbd2_journal_destroy(sbi->s_journal); |
| 838 | sbi->s_journal = NULL; | 858 | sbi->s_journal = NULL; |
| 839 | if (err < 0) | 859 | if ((err < 0) && !aborted) |
| 840 | ext4_abort(sb, "Couldn't clean up the journal"); | 860 | ext4_abort(sb, "Couldn't clean up the journal"); |
| 841 | } | 861 | } |
| 842 | 862 | ||
| @@ -847,7 +867,7 @@ static void ext4_put_super(struct super_block *sb) | |||
| 847 | ext4_mb_release(sb); | 867 | ext4_mb_release(sb); |
| 848 | ext4_ext_release(sb); | 868 | ext4_ext_release(sb); |
| 849 | 869 | ||
| 850 | if (!(sb->s_flags & MS_RDONLY)) { | 870 | if (!(sb->s_flags & MS_RDONLY) && !aborted) { |
| 851 | ext4_clear_feature_journal_needs_recovery(sb); | 871 | ext4_clear_feature_journal_needs_recovery(sb); |
| 852 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 872 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| 853 | } | 873 | } |
| @@ -1284,7 +1304,7 @@ enum { | |||
| 1284 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, | 1304 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, |
| 1285 | Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax, | 1305 | Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax, |
| 1286 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, | 1306 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, |
| 1287 | Opt_lazytime, Opt_nolazytime, | 1307 | Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize, |
| 1288 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, | 1308 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, |
| 1289 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1309 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
| 1290 | Opt_dioread_nolock, Opt_dioread_lock, | 1310 | Opt_dioread_nolock, Opt_dioread_lock, |
| @@ -1352,6 +1372,7 @@ static const match_table_t tokens = { | |||
| 1352 | {Opt_delalloc, "delalloc"}, | 1372 | {Opt_delalloc, "delalloc"}, |
| 1353 | {Opt_lazytime, "lazytime"}, | 1373 | {Opt_lazytime, "lazytime"}, |
| 1354 | {Opt_nolazytime, "nolazytime"}, | 1374 | {Opt_nolazytime, "nolazytime"}, |
| 1375 | {Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"}, | ||
| 1355 | {Opt_nodelalloc, "nodelalloc"}, | 1376 | {Opt_nodelalloc, "nodelalloc"}, |
| 1356 | {Opt_removed, "mblk_io_submit"}, | 1377 | {Opt_removed, "mblk_io_submit"}, |
| 1357 | {Opt_removed, "nomblk_io_submit"}, | 1378 | {Opt_removed, "nomblk_io_submit"}, |
| @@ -1557,6 +1578,7 @@ static const struct mount_opts { | |||
| 1557 | #endif | 1578 | #endif |
| 1558 | {Opt_nouid32, EXT4_MOUNT_NO_UID32, MOPT_SET}, | 1579 | {Opt_nouid32, EXT4_MOUNT_NO_UID32, MOPT_SET}, |
| 1559 | {Opt_debug, EXT4_MOUNT_DEBUG, MOPT_SET}, | 1580 | {Opt_debug, EXT4_MOUNT_DEBUG, MOPT_SET}, |
| 1581 | {Opt_debug_want_extra_isize, 0, MOPT_GTE0}, | ||
| 1560 | {Opt_quota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, MOPT_SET | MOPT_Q}, | 1582 | {Opt_quota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, MOPT_SET | MOPT_Q}, |
| 1561 | {Opt_usrquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, | 1583 | {Opt_usrquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, |
| 1562 | MOPT_SET | MOPT_Q}, | 1584 | MOPT_SET | MOPT_Q}, |
| @@ -1670,6 +1692,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
| 1670 | if (arg == 0) | 1692 | if (arg == 0) |
| 1671 | arg = JBD2_DEFAULT_MAX_COMMIT_AGE; | 1693 | arg = JBD2_DEFAULT_MAX_COMMIT_AGE; |
| 1672 | sbi->s_commit_interval = HZ * arg; | 1694 | sbi->s_commit_interval = HZ * arg; |
| 1695 | } else if (token == Opt_debug_want_extra_isize) { | ||
| 1696 | sbi->s_want_extra_isize = arg; | ||
| 1673 | } else if (token == Opt_max_batch_time) { | 1697 | } else if (token == Opt_max_batch_time) { |
| 1674 | sbi->s_max_batch_time = arg; | 1698 | sbi->s_max_batch_time = arg; |
| 1675 | } else if (token == Opt_min_batch_time) { | 1699 | } else if (token == Opt_min_batch_time) { |
| @@ -2613,9 +2637,9 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi) | |||
| 2613 | 2637 | ||
| 2614 | if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group) | 2638 | if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group) |
| 2615 | ret = sbi->s_stripe; | 2639 | ret = sbi->s_stripe; |
| 2616 | else if (stripe_width <= sbi->s_blocks_per_group) | 2640 | else if (stripe_width && stripe_width <= sbi->s_blocks_per_group) |
| 2617 | ret = stripe_width; | 2641 | ret = stripe_width; |
| 2618 | else if (stride <= sbi->s_blocks_per_group) | 2642 | else if (stride && stride <= sbi->s_blocks_per_group) |
| 2619 | ret = stride; | 2643 | ret = stride; |
| 2620 | else | 2644 | else |
| 2621 | ret = 0; | 2645 | ret = 0; |
| @@ -3836,7 +3860,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3836 | db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / | 3860 | db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / |
| 3837 | EXT4_DESC_PER_BLOCK(sb); | 3861 | EXT4_DESC_PER_BLOCK(sb); |
| 3838 | if (ext4_has_feature_meta_bg(sb)) { | 3862 | if (ext4_has_feature_meta_bg(sb)) { |
| 3839 | if (le32_to_cpu(es->s_first_meta_bg) >= db_count) { | 3863 | if (le32_to_cpu(es->s_first_meta_bg) > db_count) { |
| 3840 | ext4_msg(sb, KERN_WARNING, | 3864 | ext4_msg(sb, KERN_WARNING, |
| 3841 | "first meta block group too large: %u " | 3865 | "first meta block group too large: %u " |
| 3842 | "(group descriptor block count %u)", | 3866 | "(group descriptor block count %u)", |
| @@ -3919,7 +3943,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3919 | * root first: it may be modified in the journal! | 3943 | * root first: it may be modified in the journal! |
| 3920 | */ | 3944 | */ |
| 3921 | if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) { | 3945 | if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) { |
| 3922 | if (ext4_load_journal(sb, es, journal_devnum)) | 3946 | err = ext4_load_journal(sb, es, journal_devnum); |
| 3947 | if (err) | ||
| 3923 | goto failed_mount3a; | 3948 | goto failed_mount3a; |
| 3924 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && | 3949 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && |
| 3925 | ext4_has_feature_journal_needs_recovery(sb)) { | 3950 | ext4_has_feature_journal_needs_recovery(sb)) { |
| @@ -4081,7 +4106,8 @@ no_journal: | |||
| 4081 | sb->s_flags |= MS_RDONLY; | 4106 | sb->s_flags |= MS_RDONLY; |
| 4082 | 4107 | ||
| 4083 | /* determine the minimum size of new large inodes, if present */ | 4108 | /* determine the minimum size of new large inodes, if present */ |
| 4084 | if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { | 4109 | if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE && |
| 4110 | sbi->s_want_extra_isize == 0) { | ||
| 4085 | sbi->s_want_extra_isize = sizeof(struct ext4_inode) - | 4111 | sbi->s_want_extra_isize = sizeof(struct ext4_inode) - |
| 4086 | EXT4_GOOD_OLD_INODE_SIZE; | 4112 | EXT4_GOOD_OLD_INODE_SIZE; |
| 4087 | if (ext4_has_feature_extra_isize(sb)) { | 4113 | if (ext4_has_feature_extra_isize(sb)) { |
| @@ -4709,6 +4735,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
| 4709 | bool needs_barrier = false; | 4735 | bool needs_barrier = false; |
| 4710 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 4736 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 4711 | 4737 | ||
| 4738 | if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) | ||
| 4739 | return 0; | ||
| 4740 | |||
| 4712 | trace_ext4_sync_fs(sb, wait); | 4741 | trace_ext4_sync_fs(sb, wait); |
| 4713 | flush_workqueue(sbi->rsv_conversion_wq); | 4742 | flush_workqueue(sbi->rsv_conversion_wq); |
| 4714 | /* | 4743 | /* |
| @@ -4792,7 +4821,7 @@ out: | |||
| 4792 | */ | 4821 | */ |
| 4793 | static int ext4_unfreeze(struct super_block *sb) | 4822 | static int ext4_unfreeze(struct super_block *sb) |
| 4794 | { | 4823 | { |
| 4795 | if (sb->s_flags & MS_RDONLY) | 4824 | if ((sb->s_flags & MS_RDONLY) || ext4_forced_shutdown(EXT4_SB(sb))) |
| 4796 | return 0; | 4825 | return 0; |
| 4797 | 4826 | ||
| 4798 | if (EXT4_SB(sb)->s_journal) { | 4827 | if (EXT4_SB(sb)->s_journal) { |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 5a94fa52b74f..67636acf7624 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
| @@ -411,6 +411,9 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name, | |||
| 411 | { | 411 | { |
| 412 | int error; | 412 | int error; |
| 413 | 413 | ||
| 414 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | ||
| 415 | return -EIO; | ||
| 416 | |||
| 414 | if (strlen(name) > 255) | 417 | if (strlen(name) > 255) |
| 415 | return -ERANGE; | 418 | return -ERANGE; |
| 416 | 419 | ||
| @@ -1188,16 +1191,14 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
| 1188 | struct ext4_xattr_block_find bs = { | 1191 | struct ext4_xattr_block_find bs = { |
| 1189 | .s = { .not_found = -ENODATA, }, | 1192 | .s = { .not_found = -ENODATA, }, |
| 1190 | }; | 1193 | }; |
| 1191 | unsigned long no_expand; | 1194 | int no_expand; |
| 1192 | int error; | 1195 | int error; |
| 1193 | 1196 | ||
| 1194 | if (!name) | 1197 | if (!name) |
| 1195 | return -EINVAL; | 1198 | return -EINVAL; |
| 1196 | if (strlen(name) > 255) | 1199 | if (strlen(name) > 255) |
| 1197 | return -ERANGE; | 1200 | return -ERANGE; |
| 1198 | down_write(&EXT4_I(inode)->xattr_sem); | 1201 | ext4_write_lock_xattr(inode, &no_expand); |
| 1199 | no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 1200 | ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 1201 | 1202 | ||
| 1202 | error = ext4_reserve_inode_write(handle, inode, &is.iloc); | 1203 | error = ext4_reserve_inode_write(handle, inode, &is.iloc); |
| 1203 | if (error) | 1204 | if (error) |
| @@ -1264,7 +1265,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
| 1264 | ext4_xattr_update_super_block(handle, inode->i_sb); | 1265 | ext4_xattr_update_super_block(handle, inode->i_sb); |
| 1265 | inode->i_ctime = current_time(inode); | 1266 | inode->i_ctime = current_time(inode); |
| 1266 | if (!value) | 1267 | if (!value) |
| 1267 | ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); | 1268 | no_expand = 0; |
| 1268 | error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); | 1269 | error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); |
| 1269 | /* | 1270 | /* |
| 1270 | * The bh is consumed by ext4_mark_iloc_dirty, even with | 1271 | * The bh is consumed by ext4_mark_iloc_dirty, even with |
| @@ -1278,9 +1279,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
| 1278 | cleanup: | 1279 | cleanup: |
| 1279 | brelse(is.iloc.bh); | 1280 | brelse(is.iloc.bh); |
| 1280 | brelse(bs.bh); | 1281 | brelse(bs.bh); |
| 1281 | if (no_expand == 0) | 1282 | ext4_write_unlock_xattr(inode, &no_expand); |
| 1282 | ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 1283 | up_write(&EXT4_I(inode)->xattr_sem); | ||
| 1284 | return error; | 1283 | return error; |
| 1285 | } | 1284 | } |
| 1286 | 1285 | ||
| @@ -1497,12 +1496,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, | |||
| 1497 | int error = 0, tried_min_extra_isize = 0; | 1496 | int error = 0, tried_min_extra_isize = 0; |
| 1498 | int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); | 1497 | int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); |
| 1499 | int isize_diff; /* How much do we need to grow i_extra_isize */ | 1498 | int isize_diff; /* How much do we need to grow i_extra_isize */ |
| 1499 | int no_expand; | ||
| 1500 | |||
| 1501 | if (ext4_write_trylock_xattr(inode, &no_expand) == 0) | ||
| 1502 | return 0; | ||
| 1500 | 1503 | ||
| 1501 | down_write(&EXT4_I(inode)->xattr_sem); | ||
| 1502 | /* | ||
| 1503 | * Set EXT4_STATE_NO_EXPAND to avoid recursion when marking inode dirty | ||
| 1504 | */ | ||
| 1505 | ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 1506 | retry: | 1504 | retry: |
| 1507 | isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize; | 1505 | isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize; |
| 1508 | if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) | 1506 | if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) |
| @@ -1584,17 +1582,16 @@ shift: | |||
| 1584 | EXT4_I(inode)->i_extra_isize = new_extra_isize; | 1582 | EXT4_I(inode)->i_extra_isize = new_extra_isize; |
| 1585 | brelse(bh); | 1583 | brelse(bh); |
| 1586 | out: | 1584 | out: |
| 1587 | ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); | 1585 | ext4_write_unlock_xattr(inode, &no_expand); |
| 1588 | up_write(&EXT4_I(inode)->xattr_sem); | ||
| 1589 | return 0; | 1586 | return 0; |
| 1590 | 1587 | ||
| 1591 | cleanup: | 1588 | cleanup: |
| 1592 | brelse(bh); | 1589 | brelse(bh); |
| 1593 | /* | 1590 | /* |
| 1594 | * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode | 1591 | * Inode size expansion failed; don't try again |
| 1595 | * size expansion failed. | ||
| 1596 | */ | 1592 | */ |
| 1597 | up_write(&EXT4_I(inode)->xattr_sem); | 1593 | no_expand = 1; |
| 1594 | ext4_write_unlock_xattr(inode, &no_expand); | ||
| 1598 | return error; | 1595 | return error; |
| 1599 | } | 1596 | } |
| 1600 | 1597 | ||
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index a92e783fa057..099c8b670ef5 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
| @@ -102,6 +102,38 @@ extern const struct xattr_handler ext4_xattr_security_handler; | |||
| 102 | 102 | ||
| 103 | #define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c" | 103 | #define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c" |
| 104 | 104 | ||
| 105 | /* | ||
| 106 | * The EXT4_STATE_NO_EXPAND is overloaded and used for two purposes. | ||
| 107 | * The first is to signal that there the inline xattrs and data are | ||
| 108 | * taking up so much space that we might as well not keep trying to | ||
| 109 | * expand it. The second is that xattr_sem is taken for writing, so | ||
| 110 | * we shouldn't try to recurse into the inode expansion. For this | ||
| 111 | * second case, we need to make sure that we take save and restore the | ||
| 112 | * NO_EXPAND state flag appropriately. | ||
| 113 | */ | ||
| 114 | static inline void ext4_write_lock_xattr(struct inode *inode, int *save) | ||
| 115 | { | ||
| 116 | down_write(&EXT4_I(inode)->xattr_sem); | ||
| 117 | *save = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 118 | ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline int ext4_write_trylock_xattr(struct inode *inode, int *save) | ||
| 122 | { | ||
| 123 | if (down_write_trylock(&EXT4_I(inode)->xattr_sem) == 0) | ||
| 124 | return 0; | ||
| 125 | *save = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 126 | ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 127 | return 1; | ||
| 128 | } | ||
| 129 | |||
| 130 | static inline void ext4_write_unlock_xattr(struct inode *inode, int *save) | ||
| 131 | { | ||
| 132 | if (*save == 0) | ||
| 133 | ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); | ||
| 134 | up_write(&EXT4_I(inode)->xattr_sem); | ||
| 135 | } | ||
| 136 | |||
| 105 | extern ssize_t ext4_listxattr(struct dentry *, char *, size_t); | 137 | extern ssize_t ext4_listxattr(struct dentry *, char *, size_t); |
| 106 | 138 | ||
| 107 | extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t); | 139 | extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index d8a5d0a08f07..a1a359bfcc9c 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -276,11 +276,11 @@ loop: | |||
| 276 | goto loop; | 276 | goto loop; |
| 277 | 277 | ||
| 278 | end_loop: | 278 | end_loop: |
| 279 | write_unlock(&journal->j_state_lock); | ||
| 280 | del_timer_sync(&journal->j_commit_timer); | 279 | del_timer_sync(&journal->j_commit_timer); |
| 281 | journal->j_task = NULL; | 280 | journal->j_task = NULL; |
| 282 | wake_up(&journal->j_wait_done_commit); | 281 | wake_up(&journal->j_wait_done_commit); |
| 283 | jbd_debug(1, "Journal thread exiting.\n"); | 282 | jbd_debug(1, "Journal thread exiting.\n"); |
| 283 | write_unlock(&journal->j_state_lock); | ||
| 284 | return 0; | 284 | return 0; |
| 285 | } | 285 | } |
| 286 | 286 | ||
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index e1652665bd93..5e659ee08d6a 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -1863,7 +1863,9 @@ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh) | |||
| 1863 | 1863 | ||
| 1864 | __blist_del_buffer(list, jh); | 1864 | __blist_del_buffer(list, jh); |
| 1865 | jh->b_jlist = BJ_None; | 1865 | jh->b_jlist = BJ_None; |
| 1866 | if (test_clear_buffer_jbddirty(bh)) | 1866 | if (transaction && is_journal_aborted(transaction->t_journal)) |
| 1867 | clear_buffer_jbddirty(bh); | ||
| 1868 | else if (test_clear_buffer_jbddirty(bh)) | ||
| 1867 | mark_buffer_dirty(bh); /* Expose it to the VM */ | 1869 | mark_buffer_dirty(bh); /* Expose it to the VM */ |
| 1868 | } | 1870 | } |
| 1869 | 1871 | ||
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h index f4754282c9c2..3252799832cf 100644 --- a/include/linux/cryptohash.h +++ b/include/linux/cryptohash.h | |||
| @@ -15,6 +15,4 @@ void sha_transform(__u32 *digest, const char *data, __u32 *W); | |||
| 15 | 15 | ||
| 16 | void md5_transform(__u32 *hash, __u32 const *in); | 16 | void md5_transform(__u32 *hash, __u32 const *in); |
| 17 | 17 | ||
| 18 | __u32 half_md4_transform(__u32 buf[4], __u32 const in[8]); | ||
| 19 | |||
| 20 | #endif | 18 | #endif |
diff --git a/lib/Makefile b/lib/Makefile index bc4073a8cd08..19ea76149a37 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -31,7 +31,7 @@ lib-$(CONFIG_HAS_DMA) += dma-noop.o | |||
| 31 | lib-y += kobject.o klist.o | 31 | lib-y += kobject.o klist.o |
| 32 | obj-y += lockref.o | 32 | obj-y += lockref.o |
| 33 | 33 | ||
| 34 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 34 | obj-y += bcd.o div64.o sort.o parser.o debug_locks.o random32.o \ |
| 35 | bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ | 35 | bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ |
| 36 | gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \ | 36 | gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \ |
| 37 | bsearch.o find_bit.o llist.o memweight.o kfifo.o \ | 37 | bsearch.o find_bit.o llist.o memweight.o kfifo.o \ |
diff --git a/lib/halfmd4.c b/lib/halfmd4.c deleted file mode 100644 index 137e861d9690..000000000000 --- a/lib/halfmd4.c +++ /dev/null | |||
| @@ -1,67 +0,0 @@ | |||
| 1 | #include <linux/compiler.h> | ||
| 2 | #include <linux/export.h> | ||
| 3 | #include <linux/cryptohash.h> | ||
| 4 | #include <linux/bitops.h> | ||
| 5 | |||
| 6 | /* F, G and H are basic MD4 functions: selection, majority, parity */ | ||
| 7 | #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | ||
| 8 | #define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | ||
| 9 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||
| 10 | |||
| 11 | /* | ||
| 12 | * The generic round function. The application is so specific that | ||
| 13 | * we don't bother protecting all the arguments with parens, as is generally | ||
| 14 | * good macro practice, in favor of extra legibility. | ||
| 15 | * Rotation is separate from addition to prevent recomputation | ||
| 16 | */ | ||
| 17 | #define ROUND(f, a, b, c, d, x, s) \ | ||
| 18 | (a += f(b, c, d) + x, a = rol32(a, s)) | ||
| 19 | #define K1 0 | ||
| 20 | #define K2 013240474631UL | ||
| 21 | #define K3 015666365641UL | ||
| 22 | |||
| 23 | /* | ||
| 24 | * Basic cut-down MD4 transform. Returns only 32 bits of result. | ||
| 25 | */ | ||
| 26 | __u32 half_md4_transform(__u32 buf[4], __u32 const in[8]) | ||
| 27 | { | ||
| 28 | __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | ||
| 29 | |||
| 30 | /* Round 1 */ | ||
| 31 | ROUND(F, a, b, c, d, in[0] + K1, 3); | ||
| 32 | ROUND(F, d, a, b, c, in[1] + K1, 7); | ||
| 33 | ROUND(F, c, d, a, b, in[2] + K1, 11); | ||
| 34 | ROUND(F, b, c, d, a, in[3] + K1, 19); | ||
| 35 | ROUND(F, a, b, c, d, in[4] + K1, 3); | ||
| 36 | ROUND(F, d, a, b, c, in[5] + K1, 7); | ||
| 37 | ROUND(F, c, d, a, b, in[6] + K1, 11); | ||
| 38 | ROUND(F, b, c, d, a, in[7] + K1, 19); | ||
| 39 | |||
| 40 | /* Round 2 */ | ||
| 41 | ROUND(G, a, b, c, d, in[1] + K2, 3); | ||
| 42 | ROUND(G, d, a, b, c, in[3] + K2, 5); | ||
| 43 | ROUND(G, c, d, a, b, in[5] + K2, 9); | ||
| 44 | ROUND(G, b, c, d, a, in[7] + K2, 13); | ||
| 45 | ROUND(G, a, b, c, d, in[0] + K2, 3); | ||
| 46 | ROUND(G, d, a, b, c, in[2] + K2, 5); | ||
| 47 | ROUND(G, c, d, a, b, in[4] + K2, 9); | ||
| 48 | ROUND(G, b, c, d, a, in[6] + K2, 13); | ||
| 49 | |||
| 50 | /* Round 3 */ | ||
| 51 | ROUND(H, a, b, c, d, in[3] + K3, 3); | ||
| 52 | ROUND(H, d, a, b, c, in[7] + K3, 9); | ||
| 53 | ROUND(H, c, d, a, b, in[2] + K3, 11); | ||
| 54 | ROUND(H, b, c, d, a, in[6] + K3, 15); | ||
| 55 | ROUND(H, a, b, c, d, in[1] + K3, 3); | ||
| 56 | ROUND(H, d, a, b, c, in[5] + K3, 9); | ||
| 57 | ROUND(H, c, d, a, b, in[0] + K3, 11); | ||
| 58 | ROUND(H, b, c, d, a, in[4] + K3, 15); | ||
| 59 | |||
| 60 | buf[0] += a; | ||
| 61 | buf[1] += b; | ||
| 62 | buf[2] += c; | ||
| 63 | buf[3] += d; | ||
| 64 | |||
| 65 | return buf[1]; /* "most hashed" word */ | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(half_md4_transform); | ||
