ext4: do not perform data journaling when data is encrypted
Currently data journalling is incompatible with encryption: enabling both
at the same time has never been supported by design, and would result in
unpredictable behavior. However, users are not precluded from turning on
both features simultaneously. This change programmatically replaces data
journaling for encrypted regular files with ordered data journaling mode.
Background:
Journaling encrypted data has not been supported because it operates on
buffer heads of the page in the page cache. Namely, when the commit
happens, which could be up to five seconds after caching, the commit
thread uses the buffer heads attached to the page to copy the contents of
the page to the journal. With encryption, it would have been required to
keep the bounce buffer with ciphertext for up to the aforementioned five
seconds, since the page cache can only hold plaintext and could not be
used for journaling. Alternatively, it would be required to setup the
journal to initiate a callback at the commit time to perform deferred
encryption - in this case, not only would the data have to be written
twice, but it would also have to be encrypted twice. This level of
complexity was not justified for a mode that in practice is very rarely
used because of the overhead from the data journalling.
Solution:
If data=journaled has been set as a mount option for a filesystem, or if
journaling is enabled on a regular file, do not perform journaling if the
file is also encrypted, instead fall back to the data=ordered mode for the
file.
Rationale:
The intent is to allow seamless and proper filesystem operation when
journaling and encryption have both been enabled, and have these two
conflicting features gracefully resolved by the filesystem.
Fixes: 4461471107
Signed-off-by: Sergey Karamov <skaramov@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
This commit is contained in:
parent
578620f451
commit
73b92a2a5e
|
@ -414,17 +414,19 @@ static inline int ext4_inode_journal_mode(struct inode *inode)
|
|||
return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
|
||||
/* We do not support data journalling with delayed allocation */
|
||||
if (!S_ISREG(inode->i_mode) ||
|
||||
test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
|
||||
return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
|
||||
if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
|
||||
!test_opt(inode->i_sb, DELALLOC))
|
||||
test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
|
||||
(ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
|
||||
!test_opt(inode->i_sb, DELALLOC))) {
|
||||
/* We do not support data journalling for encrypted data */
|
||||
if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode))
|
||||
return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
|
||||
return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
|
||||
}
|
||||
if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
|
||||
return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
|
||||
if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
|
||||
return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
|
||||
else
|
||||
BUG();
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline int ext4_should_journal_data(struct inode *inode)
|
||||
|
|
|
@ -3530,6 +3530,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
"both data=journal and dax");
|
||||
goto failed_mount;
|
||||
}
|
||||
if (ext4_has_feature_encrypt(sb)) {
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"encrypted files will use data=ordered "
|
||||
"instead of data journaling mode");
|
||||
}
|
||||
if (test_opt(sb, DELALLOC))
|
||||
clear_opt(sb, DELALLOC);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue