* fscrypt API cleanups
@ 2025-11-18 6:21 Christoph Hellwig
0 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2025-11-18 6:21 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Hi all,
this series cleans up various fscrypt APIs to pass logical offsets in
and lengths in bytes, and on-disk sectors as 512-byte sector units,
like most of the VFS and block code.
Note that this is based on top of fscrypt/for-current and not
fscrypt/for-next to pick up "fscrypt: fix left shift underflow when
inode->i_blkbits > PAGE_SHIFT". There also is a minor conflict in
linux-next with the iomap tree tue to that tree changing and adjacent
line to one changes in this patch.
Eric only asked for the first two patches to be sent out, but I more of
my stack as I think it should be useful. Feel free to apply as many
as you think are suitable.
Diffstat:
fs/crypto/bio.c | 108 +++++++++++++++++++++++++-------------------
fs/crypto/fscrypt_private.h | 3 -
fs/crypto/inline_crypt.c | 34 ++++++-------
fs/crypto/keysetup.c | 2
fs/ext4/inode.c | 5 +-
fs/ext4/readpage.c | 7 +-
fs/f2fs/data.c | 7 ++
fs/f2fs/file.c | 4 +
fs/iomap/direct-io.c | 6 --
include/linux/fscrypt.h | 19 +++----
10 files changed, 105 insertions(+), 90 deletions(-)
^ permalink raw reply [flat|nested] 16+ messages in thread
* fscrypt API cleanups
@ 2026-02-18 6:14 Christoph Hellwig
2026-02-18 6:14 ` [PATCH 1/9] fscrypt: pass a byte offset to fscrypt_generate_dun Christoph Hellwig
` (8 more replies)
0 siblings, 9 replies; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Hi all,
this series cleans up various fscrypt APIs to pass logical offsets in
and lengths in bytes, and on-disk sectors as 512-byte sector units,
like most of the VFS and block code.
Diffstat:
fs/crypto/bio.c | 35 +++++++++++++++--------------------
fs/crypto/fscrypt_private.h | 3 ---
fs/crypto/inline_crypt.c | 34 ++++++++++++++++------------------
fs/crypto/keysetup.c | 2 --
fs/ext4/inode.c | 5 ++++-
fs/ext4/readpage.c | 7 ++++---
fs/f2fs/data.c | 7 +++++--
fs/f2fs/file.c | 4 +++-
fs/iomap/direct-io.c | 6 ++----
include/linux/fscrypt.h | 19 +++++++++----------
10 files changed, 58 insertions(+), 64 deletions(-)
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/9] fscrypt: pass a byte offset to fscrypt_generate_dun
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-18 6:14 ` [PATCH 2/9] fscrypt: pass a byte offset to fscrypt_mergeable_bio Christoph Hellwig
` (7 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Logical offsets into an inode are usually expresssed as bytes in the VFS.
Switch fscrypt_generate_dun to that convention and remove the
ci_data_units_per_block_bits member in struct fscrypt_inode_info that
was only used to cache the DUN shift based on the logical block size
granularity.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/fscrypt_private.h | 3 ---
fs/crypto/inline_crypt.c | 10 ++++------
fs/crypto/keysetup.c | 2 --
3 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 4e8e82a9ccf9..8d3c278a7591 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -278,9 +278,6 @@ struct fscrypt_inode_info {
*/
u8 ci_data_unit_bits;
- /* Cached value: log2 of number of data units per FS block */
- u8 ci_data_units_per_block_bits;
-
/* Hashed inode number. Only set for IV_INO_LBLK_32 */
u32 ci_hashed_ino;
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index ed6e926226b5..1773dd7ea7cf 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -268,14 +268,12 @@ bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci,
- u64 lblk_num,
- u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE])
+ loff_t pos, u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE])
{
- u64 index = lblk_num << ci->ci_data_units_per_block_bits;
union fscrypt_iv iv;
int i;
- fscrypt_generate_iv(&iv, index, ci);
+ fscrypt_generate_iv(&iv, pos >> ci->ci_data_unit_bits, ci);
BUILD_BUG_ON(FSCRYPT_MAX_IV_SIZE > BLK_CRYPTO_MAX_IV_SIZE);
memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE);
@@ -309,7 +307,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
return;
ci = fscrypt_get_inode_info_raw(inode);
- fscrypt_generate_dun(ci, first_lblk, dun);
+ fscrypt_generate_dun(ci, first_lblk << inode->i_blkbits, dun);
bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
}
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx);
@@ -401,7 +399,7 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
if (bc->bc_key != ci->ci_enc_key.blk_key)
return false;
- fscrypt_generate_dun(ci, next_lblk, next_dun);
+ fscrypt_generate_dun(ci, next_lblk << inode->i_blkbits, next_dun);
return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
}
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 40fa05688d3a..d83257e9945e 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -609,8 +609,6 @@ fscrypt_setup_encryption_info(struct inode *inode,
crypt_info->ci_data_unit_bits =
fscrypt_policy_du_bits(&crypt_info->ci_policy, inode);
- crypt_info->ci_data_units_per_block_bits =
- inode->i_blkbits - crypt_info->ci_data_unit_bits;
res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
if (res)
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/9] fscrypt: pass a byte offset to fscrypt_mergeable_bio
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
2026-02-18 6:14 ` [PATCH 1/9] fscrypt: pass a byte offset to fscrypt_generate_dun Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-21 19:44 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 3/9] fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx Christoph Hellwig
` (6 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Logical offsets into an inode are usually expresssed as bytes in the VFS.
Switch fscrypt_mergeable_bio to that convention.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 3 ++-
fs/crypto/inline_crypt.c | 9 +++++----
fs/ext4/readpage.c | 3 ++-
fs/f2fs/data.c | 3 ++-
include/linux/fscrypt.h | 4 ++--
5 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 6da683ea69dc..0a701d4a17ef 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -100,7 +100,8 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
len -= blocks_this_page;
lblk += blocks_this_page;
sector += (bytes_this_page >> SECTOR_SHIFT);
- if (!len || !fscrypt_mergeable_bio(bio, inode, lblk))
+ if (!len || !fscrypt_mergeable_bio(bio, inode,
+ (loff_t)lblk << blockbits))
break;
}
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index 1773dd7ea7cf..aba830e0827d 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -361,7 +361,7 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
* fscrypt_mergeable_bio() - test whether data can be added to a bio
* @bio: the bio being built up
* @inode: the inode for the next part of the I/O
- * @next_lblk: the next file logical block number in the I/O
+ * @pos: the next file logical offset (in bytes) in the I/O
*
* When building a bio which may contain data which should undergo inline
* encryption (or decryption) via fscrypt, filesystems should call this function
@@ -379,7 +379,7 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
* Return: true iff the I/O is mergeable
*/
bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
- u64 next_lblk)
+ loff_t pos)
{
const struct bio_crypt_ctx *bc = bio->bi_crypt_context;
const struct fscrypt_inode_info *ci;
@@ -399,7 +399,7 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
if (bc->bc_key != ci->ci_enc_key.blk_key)
return false;
- fscrypt_generate_dun(ci, next_lblk << inode->i_blkbits, next_dun);
+ fscrypt_generate_dun(ci, pos, next_dun);
return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
}
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
@@ -423,7 +423,8 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio,
if (!bh_get_inode_and_lblk_num(next_bh, &inode, &next_lblk))
return !bio->bi_crypt_context;
- return fscrypt_mergeable_bio(bio, inode, next_lblk);
+ return fscrypt_mergeable_bio(bio, inode,
+ (loff_t)next_lblk << inode->i_blkbits);
}
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh);
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 830f3b8a321f..ba7cfddd6038 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -342,7 +342,8 @@ static int ext4_mpage_readpages(struct inode *inode, struct fsverity_info *vi,
* BIO off first?
*/
if (bio && (last_block_in_bio != first_block - 1 ||
- !fscrypt_mergeable_bio(bio, inode, next_block))) {
+ !fscrypt_mergeable_bio(bio, inode,
+ (loff_t)next_block << blkbits))) {
submit_and_realloc:
blk_crypto_submit_bio(bio);
bio = NULL;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 338df7a2aea6..dca273fedfde 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -541,7 +541,8 @@ static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode,
if (fio && fio->encrypted_page)
return !bio_has_crypt_ctx(bio);
- return fscrypt_mergeable_bio(bio, inode, next_idx);
+ return fscrypt_mergeable_bio(bio, inode,
+ (loff_t)next_idx << inode->i_blkbits);
}
void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio,
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 516aba5b858b..5f2e02a61401 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -874,7 +874,7 @@ void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
gfp_t gfp_mask);
bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
- u64 next_lblk);
+ loff_t pos);
bool fscrypt_mergeable_bio_bh(struct bio *bio,
const struct buffer_head *next_bh);
@@ -901,7 +901,7 @@ static inline void fscrypt_set_bio_crypt_ctx_bh(
static inline bool fscrypt_mergeable_bio(struct bio *bio,
const struct inode *inode,
- u64 next_lblk)
+ loff_t pos)
{
return true;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/9] fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
2026-02-18 6:14 ` [PATCH 1/9] fscrypt: pass a byte offset to fscrypt_generate_dun Christoph Hellwig
2026-02-18 6:14 ` [PATCH 2/9] fscrypt: pass a byte offset to fscrypt_mergeable_bio Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-21 19:45 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 4/9] fscrypt: pass a byte offset to fscrypt_zeroout_range_inline_crypt Christoph Hellwig
` (5 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Logical offsets into an inode are usually expresssed as bytes in the VFS.
Switch fscrypt_set_bio_crypt_ctx to that convention.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 8 ++++----
fs/crypto/inline_crypt.c | 9 +++++----
fs/ext4/readpage.c | 4 ++--
fs/f2fs/data.c | 4 +++-
fs/iomap/direct-io.c | 6 ++----
include/linux/fscrypt.h | 7 +++----
6 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 0a701d4a17ef..e7fb2fdd9728 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -75,6 +75,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
{
const unsigned int blockbits = inode->i_blkbits;
const unsigned int blocks_per_page = 1 << (PAGE_SHIFT - blockbits);
+ loff_t pos = (loff_t)lblk << blockbits;
struct fscrypt_zero_done done = {
.pending = ATOMIC_INIT(1),
.done = COMPLETION_INITIALIZER_ONSTACK(done.done),
@@ -89,7 +90,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
bio->bi_iter.bi_sector = sector;
bio->bi_private = &done;
bio->bi_end_io = fscrypt_zeroout_range_end_io;
- fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOFS);
+ fscrypt_set_bio_crypt_ctx(bio, inode, pos, GFP_NOFS);
for (n = 0; n < BIO_MAX_VECS; n++) {
unsigned int blocks_this_page =
@@ -98,10 +99,9 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
__bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0);
len -= blocks_this_page;
- lblk += blocks_this_page;
+ pos += bytes_this_page;
sector += (bytes_this_page >> SECTOR_SHIFT);
- if (!len || !fscrypt_mergeable_bio(bio, inode,
- (loff_t)lblk << blockbits))
+ if (!len || !fscrypt_mergeable_bio(bio, inode, pos))
break;
}
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index aba830e0827d..c069958c4819 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -285,7 +285,7 @@ static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci,
* fscrypt_set_bio_crypt_ctx() - prepare a file contents bio for inline crypto
* @bio: a bio which will eventually be submitted to the file
* @inode: the file's inode
- * @first_lblk: the first file logical block number in the I/O
+ * @pos: the first file logical offset (in bytes) in the I/O
* @gfp_mask: memory allocation flags - these must be a waiting mask so that
* bio_crypt_set_ctx can't fail.
*
@@ -298,7 +298,7 @@ static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci,
* The encryption context will be freed automatically when the bio is freed.
*/
void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
- u64 first_lblk, gfp_t gfp_mask)
+ loff_t pos, gfp_t gfp_mask)
{
const struct fscrypt_inode_info *ci;
u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
@@ -307,7 +307,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
return;
ci = fscrypt_get_inode_info_raw(inode);
- fscrypt_generate_dun(ci, first_lblk << inode->i_blkbits, dun);
+ fscrypt_generate_dun(ci, pos, dun);
bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
}
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx);
@@ -353,7 +353,8 @@ void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
u64 first_lblk;
if (bh_get_inode_and_lblk_num(first_bh, &inode, &first_lblk))
- fscrypt_set_bio_crypt_ctx(bio, inode, first_lblk, gfp_mask);
+ fscrypt_set_bio_crypt_ctx(bio, inode,
+ first_lblk << inode->i_blkbits, gfp_mask);
}
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index ba7cfddd6038..fbfa4d830d9a 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -355,8 +355,8 @@ static int ext4_mpage_readpages(struct inode *inode, struct fsverity_info *vi,
*/
bio = bio_alloc(bdev, bio_max_segs(nr_pages),
REQ_OP_READ, GFP_KERNEL);
- fscrypt_set_bio_crypt_ctx(bio, inode, next_block,
- GFP_KERNEL);
+ fscrypt_set_bio_crypt_ctx(bio, inode,
+ (loff_t)next_block << blkbits, GFP_KERNEL);
ext4_set_bio_post_read_ctx(bio, inode, vi);
bio->bi_iter.bi_sector = first_block << (blkbits - 9);
bio->bi_end_io = mpage_end_io;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index dca273fedfde..07b4ed6bb0cc 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -527,7 +527,9 @@ static void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
* read/write raw data without encryption.
*/
if (!fio || !fio->encrypted_page)
- fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask);
+ fscrypt_set_bio_crypt_ctx(bio, inode,
+ (loff_t)first_idx << inode->i_blkbits,
+ gfp_mask);
}
static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode,
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 8c1fd7573aee..9cc24667d8f6 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -298,8 +298,7 @@ static int iomap_dio_zero(const struct iomap_iter *iter, struct iomap_dio *dio,
bio = iomap_dio_alloc_bio(iter, dio, nr_vecs,
REQ_OP_WRITE | REQ_SYNC | REQ_IDLE);
- fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits,
- GFP_KERNEL);
+ fscrypt_set_bio_crypt_ctx(bio, inode, pos, GFP_KERNEL);
bio->bi_iter.bi_sector = iomap_sector(&iter->iomap, pos);
bio->bi_private = dio;
bio->bi_end_io = iomap_dio_bio_end_io;
@@ -329,8 +328,7 @@ static ssize_t iomap_dio_bio_iter_one(struct iomap_iter *iter,
nr_vecs = bio_iov_vecs_to_alloc(dio->submit.iter, BIO_MAX_VECS);
bio = iomap_dio_alloc_bio(iter, dio, nr_vecs, op);
- fscrypt_set_bio_crypt_ctx(bio, iter->inode,
- pos >> iter->inode->i_blkbits, GFP_KERNEL);
+ fscrypt_set_bio_crypt_ctx(bio, iter->inode, pos, GFP_KERNEL);
bio->bi_iter.bi_sector = iomap_sector(&iter->iomap, pos);
bio->bi_write_hint = iter->inode->i_write_hint;
bio->bi_ioprio = dio->iocb->ki_ioprio;
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 5f2e02a61401..5b86d7d0d367 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -865,9 +865,8 @@ static inline void fscrypt_set_ops(struct super_block *sb,
bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode);
-void fscrypt_set_bio_crypt_ctx(struct bio *bio,
- const struct inode *inode, u64 first_lblk,
- gfp_t gfp_mask);
+void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
+ loff_t pos, gfp_t gfp_mask);
void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
const struct buffer_head *first_bh,
@@ -892,7 +891,7 @@ static inline bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
static inline void fscrypt_set_bio_crypt_ctx(struct bio *bio,
const struct inode *inode,
- u64 first_lblk, gfp_t gfp_mask) { }
+ loff_t pos, gfp_t gfp_mask) { }
static inline void fscrypt_set_bio_crypt_ctx_bh(
struct bio *bio,
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/9] fscrypt: pass a byte offset to fscrypt_zeroout_range_inline_crypt
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
` (2 preceding siblings ...)
2026-02-18 6:14 ` [PATCH 3/9] fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-18 6:14 ` [PATCH 5/9] fscrypt: pass a byte length " Christoph Hellwig
` (4 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Logical offsets into an inode are usually expresssed as bytes in the VFS.
Switch fscrypt_zeroout_range_inline_crypt to that convention.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index e7fb2fdd9728..7558b3e69701 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -70,12 +70,11 @@ static void fscrypt_zeroout_range_end_io(struct bio *bio)
}
static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
- pgoff_t lblk, sector_t sector,
+ loff_t pos, sector_t sector,
unsigned int len)
{
const unsigned int blockbits = inode->i_blkbits;
const unsigned int blocks_per_page = 1 << (PAGE_SHIFT - blockbits);
- loff_t pos = (loff_t)lblk << blockbits;
struct fscrypt_zero_done done = {
.pending = ATOMIC_INIT(1),
.done = COMPLETION_INITIALIZER_ONSTACK(done.done),
@@ -142,6 +141,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
const unsigned int du_per_page = 1U << du_per_page_bits;
u64 du_index = (u64)lblk << (inode->i_blkbits - du_bits);
u64 du_remaining = (u64)len << (inode->i_blkbits - du_bits);
+ loff_t pos = (loff_t)lblk << inode->i_blkbits;
sector_t sector = pblk << (inode->i_blkbits - SECTOR_SHIFT);
struct page *pages[16]; /* write up to 16 pages at a time */
unsigned int nr_pages;
@@ -154,7 +154,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
return 0;
if (fscrypt_inode_uses_inline_crypto(inode))
- return fscrypt_zeroout_range_inline_crypt(inode, lblk, sector,
+ return fscrypt_zeroout_range_inline_crypt(inode, pos, sector,
len);
BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_VECS);
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 5/9] fscrypt: pass a byte length to fscrypt_zeroout_range_inline_crypt
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
` (3 preceding siblings ...)
2026-02-18 6:14 ` [PATCH 4/9] fscrypt: pass a byte offset to fscrypt_zeroout_range_inline_crypt Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-18 6:14 ` [PATCH 6/9] fscrypt: return a byte offset from bh_get_inode_and_lblk_num Christoph Hellwig
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Range lengths are usually expressed as bytes in the VFS, switch
fscrypt_zeroout_range_inline_crypt to this convention.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 7558b3e69701..36025ce7a264 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -73,8 +73,6 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
loff_t pos, sector_t sector,
unsigned int len)
{
- const unsigned int blockbits = inode->i_blkbits;
- const unsigned int blocks_per_page = 1 << (PAGE_SHIFT - blockbits);
struct fscrypt_zero_done done = {
.pending = ATOMIC_INIT(1),
.done = COMPLETION_INITIALIZER_ONSTACK(done.done),
@@ -92,12 +90,10 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
fscrypt_set_bio_crypt_ctx(bio, inode, pos, GFP_NOFS);
for (n = 0; n < BIO_MAX_VECS; n++) {
- unsigned int blocks_this_page =
- min(len, blocks_per_page);
- unsigned int bytes_this_page = blocks_this_page << blockbits;
+ unsigned int bytes_this_page = min(len, PAGE_SIZE);
__bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0);
- len -= blocks_this_page;
+ len -= bytes_this_page;
pos += bytes_this_page;
sector += (bytes_this_page >> SECTOR_SHIFT);
if (!len || !fscrypt_mergeable_bio(bio, inode, pos))
@@ -155,7 +151,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
if (fscrypt_inode_uses_inline_crypto(inode))
return fscrypt_zeroout_range_inline_crypt(inode, pos, sector,
- len);
+ len << inode->i_blkbits);
BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_VECS);
nr_pages = min_t(u64, ARRAY_SIZE(pages),
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 6/9] fscrypt: return a byte offset from bh_get_inode_and_lblk_num
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
` (4 preceding siblings ...)
2026-02-18 6:14 ` [PATCH 5/9] fscrypt: pass a byte length " Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-21 19:47 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 7/9] fscrypt: pass a byte offset to fscrypt_zeroout_range Christoph Hellwig
` (2 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
All the callers now want a byte offset into the inode, so return
that from bh_get_inode_and_lblk_num.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/inline_crypt.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index c069958c4819..128268adf960 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -315,7 +315,7 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx);
/* Extract the inode and logical block number from a buffer_head. */
static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh,
const struct inode **inode_ret,
- u64 *lblk_num_ret)
+ loff_t *pos_ret)
{
struct folio *folio = bh->b_folio;
const struct address_space *mapping;
@@ -331,7 +331,7 @@ static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh,
inode = mapping->host;
*inode_ret = inode;
- *lblk_num_ret = (folio_pos(folio) + bh_offset(bh)) >> inode->i_blkbits;
+ *pos_ret = folio_pos(folio) + bh_offset(bh);
return true;
}
@@ -350,11 +350,10 @@ void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
gfp_t gfp_mask)
{
const struct inode *inode;
- u64 first_lblk;
+ loff_t pos;
- if (bh_get_inode_and_lblk_num(first_bh, &inode, &first_lblk))
- fscrypt_set_bio_crypt_ctx(bio, inode,
- first_lblk << inode->i_blkbits, gfp_mask);
+ if (bh_get_inode_and_lblk_num(first_bh, &inode, &pos))
+ fscrypt_set_bio_crypt_ctx(bio, inode, pos, gfp_mask);
}
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
@@ -419,13 +418,12 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio,
const struct buffer_head *next_bh)
{
const struct inode *inode;
- u64 next_lblk;
+ loff_t pos;
- if (!bh_get_inode_and_lblk_num(next_bh, &inode, &next_lblk))
+ if (!bh_get_inode_and_lblk_num(next_bh, &inode, &pos))
return !bio->bi_crypt_context;
- return fscrypt_mergeable_bio(bio, inode,
- (loff_t)next_lblk << inode->i_blkbits);
+ return fscrypt_mergeable_bio(bio, inode, pos);
}
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh);
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 7/9] fscrypt: pass a byte offset to fscrypt_zeroout_range
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
` (5 preceding siblings ...)
2026-02-18 6:14 ` [PATCH 6/9] fscrypt: return a byte offset from bh_get_inode_and_lblk_num Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-21 19:49 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 8/9] fscrypt: pass a byte length " Christoph Hellwig
2026-02-18 6:14 ` [PATCH 9/9] fscrypt: pass a real sector_t " Christoph Hellwig
8 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Logical offsets into an inode are usually expresssed as bytes in the VFS.
Switch fscrypt_zeroout_range to that convention.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 6 +++---
fs/ext4/inode.c | 3 ++-
fs/f2fs/file.c | 4 +++-
include/linux/fscrypt.h | 4 ++--
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 36025ce7a264..e41e605cf7e6 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -113,7 +113,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
/**
* fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file
* @inode: the file's inode
- * @lblk: the first file logical block to zero out
+ * @pos: the first file logical offset (in bytes) to zero out
* @pblk: the first filesystem physical block to zero out
* @len: number of blocks to zero out
*
@@ -127,7 +127,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
*
* Return: 0 on success; -errno on failure.
*/
-int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
+int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
sector_t pblk, unsigned int len)
{
const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
@@ -135,7 +135,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
const unsigned int du_size = 1U << du_bits;
const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
const unsigned int du_per_page = 1U << du_per_page_bits;
- u64 du_index = (u64)lblk << (inode->i_blkbits - du_bits);
+ u64 du_index = pos >> du_bits;
u64 du_remaining = (u64)len << (inode->i_blkbits - du_bits);
loff_t pos = (loff_t)lblk << inode->i_blkbits;
sector_t sector = pblk << (inode->i_blkbits - SECTOR_SHIFT);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 396dc3a5d16b..945613c95ffa 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -405,7 +405,8 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
KUNIT_STATIC_STUB_REDIRECT(ext4_issue_zeroout, inode, lblk, pblk, len);
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
- return fscrypt_zeroout_range(inode, lblk, pblk, len);
+ return fscrypt_zeroout_range(inode,
+ (loff_t)lblk << inode->i_blkbits, pblk, len);
ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS);
if (ret > 0)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index c8a2f17a8f11..239c2666ceb5 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4162,7 +4162,9 @@ static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode,
if (!ret && (flags & F2FS_TRIM_FILE_ZEROOUT)) {
if (IS_ENCRYPTED(inode))
- ret = fscrypt_zeroout_range(inode, off, block, len);
+ ret = fscrypt_zeroout_range(inode,
+ (loff_t)off << inode->i_blkbits, block,
+ len);
else
ret = blkdev_issue_zeroout(bdev, sector, nr_sects,
GFP_NOFS, 0);
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 5b86d7d0d367..065f909ebda2 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -450,7 +450,7 @@ u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
/* bio.c */
bool fscrypt_decrypt_bio(struct bio *bio);
-int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
+int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
sector_t pblk, unsigned int len);
/* hooks.c */
@@ -755,7 +755,7 @@ static inline bool fscrypt_decrypt_bio(struct bio *bio)
return true;
}
-static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
+static inline int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
sector_t pblk, unsigned int len)
{
return -EOPNOTSUPP;
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 8/9] fscrypt: pass a byte length to fscrypt_zeroout_range
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
` (6 preceding siblings ...)
2026-02-18 6:14 ` [PATCH 7/9] fscrypt: pass a byte offset to fscrypt_zeroout_range Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
2026-02-21 19:56 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 9/9] fscrypt: pass a real sector_t " Christoph Hellwig
8 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
Range lengths are usually expressed as bytes in the VFS, switch
fscrypt_zeroout_range to this convention.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 6 +++---
fs/ext4/inode.c | 3 ++-
fs/f2fs/file.c | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index e41e605cf7e6..cea931620c04 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -115,7 +115,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
* @inode: the file's inode
* @pos: the first file logical offset (in bytes) to zero out
* @pblk: the first filesystem physical block to zero out
- * @len: number of blocks to zero out
+ * @len: bytes to zero out
*
* Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write
* ciphertext blocks which decrypt to the all-zeroes block. The blocks must be
@@ -136,7 +136,7 @@ int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
const unsigned int du_per_page = 1U << du_per_page_bits;
u64 du_index = pos >> du_bits;
- u64 du_remaining = (u64)len << (inode->i_blkbits - du_bits);
+ u64 du_remaining = len >> du_bits;
loff_t pos = (loff_t)lblk << inode->i_blkbits;
sector_t sector = pblk << (inode->i_blkbits - SECTOR_SHIFT);
struct page *pages[16]; /* write up to 16 pages at a time */
@@ -151,7 +151,7 @@ int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
if (fscrypt_inode_uses_inline_crypto(inode))
return fscrypt_zeroout_range_inline_crypt(inode, pos, sector,
- len << inode->i_blkbits);
+ len);
BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_VECS);
nr_pages = min_t(u64, ARRAY_SIZE(pages),
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 945613c95ffa..675ef741cb30 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -406,7 +406,8 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
return fscrypt_zeroout_range(inode,
- (loff_t)lblk << inode->i_blkbits, pblk, len);
+ (loff_t)lblk << inode->i_blkbits, pblk,
+ len << inode->i_blkbits);
ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS);
if (ret > 0)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 239c2666ceb5..5b7013f7f6a1 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4164,7 +4164,7 @@ static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode,
if (IS_ENCRYPTED(inode))
ret = fscrypt_zeroout_range(inode,
(loff_t)off << inode->i_blkbits, block,
- len);
+ len << inode->i_blkbits);
else
ret = blkdev_issue_zeroout(bdev, sector, nr_sects,
GFP_NOFS, 0);
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 9/9] fscrypt: pass a real sector_t to fscrypt_zeroout_range
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
` (7 preceding siblings ...)
2026-02-18 6:14 ` [PATCH 8/9] fscrypt: pass a byte length " Christoph Hellwig
@ 2026-02-18 6:14 ` Christoph Hellwig
8 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2026-02-18 6:14 UTC (permalink / raw)
To: Eric Biggers
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
While the pblk argument to fscrypt_zeroout_range is declared as a
sector_t, it actually is interpreted as a logical block size unit, which
is highly unusual. Switch to passing the 512 byte units that sector_t is
defined for.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/crypto/bio.c | 6 ++----
fs/ext4/inode.c | 3 ++-
fs/f2fs/file.c | 2 +-
include/linux/fscrypt.h | 4 ++--
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index cea931620c04..45fe74aa8366 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -114,7 +114,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
* fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file
* @inode: the file's inode
* @pos: the first file logical offset (in bytes) to zero out
- * @pblk: the first filesystem physical block to zero out
+ * @sector: the first sector to zero out
* @len: bytes to zero out
*
* Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write
@@ -128,7 +128,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
* Return: 0 on success; -errno on failure.
*/
int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
- sector_t pblk, unsigned int len)
+ sector_t sector, unsigned int len)
{
const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
const unsigned int du_bits = ci->ci_data_unit_bits;
@@ -137,8 +137,6 @@ int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
const unsigned int du_per_page = 1U << du_per_page_bits;
u64 du_index = pos >> du_bits;
u64 du_remaining = len >> du_bits;
- loff_t pos = (loff_t)lblk << inode->i_blkbits;
- sector_t sector = pblk << (inode->i_blkbits - SECTOR_SHIFT);
struct page *pages[16]; /* write up to 16 pages at a time */
unsigned int nr_pages;
unsigned int i;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 675ef741cb30..d0028d6d3de1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -406,7 +406,8 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
return fscrypt_zeroout_range(inode,
- (loff_t)lblk << inode->i_blkbits, pblk,
+ (loff_t)lblk << inode->i_blkbits,
+ pblk << (inode->i_blkbits - SECTOR_SHIFT),
len << inode->i_blkbits);
ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 5b7013f7f6a1..ad435dea656a 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4163,7 +4163,7 @@ static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode,
if (!ret && (flags & F2FS_TRIM_FILE_ZEROOUT)) {
if (IS_ENCRYPTED(inode))
ret = fscrypt_zeroout_range(inode,
- (loff_t)off << inode->i_blkbits, block,
+ (loff_t)off << inode->i_blkbits, sector,
len << inode->i_blkbits);
else
ret = blkdev_issue_zeroout(bdev, sector, nr_sects,
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 065f909ebda2..11464bf0a241 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -451,7 +451,7 @@ u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
/* bio.c */
bool fscrypt_decrypt_bio(struct bio *bio);
int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
- sector_t pblk, unsigned int len);
+ sector_t sector, unsigned int len);
/* hooks.c */
int fscrypt_file_open(struct inode *inode, struct file *filp);
@@ -756,7 +756,7 @@ static inline bool fscrypt_decrypt_bio(struct bio *bio)
}
static inline int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
- sector_t pblk, unsigned int len)
+ sector_t sector, unsigned int len)
{
return -EOPNOTSUPP;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 2/9] fscrypt: pass a byte offset to fscrypt_mergeable_bio
2026-02-18 6:14 ` [PATCH 2/9] fscrypt: pass a byte offset to fscrypt_mergeable_bio Christoph Hellwig
@ 2026-02-21 19:44 ` Eric Biggers
0 siblings, 0 replies; 16+ messages in thread
From: Eric Biggers @ 2026-02-21 19:44 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
On Wed, Feb 18, 2026 at 07:14:40AM +0100, Christoph Hellwig wrote:
> Logical offsets into an inode are usually expresssed as bytes in the VFS.
expresssed => expressed, in all the commit messages
> /**
> * fscrypt_mergeable_bio_bh() - test whether data can be added to a bio
> * @bio: the bio being built up
> * @next_bh: the next buffer_head for which I/O will be submitted
> *
> * Same as fscrypt_mergeable_bio(), except this takes a buffer_head instead of
> * an inode and block number directly.
Above comment needs "block number" => "file position".
(Or "file offset" if you want. I think "file position" makes more
sense, given that the variable is called 'pos'. Either way, "block
number" is definitely wrong.)
- Eric
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/9] fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx
2026-02-18 6:14 ` [PATCH 3/9] fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx Christoph Hellwig
@ 2026-02-21 19:45 ` Eric Biggers
0 siblings, 0 replies; 16+ messages in thread
From: Eric Biggers @ 2026-02-21 19:45 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
On Wed, Feb 18, 2026 at 07:14:41AM +0100, Christoph Hellwig wrote:
> diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
[...]
> /**
> * fscrypt_set_bio_crypt_ctx_bh() - prepare a file contents bio for inline
> * crypto
> * @bio: a bio which will eventually be submitted to the file
> * @first_bh: the first buffer_head for which I/O will be submitted
> * @gfp_mask: memory allocation flags
> *
> * Same as fscrypt_set_bio_crypt_ctx(), except this takes a buffer_head instead
> * of an inode and block number directly.
Similarly, the above needs "block number" => "file position"
- Eric
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 6/9] fscrypt: return a byte offset from bh_get_inode_and_lblk_num
2026-02-18 6:14 ` [PATCH 6/9] fscrypt: return a byte offset from bh_get_inode_and_lblk_num Christoph Hellwig
@ 2026-02-21 19:47 ` Eric Biggers
0 siblings, 0 replies; 16+ messages in thread
From: Eric Biggers @ 2026-02-21 19:47 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
On Wed, Feb 18, 2026 at 07:14:44AM +0100, Christoph Hellwig wrote:
> @@ -331,7 +331,7 @@ static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh,
> inode = mapping->host;
>
> *inode_ret = inode;
> - *lblk_num_ret = (folio_pos(folio) + bh_offset(bh)) >> inode->i_blkbits;
> + *pos_ret = folio_pos(folio) + bh_offset(bh);
> return true;
> }
Rename bh_get_inode_and_lblk_num() to bh_get_inode_and_pos() to reflect
the new semantics.
(And s/logical block number/file position/ in the comment above it)
- Eric
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 7/9] fscrypt: pass a byte offset to fscrypt_zeroout_range
2026-02-18 6:14 ` [PATCH 7/9] fscrypt: pass a byte offset to fscrypt_zeroout_range Christoph Hellwig
@ 2026-02-21 19:49 ` Eric Biggers
0 siblings, 0 replies; 16+ messages in thread
From: Eric Biggers @ 2026-02-21 19:49 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
On Wed, Feb 18, 2026 at 07:14:45AM +0100, Christoph Hellwig wrote:
> Logical offsets into an inode are usually expresssed as bytes in the VFS.
> Switch fscrypt_zeroout_range to that convention.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/crypto/bio.c | 6 +++---
> fs/ext4/inode.c | 3 ++-
> fs/f2fs/file.c | 4 +++-
> include/linux/fscrypt.h | 4 ++--
> 4 files changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> index 36025ce7a264..e41e605cf7e6 100644
> --- a/fs/crypto/bio.c
> +++ b/fs/crypto/bio.c
> @@ -113,7 +113,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
> /**
> * fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file
> * @inode: the file's inode
> - * @lblk: the first file logical block to zero out
> + * @pos: the first file logical offset (in bytes) to zero out
> * @pblk: the first filesystem physical block to zero out
> * @len: number of blocks to zero out
> *
> @@ -127,7 +127,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
> *
> * Return: 0 on success; -errno on failure.
> */
> -int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
> +int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
> sector_t pblk, unsigned int len)
> {
> const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
> @@ -135,7 +135,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
> const unsigned int du_size = 1U << du_bits;
> const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
> const unsigned int du_per_page = 1U << du_per_page_bits;
> - u64 du_index = (u64)lblk << (inode->i_blkbits - du_bits);
> + u64 du_index = pos >> du_bits;
> u64 du_remaining = (u64)len << (inode->i_blkbits - du_bits);
> loff_t pos = (loff_t)lblk << inode->i_blkbits;
This is a bisection hazard because the 'pos' local variable isn't
removed until a later patch. It needs to be removed in this patch.
- Eric
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 8/9] fscrypt: pass a byte length to fscrypt_zeroout_range
2026-02-18 6:14 ` [PATCH 8/9] fscrypt: pass a byte length " Christoph Hellwig
@ 2026-02-21 19:56 ` Eric Biggers
0 siblings, 0 replies; 16+ messages in thread
From: Eric Biggers @ 2026-02-21 19:56 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Theodore Y. Ts'o, Jaegeuk Kim, Andreas Dilger, Chao Yu,
Christian Brauner, Darrick J. Wong, linux-fscrypt, linux-ext4,
linux-f2fs-devel, linux-fsdevel
On Wed, Feb 18, 2026 at 07:14:46AM +0100, Christoph Hellwig wrote:
> Range lengths are usually expressed as bytes in the VFS, switch
> fscrypt_zeroout_range to this convention.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/crypto/bio.c | 6 +++---
> fs/ext4/inode.c | 3 ++-
> fs/f2fs/file.c | 2 +-
> 3 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> index e41e605cf7e6..cea931620c04 100644
> --- a/fs/crypto/bio.c
> +++ b/fs/crypto/bio.c
> @@ -115,7 +115,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
> * @inode: the file's inode
> * @pos: the first file logical offset (in bytes) to zero out
> * @pblk: the first filesystem physical block to zero out
> - * @len: number of blocks to zero out
> + * @len: bytes to zero out
> *
> * Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write
> * ciphertext blocks which decrypt to the all-zeroes block. The blocks must be
> @@ -136,7 +136,7 @@ int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
This should be accompanied by a change in the type of 'len' to u64 or
loff_t, and similarly in fscrypt_zeroout_range_inline_crypt(). It's
unclear that the callers always pass lengths <= U32_MAX bytes,
especially the one in f2fs.
Also, the comment for fscrypt_zeroout_range() should be updated to
mention that pos and len need to be multiples of the filesystem block
size, given that it will no longer be implied by the units.
- Eric
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-02-21 19:56 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-18 6:14 fscrypt API cleanups Christoph Hellwig
2026-02-18 6:14 ` [PATCH 1/9] fscrypt: pass a byte offset to fscrypt_generate_dun Christoph Hellwig
2026-02-18 6:14 ` [PATCH 2/9] fscrypt: pass a byte offset to fscrypt_mergeable_bio Christoph Hellwig
2026-02-21 19:44 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 3/9] fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx Christoph Hellwig
2026-02-21 19:45 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 4/9] fscrypt: pass a byte offset to fscrypt_zeroout_range_inline_crypt Christoph Hellwig
2026-02-18 6:14 ` [PATCH 5/9] fscrypt: pass a byte length " Christoph Hellwig
2026-02-18 6:14 ` [PATCH 6/9] fscrypt: return a byte offset from bh_get_inode_and_lblk_num Christoph Hellwig
2026-02-21 19:47 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 7/9] fscrypt: pass a byte offset to fscrypt_zeroout_range Christoph Hellwig
2026-02-21 19:49 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 8/9] fscrypt: pass a byte length " Christoph Hellwig
2026-02-21 19:56 ` Eric Biggers
2026-02-18 6:14 ` [PATCH 9/9] fscrypt: pass a real sector_t " Christoph Hellwig
-- strict thread matches above, loose matches on Subject: below --
2025-11-18 6:21 fscrypt API cleanups Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox