mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
fscrypt: change fscrypt_dio_supported() to prepare for STATX_DIOALIGN
To prepare for STATX_DIOALIGN support, make two changes to fscrypt_dio_supported(). First, remove the filesystem-block-alignment check and make the filesystems handle it instead. It previously made sense to have it in fs/crypto/; however, to support STATX_DIOALIGN the alignment restriction would have to be returned to filesystems. It ends up being simpler if filesystems handle this part themselves, especially for f2fs which only allows fs-block-aligned DIO in the first place. Second, make fscrypt_dio_supported() work on inodes whose encryption key hasn't been set up yet, by making it set up the key if needed. This is required for statx(), since statx() doesn't require a file descriptor. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Eric Biggers <ebiggers@google.com> Link: https://lore.kernel.org/r/20220827065851.135710-4-ebiggers@kernel.org
This commit is contained in:
parent
2d985f8c6b
commit
53dd3f802a
@ -401,46 +401,45 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
|||||||
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh);
|
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fscrypt_dio_supported() - check whether a DIO (direct I/O) request is
|
* fscrypt_dio_supported() - check whether DIO (direct I/O) is supported on an
|
||||||
* supported as far as encryption is concerned
|
* inode, as far as encryption is concerned
|
||||||
* @iocb: the file and position the I/O is targeting
|
* @inode: the inode in question
|
||||||
* @iter: the I/O data segment(s)
|
|
||||||
*
|
*
|
||||||
* Return: %true if there are no encryption constraints that prevent DIO from
|
* Return: %true if there are no encryption constraints that prevent DIO from
|
||||||
* being supported; %false if DIO is unsupported. (Note that in the
|
* being supported; %false if DIO is unsupported. (Note that in the
|
||||||
* %true case, the filesystem might have other, non-encryption-related
|
* %true case, the filesystem might have other, non-encryption-related
|
||||||
* constraints that prevent DIO from actually being supported.)
|
* constraints that prevent DIO from actually being supported. Also, on
|
||||||
|
* encrypted files the filesystem is still responsible for only allowing
|
||||||
|
* DIO when requests are filesystem-block-aligned.)
|
||||||
*/
|
*/
|
||||||
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter)
|
bool fscrypt_dio_supported(struct inode *inode)
|
||||||
{
|
{
|
||||||
const struct inode *inode = file_inode(iocb->ki_filp);
|
int err;
|
||||||
const unsigned int blocksize = i_blocksize(inode);
|
|
||||||
|
|
||||||
/* If the file is unencrypted, no veto from us. */
|
/* If the file is unencrypted, no veto from us. */
|
||||||
if (!fscrypt_needs_contents_encryption(inode))
|
if (!fscrypt_needs_contents_encryption(inode))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* We only support DIO with inline crypto, not fs-layer crypto. */
|
|
||||||
if (!fscrypt_inode_uses_inline_crypto(inode))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since the granularity of encryption is filesystem blocks, the file
|
* We only support DIO with inline crypto, not fs-layer crypto.
|
||||||
* position and total I/O length must be aligned to the filesystem block
|
|
||||||
* size -- not just to the block device's logical block size as is
|
|
||||||
* traditionally the case for DIO on many filesystems.
|
|
||||||
*
|
*
|
||||||
* We require that the user-provided memory buffers be filesystem block
|
* To determine whether the inode is using inline crypto, we have to set
|
||||||
* aligned too. It is simpler to have a single alignment value required
|
* up the key if it wasn't already done. This is because in the current
|
||||||
* for all properties of the I/O, as is normally the case for DIO.
|
* design of fscrypt, the decision of whether to use inline crypto or
|
||||||
* Also, allowing less aligned buffers would imply that data units could
|
* not isn't made until the inode's encryption key is being set up. In
|
||||||
* cross bvecs, which would greatly complicate the I/O stack, which
|
* the DIO read/write case, the key will always be set up already, since
|
||||||
* assumes that bios can be split at any bvec boundary.
|
* the file will be open. But in the case of statx(), the key might not
|
||||||
|
* be set up yet, as the file might not have been opened yet.
|
||||||
*/
|
*/
|
||||||
if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize))
|
err = fscrypt_require_key(inode);
|
||||||
|
if (err) {
|
||||||
|
/*
|
||||||
|
* Key unavailable or couldn't be set up. This edge case isn't
|
||||||
|
* worth worrying about; just report that DIO is unsupported.
|
||||||
|
*/
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return fscrypt_inode_uses_inline_crypto(inode);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
|
EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
|
||||||
|
|
||||||
|
@ -40,8 +40,13 @@ static bool ext4_dio_supported(struct kiocb *iocb, struct iov_iter *iter)
|
|||||||
{
|
{
|
||||||
struct inode *inode = file_inode(iocb->ki_filp);
|
struct inode *inode = file_inode(iocb->ki_filp);
|
||||||
|
|
||||||
if (!fscrypt_dio_supported(iocb, iter))
|
if (IS_ENCRYPTED(inode)) {
|
||||||
return false;
|
if (!fscrypt_dio_supported(inode))
|
||||||
|
return false;
|
||||||
|
if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter),
|
||||||
|
i_blocksize(inode)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (fsverity_active(inode))
|
if (fsverity_active(inode))
|
||||||
return false;
|
return false;
|
||||||
if (ext4_should_journal_data(inode))
|
if (ext4_should_journal_data(inode))
|
||||||
|
@ -4498,7 +4498,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode,
|
|||||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
int rw = iov_iter_rw(iter);
|
int rw = iov_iter_rw(iter);
|
||||||
|
|
||||||
if (!fscrypt_dio_supported(iocb, iter))
|
if (!fscrypt_dio_supported(inode))
|
||||||
return true;
|
return true;
|
||||||
if (fsverity_active(inode))
|
if (fsverity_active(inode))
|
||||||
return true;
|
return true;
|
||||||
|
@ -768,7 +768,7 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
|
|||||||
bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
||||||
const struct buffer_head *next_bh);
|
const struct buffer_head *next_bh);
|
||||||
|
|
||||||
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter);
|
bool fscrypt_dio_supported(struct inode *inode);
|
||||||
|
|
||||||
u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks);
|
u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks);
|
||||||
|
|
||||||
@ -801,11 +801,8 @@ static inline bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool fscrypt_dio_supported(struct kiocb *iocb,
|
static inline bool fscrypt_dio_supported(struct inode *inode)
|
||||||
struct iov_iter *iter)
|
|
||||||
{
|
{
|
||||||
const struct inode *inode = file_inode(iocb->ki_filp);
|
|
||||||
|
|
||||||
return !fscrypt_needs_contents_encryption(inode);
|
return !fscrypt_needs_contents_encryption(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user