1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * iomap callack functions
4 *
5 * Copyright (C) 2026 Namjae Jeon <linkinjeon@kernel.org>
6 */
7
8 #include <linux/iomap.h>
9 #include <linux/pagemap.h>
10
11 #include "exfat_raw.h"
12 #include "exfat_fs.h"
13 #include "iomap.h"
14
15 /*
16 * exfat_file_write_dio_end_io - Direct I/O write completion handler
17 *
18 * Updates i_size if the write extended the file. Called from the dio layer
19 * after I/O completion.
20 */
exfat_file_write_dio_end_io(struct kiocb * iocb,ssize_t size,int error,unsigned int flags)21 static int exfat_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
22 int error, unsigned int flags)
23 {
24 struct inode *inode = file_inode(iocb->ki_filp);
25
26 if (error)
27 return error;
28
29 if (size && i_size_read(inode) < iocb->ki_pos + size) {
30 i_size_write(inode, iocb->ki_pos + size);
31 mark_inode_dirty(inode);
32 }
33
34 return 0;
35 }
36
37 const struct iomap_dio_ops exfat_write_dio_ops = {
38 .end_io = exfat_file_write_dio_end_io,
39 };
40
__exfat_iomap_begin(struct inode * inode,loff_t offset,loff_t length,unsigned int flags,struct iomap * iomap,bool may_alloc)41 static int __exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
42 unsigned int flags, struct iomap *iomap, bool may_alloc)
43 {
44 struct super_block *sb = inode->i_sb;
45 struct exfat_sb_info *sbi = EXFAT_SB(sb);
46 struct exfat_inode_info *ei = EXFAT_I(inode);
47 unsigned int cluster, num_clusters;
48 loff_t cluster_offset, cluster_length;
49 int err;
50 bool balloc = false;
51
52 if (!may_alloc) {
53 /* Completely beyond EOF. Treat as hole */
54 if (i_size_read(inode) <= offset) {
55 iomap->type = IOMAP_HOLE;
56 iomap->addr = IOMAP_NULL_ADDR;
57 iomap->offset = offset;
58 iomap->length = length;
59 return 0;
60 }
61
62 /* Clamp length if the requested range goes beyond i_size */
63 if (offset + length > i_size_read(inode))
64 length = round_up(i_size_read(inode),
65 i_blocksize(inode)) - offset;
66 }
67
68 num_clusters = exfat_bytes_to_cluster_round_up(sbi,
69 offset + length) - exfat_bytes_to_cluster(sbi, offset);
70
71 mutex_lock(&sbi->s_lock);
72 iomap->bdev = inode->i_sb->s_bdev;
73 iomap->offset = offset;
74
75 err = exfat_map_cluster(inode, exfat_bytes_to_cluster(sbi, offset),
76 &cluster, &num_clusters, may_alloc, &balloc);
77 if (err)
78 goto out;
79
80 cluster_offset = exfat_cluster_offset(sbi, offset);
81 cluster_length = exfat_cluster_to_bytes(sbi, num_clusters);
82
83 iomap->length = min_t(loff_t, length, cluster_length - cluster_offset);
84 iomap->addr = exfat_cluster_to_phys_bytes(sbi, cluster) + cluster_offset;
85 iomap->type = IOMAP_MAPPED;
86 iomap->flags = IOMAP_F_MERGED;
87
88 if (may_alloc || flags & IOMAP_ZERO) {
89 if (balloc)
90 iomap->flags |= IOMAP_F_NEW;
91 else if (iomap->offset + iomap->length >= ei->valid_size) {
92 /*
93 * This is a write that starts at or extends beyond
94 * the current valid_size. The region between the old
95 * valid_size and the end of this write needs to be
96 * zeroed in the page cache to prevent stale data
97 * exposure (see IOMAP_F_ZERO_TAIL handling in
98 * __iomap_write_begin()).
99 */
100 iomap->flags |= IOMAP_F_ZERO_TAIL;
101 }
102 } else {
103 /*
104 * valid_size is tracked in byte granularity and
105 * marks the exact boundary between valid data and
106 * holes (or unwritten space).
107 *
108 * When IOMAP_REPORT is set (used by lseek(SEEK_HOLE)
109 * and SEEK_DATA), we return IOMAP_HOLE. This allows
110 * iomap_seek_hole_iter() to directly return the
111 * precise byte position.
112 *
113 * For normal I/O paths (without IOMAP_REPORT) we
114 * return IOMAP_UNWRITTEN so the write path can
115 * distinguish it from a real hole.
116 */
117 if (offset >= ei->valid_size) {
118 iomap->type = flags & IOMAP_REPORT ?
119 IOMAP_HOLE : IOMAP_UNWRITTEN;
120 } else if (offset + iomap->length > ei->valid_size) {
121 if (flags & IOMAP_REPORT) {
122 /*
123 * For SEEK_HOLE/SEEK_DATA, clip the length
124 * to the exact byte boundary (valid_size).
125 * This ensures the caller gets the precise
126 * hole position in byte units.
127 */
128 iomap->length = ei->valid_size - iomap->offset;
129 } else
130 iomap->length = round_up(ei->valid_size,
131 i_blocksize(inode)) -
132 iomap->offset;
133 }
134 }
135
136 iomap->flags |= IOMAP_F_MERGED;
137 out:
138 mutex_unlock(&sbi->s_lock);
139 return err;
140 }
141
exfat_iomap_begin(struct inode * inode,loff_t offset,loff_t length,unsigned int flags,struct iomap * iomap,struct iomap * srcmap)142 static int exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
143 unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
144 {
145 return __exfat_iomap_begin(inode, offset, length, flags, iomap, false);
146 }
147
exfat_write_iomap_begin(struct inode * inode,loff_t offset,loff_t length,unsigned int flags,struct iomap * iomap,struct iomap * srcmap)148 static int exfat_write_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
149 unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
150 {
151 return __exfat_iomap_begin(inode, offset, length, flags, iomap, true);
152 }
153
154 static DEFINE_IOMAP_ITER_NEXT(exfat_iomap_next, exfat_iomap_begin);
155
156 const struct iomap_ops exfat_iomap_ops = {
157 .iomap_next = exfat_iomap_next,
158 };
159
160 /*
161 * exfat_write_iomap_end - Update the state after write
162 *
163 * Extends ->valid_size to cover the newly written range.
164 * Marks the inode dirty if metadata was changed.
165 */
exfat_write_iomap_end(struct inode * inode,loff_t pos,loff_t length,ssize_t written,unsigned int flags,struct iomap * iomap)166 static int exfat_write_iomap_end(struct inode *inode, loff_t pos, loff_t length,
167 ssize_t written, unsigned int flags, struct iomap *iomap)
168 {
169 struct exfat_inode_info *ei = EXFAT_I(inode);
170 bool dirtied = false;
171 loff_t end;
172
173 if (!written)
174 return 0;
175
176 end = pos + written;
177
178 if (ei->valid_size < end) {
179 ei->valid_size = end;
180 if (ei->zeroed_size < end)
181 ei->zeroed_size = end;
182 dirtied = true;
183 }
184
185 if (dirtied || iomap->flags & IOMAP_F_SIZE_CHANGED)
186 mark_inode_dirty(inode);
187
188 return written;
189 }
190
191 static DEFINE_IOMAP_ITER_NEXT_END(exfat_write_iomap_next,
192 exfat_write_iomap_begin, exfat_write_iomap_end);
193
194 const struct iomap_ops exfat_write_iomap_ops = {
195 .iomap_next = exfat_write_iomap_next,
196 };
197
198 /*
199 * exfat_writeback_range - Map folio during writeback
200 *
201 * Called for each folio during writeback. If the folio falls outside the
202 * current iomap, remaps by calling read_iomap_begin.
203 */
exfat_writeback_range(struct iomap_writepage_ctx * wpc,struct folio * folio,u64 offset,unsigned int len,u64 end_pos)204 static ssize_t exfat_writeback_range(struct iomap_writepage_ctx *wpc,
205 struct folio *folio, u64 offset, unsigned int len, u64 end_pos)
206 {
207 if (offset < wpc->iomap.offset ||
208 offset >= wpc->iomap.offset + wpc->iomap.length) {
209 int error;
210
211 error = __exfat_iomap_begin(wpc->inode, offset, len,
212 0, &wpc->iomap, false);
213 if (error)
214 return error;
215 }
216
217 return iomap_add_to_ioend(wpc, folio, offset, end_pos, len);
218 }
219
220 const struct iomap_writeback_ops exfat_writeback_ops = {
221 .writeback_range = exfat_writeback_range,
222 .writeback_submit = iomap_ioend_writeback_submit,
223 };
224
225 /**
226 * exfat_iomap_read_end_io - iomap read bio completion handler for exFAT
227 * @bio: bio that has completed reading
228 *
229 * exfat_iomap_begin() rounds up MAPPED extents to the block boundary of
230 * valid_size. This ensures that any subsequent blocks are treated as
231 * IOMAP_UNWRITTEN, but it also causes the "straddle block" containing
232 * valid_size to be read from disk. The disk data beyond valid_size in
233 * this block is stale and must be zeroed to prevent data leakage.
234 */
exfat_iomap_read_end_io(struct bio * bio)235 static void exfat_iomap_read_end_io(struct bio *bio)
236 {
237 int error = blk_status_to_errno(bio->bi_status);
238 struct folio_iter iter;
239
240 bio_for_each_folio_all(iter, bio) {
241 struct folio *folio = iter.folio;
242 struct exfat_inode_info *ei = EXFAT_I(folio->mapping->host);
243 s64 valid_size;
244 loff_t pos = folio_pos(folio);
245
246 valid_size = ei->valid_size;
247 if (pos + iter.offset < valid_size &&
248 pos + iter.offset + iter.length > valid_size)
249 folio_zero_segment(folio, offset_in_folio(folio, valid_size),
250 iter.offset + iter.length);
251
252 iomap_finish_folio_read(folio, iter.offset, iter.length, error);
253 }
254 bio_put(bio);
255 }
256
exfat_iomap_bio_submit_read(const struct iomap_iter * iter,struct iomap_read_folio_ctx * ctx)257 static void exfat_iomap_bio_submit_read(const struct iomap_iter *iter,
258 struct iomap_read_folio_ctx *ctx)
259 {
260 iomap_bio_submit_read_endio(iter, ctx, exfat_iomap_read_end_io);
261 }
262
263 const struct iomap_read_ops exfat_iomap_bio_read_ops = {
264 .read_folio_range = iomap_bio_read_folio_range,
265 .submit_read = exfat_iomap_bio_submit_read,
266 };
267
exfat_iomap_swap_activate(struct swap_info_struct * sis,struct file * file,sector_t * span)268 int exfat_iomap_swap_activate(struct swap_info_struct *sis,
269 struct file *file, sector_t *span)
270 {
271 return iomap_swapfile_activate(sis, file, span, &exfat_iomap_ops);
272 }
273