|
|
|
@ -17,6 +17,7 @@ |
|
|
|
|
#include <linux/buffer_head.h> |
|
|
|
|
#include <linux/keyslot-manager.h> |
|
|
|
|
#include <linux/overflow.h> |
|
|
|
|
#include <linux/uio.h> |
|
|
|
|
|
|
|
|
|
#include "fscrypt_private.h" |
|
|
|
|
|
|
|
|
@ -429,3 +430,84 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio, |
|
|
|
|
return fscrypt_mergeable_bio(bio, inode, next_lblk); |
|
|
|
|
} |
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* fscrypt_dio_supported() - check whether a direct I/O request is unsupported |
|
|
|
|
* due to encryption constraints |
|
|
|
|
* @iocb: the file and position the I/O is targeting |
|
|
|
|
* @iter: the I/O data segment(s) |
|
|
|
|
* |
|
|
|
|
* Return: true if direct I/O is supported |
|
|
|
|
*/ |
|
|
|
|
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter) |
|
|
|
|
{ |
|
|
|
|
const struct inode *inode = file_inode(iocb->ki_filp); |
|
|
|
|
const struct fscrypt_info *ci = inode->i_crypt_info; |
|
|
|
|
const unsigned int blocksize = i_blocksize(inode); |
|
|
|
|
|
|
|
|
|
/* If the file is unencrypted, no veto from us. */ |
|
|
|
|
if (!fscrypt_needs_contents_encryption(inode)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
/* We only support direct I/O 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 I/O |
|
|
|
|
* must be block aligned -- not just disk sector aligned. |
|
|
|
|
*/ |
|
|
|
|
if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* With IV_INO_LBLK_32 and sub-page blocks, the DUN can wrap around in |
|
|
|
|
* the middle of a page. This isn't handled by the direct I/O code yet. |
|
|
|
|
*/ |
|
|
|
|
if (blocksize != PAGE_SIZE && |
|
|
|
|
(fscrypt_policy_flags(&ci->ci_policy) & |
|
|
|
|
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_dio_supported); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* fscrypt_limit_dio_pages() - limit I/O pages to avoid discontiguous DUNs |
|
|
|
|
* @inode: the file on which I/O is being done |
|
|
|
|
* @pos: the file position (in bytes) at which the I/O is being done |
|
|
|
|
* @nr_pages: the number of pages we want to submit starting at @pos |
|
|
|
|
* |
|
|
|
|
* For direct I/O: limit the number of pages that will be submitted in the bio |
|
|
|
|
* targeting @pos, in order to avoid crossing a data unit number (DUN) |
|
|
|
|
* discontinuity. This is only needed for certain IV generation methods. |
|
|
|
|
* |
|
|
|
|
* This assumes block_size == PAGE_SIZE; see fscrypt_dio_supported(). |
|
|
|
|
* |
|
|
|
|
* Return: the actual number of pages that can be submitted |
|
|
|
|
*/ |
|
|
|
|
int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages) |
|
|
|
|
{ |
|
|
|
|
const struct fscrypt_info *ci = inode->i_crypt_info; |
|
|
|
|
u32 dun; |
|
|
|
|
|
|
|
|
|
if (!fscrypt_inode_uses_inline_crypto(inode)) |
|
|
|
|
return nr_pages; |
|
|
|
|
|
|
|
|
|
if (nr_pages <= 1) |
|
|
|
|
return nr_pages; |
|
|
|
|
|
|
|
|
|
if (!(fscrypt_policy_flags(&ci->ci_policy) & |
|
|
|
|
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) |
|
|
|
|
return nr_pages; |
|
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE)) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
/* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */ |
|
|
|
|
|
|
|
|
|
dun = ci->ci_hashed_ino + (pos >> inode->i_blkbits); |
|
|
|
|
|
|
|
|
|
return min_t(u64, nr_pages, (u64)U32_MAX + 1 - dun); |
|
|
|
|
} |
|
|
|
|