Commit f41683a2 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull ext4 fixes from Ted Ts'o:
 "Ext4 bug fixes for v4.4, including fixes for post-2038 time encodings,
  some endian conversion problems with ext4 encryption, potential memory
  leaks after truncate in data=journal mode, and an ocfs2 regression
  caused by a jbd2 performance improvement"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  jbd2: fix null committed data return in undo_access
  ext4: add "static" to ext4_seq_##name##_fops struct
  ext4: fix an endianness bug in ext4_encrypted_follow_link()
  ext4: fix an endianness bug in ext4_encrypted_zeroout()
  jbd2: Fix unreclaimed pages after truncate in data=journal mode
  ext4: Fix handling of extended tv_sec
parents 527e9316 087ffd4e
...@@ -389,7 +389,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) ...@@ -389,7 +389,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
struct ext4_crypto_ctx *ctx; struct ext4_crypto_ctx *ctx;
struct page *ciphertext_page = NULL; struct page *ciphertext_page = NULL;
struct bio *bio; struct bio *bio;
ext4_lblk_t lblk = ex->ee_block; ext4_lblk_t lblk = le32_to_cpu(ex->ee_block);
ext4_fsblk_t pblk = ext4_ext_pblock(ex); ext4_fsblk_t pblk = ext4_ext_pblock(ex);
unsigned int len = ext4_ext_get_actual_len(ex); unsigned int len = ext4_ext_get_actual_len(ex);
int ret, err = 0; int ret, err = 0;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/seqlock.h> #include <linux/seqlock.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/version.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/blockgroup_lock.h> #include <linux/blockgroup_lock.h>
#include <linux/percpu_counter.h> #include <linux/percpu_counter.h>
...@@ -727,18 +728,54 @@ struct move_extent { ...@@ -727,18 +728,54 @@ struct move_extent {
<= (EXT4_GOOD_OLD_INODE_SIZE + \ <= (EXT4_GOOD_OLD_INODE_SIZE + \
(einode)->i_extra_isize)) \ (einode)->i_extra_isize)) \
/*
* We use an encoding that preserves the times for extra epoch "00":
*
* extra msb of adjust for signed
* epoch 32-bit 32-bit tv_sec to
* bits time decoded 64-bit tv_sec 64-bit tv_sec valid time range
* 0 0 1 -0x80000000..-0x00000001 0x000000000 1901-12-13..1969-12-31
* 0 0 0 0x000000000..0x07fffffff 0x000000000 1970-01-01..2038-01-19
* 0 1 1 0x080000000..0x0ffffffff 0x100000000 2038-01-19..2106-02-07
* 0 1 0 0x100000000..0x17fffffff 0x100000000 2106-02-07..2174-02-25
* 1 0 1 0x180000000..0x1ffffffff 0x200000000 2174-02-25..2242-03-16
* 1 0 0 0x200000000..0x27fffffff 0x200000000 2242-03-16..2310-04-04
* 1 1 1 0x280000000..0x2ffffffff 0x300000000 2310-04-04..2378-04-22
* 1 1 0 0x300000000..0x37fffffff 0x300000000 2378-04-22..2446-05-10
*
* Note that previous versions of the kernel on 64-bit systems would
* incorrectly use extra epoch bits 1,1 for dates between 1901 and
* 1970. e2fsck will correct this, assuming that it is run on the
* affected filesystem before 2242.
*/
static inline __le32 ext4_encode_extra_time(struct timespec *time) static inline __le32 ext4_encode_extra_time(struct timespec *time)
{ {
return cpu_to_le32((sizeof(time->tv_sec) > 4 ? u32 extra = sizeof(time->tv_sec) > 4 ?
(time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) | ((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0;
((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK)); return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
} }
static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra) static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
{ {
if (sizeof(time->tv_sec) > 4) if (unlikely(sizeof(time->tv_sec) > 4 &&
time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) {
<< 32; #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
/* Handle legacy encoding of pre-1970 dates with epoch
* bits 1,1. We assume that by kernel version 4.20,
* everyone will have run fsck over the affected
* filesystems to correct the problem. (This
* backwards compatibility may be removed before this
* time, at the discretion of the ext4 developers.)
*/
u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
extra_bits = 0;
time->tv_sec += extra_bits << 32;
#else
time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
#endif
}
time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
} }
......
...@@ -52,7 +52,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook ...@@ -52,7 +52,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
/* Symlink is encrypted */ /* Symlink is encrypted */
sd = (struct ext4_encrypted_symlink_data *)caddr; sd = (struct ext4_encrypted_symlink_data *)caddr;
cstr.name = sd->encrypted_path; cstr.name = sd->encrypted_path;
cstr.len = le32_to_cpu(sd->len); cstr.len = le16_to_cpu(sd->len);
if ((cstr.len + if ((cstr.len +
sizeof(struct ext4_encrypted_symlink_data) - 1) > sizeof(struct ext4_encrypted_symlink_data) - 1) >
max_size) { max_size) {
......
...@@ -358,7 +358,7 @@ static int name##_open(struct inode *inode, struct file *file) \ ...@@ -358,7 +358,7 @@ static int name##_open(struct inode *inode, struct file *file) \
return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \ return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \
} \ } \
\ \
const struct file_operations ext4_seq_##name##_fops = { \ static const struct file_operations ext4_seq_##name##_fops = { \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.open = name##_open, \ .open = name##_open, \
.read = seq_read, \ .read = seq_read, \
......
...@@ -1009,7 +1009,8 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -1009,7 +1009,8 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
} }
/* Fast check whether buffer is already attached to the required transaction */ /* Fast check whether buffer is already attached to the required transaction */
static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh) static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh,
bool undo)
{ {
struct journal_head *jh; struct journal_head *jh;
bool ret = false; bool ret = false;
...@@ -1036,6 +1037,9 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh) ...@@ -1036,6 +1037,9 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh)
jh = READ_ONCE(bh->b_private); jh = READ_ONCE(bh->b_private);
if (!jh) if (!jh)
goto out; goto out;
/* For undo access buffer must have data copied */
if (undo && !jh->b_committed_data)
goto out;
if (jh->b_transaction != handle->h_transaction && if (jh->b_transaction != handle->h_transaction &&
jh->b_next_transaction != handle->h_transaction) jh->b_next_transaction != handle->h_transaction)
goto out; goto out;
...@@ -1073,7 +1077,7 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh) ...@@ -1073,7 +1077,7 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
struct journal_head *jh; struct journal_head *jh;
int rc; int rc;
if (jbd2_write_access_granted(handle, bh)) if (jbd2_write_access_granted(handle, bh, false))
return 0; return 0;
jh = jbd2_journal_add_journal_head(bh); jh = jbd2_journal_add_journal_head(bh);
...@@ -1210,7 +1214,7 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh) ...@@ -1210,7 +1214,7 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
char *committed_data = NULL; char *committed_data = NULL;
JBUFFER_TRACE(jh, "entry"); JBUFFER_TRACE(jh, "entry");
if (jbd2_write_access_granted(handle, bh)) if (jbd2_write_access_granted(handle, bh, true))
return 0; return 0;
jh = jbd2_journal_add_journal_head(bh); jh = jbd2_journal_add_journal_head(bh);
...@@ -2152,6 +2156,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, ...@@ -2152,6 +2156,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
if (!buffer_dirty(bh)) { if (!buffer_dirty(bh)) {
/* bdflush has written it. We can drop it now */ /* bdflush has written it. We can drop it now */
__jbd2_journal_remove_checkpoint(jh);
goto zap_buffer; goto zap_buffer;
} }
...@@ -2181,6 +2186,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, ...@@ -2181,6 +2186,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
/* The orphan record's transaction has /* The orphan record's transaction has
* committed. We can cleanse this buffer */ * committed. We can cleanse this buffer */
clear_buffer_jbddirty(bh); clear_buffer_jbddirty(bh);
__jbd2_journal_remove_checkpoint(jh);
goto zap_buffer; goto zap_buffer;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment