1 4008e2a0SDamien Le Moal // SPDX-License-Identifier: GPL-2.0
2 4008e2a0SDamien Le Moal /*
3 4008e2a0SDamien Le Moal * Simple file system for zoned block devices exposing zones as files.
4 4008e2a0SDamien Le Moal *
5 4008e2a0SDamien Le Moal * Copyright (C) 2022 Western Digital Corporation or its affiliates.
6 4008e2a0SDamien Le Moal */
7 4008e2a0SDamien Le Moal #include <linux/module.h>
8 4008e2a0SDamien Le Moal #include <linux/pagemap.h>
9 4008e2a0SDamien Le Moal #include <linux/iomap.h>
10 4008e2a0SDamien Le Moal #include <linux/init.h>
11 4008e2a0SDamien Le Moal #include <linux/slab.h>
12 4008e2a0SDamien Le Moal #include <linux/blkdev.h>
13 4008e2a0SDamien Le Moal #include <linux/statfs.h>
14 4008e2a0SDamien Le Moal #include <linux/writeback.h>
15 4008e2a0SDamien Le Moal #include <linux/quotaops.h>
16 4008e2a0SDamien Le Moal #include <linux/seq_file.h>
17 4008e2a0SDamien Le Moal #include <linux/parser.h>
18 4008e2a0SDamien Le Moal #include <linux/uio.h>
19 4008e2a0SDamien Le Moal #include <linux/mman.h>
20 4008e2a0SDamien Le Moal #include <linux/sched/mm.h>
21 4008e2a0SDamien Le Moal #include <linux/task_io_accounting_ops.h>
22 4008e2a0SDamien Le Moal
23 4008e2a0SDamien Le Moal #include "zonefs.h"
24 4008e2a0SDamien Le Moal
25 4008e2a0SDamien Le Moal #include "trace.h"
26 4008e2a0SDamien Le Moal
zonefs_read_iomap_begin(struct inode * inode,loff_t offset,loff_t length,unsigned int flags,struct iomap * iomap,struct iomap * srcmap)27 4008e2a0SDamien Le Moal static int zonefs_read_iomap_begin(struct inode *inode, loff_t offset,
28 4008e2a0SDamien Le Moal loff_t length, unsigned int flags,
29 4008e2a0SDamien Le Moal struct iomap *iomap, struct iomap *srcmap)
30 4008e2a0SDamien Le Moal {
31 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
32 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
33 4008e2a0SDamien Le Moal struct super_block *sb = inode->i_sb;
34 4008e2a0SDamien Le Moal loff_t isize;
35 4008e2a0SDamien Le Moal
36 4008e2a0SDamien Le Moal /*
37 4008e2a0SDamien Le Moal * All blocks are always mapped below EOF. If reading past EOF,
38 4008e2a0SDamien Le Moal * act as if there is a hole up to the file maximum size.
39 4008e2a0SDamien Le Moal */
40 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
41 4008e2a0SDamien Le Moal iomap->bdev = inode->i_sb->s_bdev;
42 4008e2a0SDamien Le Moal iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize);
43 4008e2a0SDamien Le Moal isize = i_size_read(inode);
44 4008e2a0SDamien Le Moal if (iomap->offset >= isize) {
45 4008e2a0SDamien Le Moal iomap->type = IOMAP_HOLE;
46 4008e2a0SDamien Le Moal iomap->addr = IOMAP_NULL_ADDR;
47 4008e2a0SDamien Le Moal iomap->length = length;
48 4008e2a0SDamien Le Moal } else {
49 4008e2a0SDamien Le Moal iomap->type = IOMAP_MAPPED;
50 aa7f243fSDamien Le Moal iomap->addr = (z->z_sector << SECTOR_SHIFT) + iomap->offset;
51 4008e2a0SDamien Le Moal iomap->length = isize - iomap->offset;
52 4008e2a0SDamien Le Moal }
53 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
54 4008e2a0SDamien Le Moal
55 4008e2a0SDamien Le Moal trace_zonefs_iomap_begin(inode, iomap);
56 4008e2a0SDamien Le Moal
57 4008e2a0SDamien Le Moal return 0;
58 4008e2a0SDamien Le Moal }
59 4008e2a0SDamien Le Moal
60 4008e2a0SDamien Le Moal static const struct iomap_ops zonefs_read_iomap_ops = {
61 4008e2a0SDamien Le Moal .iomap_begin = zonefs_read_iomap_begin,
62 4008e2a0SDamien Le Moal };
63 4008e2a0SDamien Le Moal
zonefs_write_iomap_begin(struct inode * inode,loff_t offset,loff_t length,unsigned int flags,struct iomap * iomap,struct iomap * srcmap)64 4008e2a0SDamien Le Moal static int zonefs_write_iomap_begin(struct inode *inode, loff_t offset,
65 4008e2a0SDamien Le Moal loff_t length, unsigned int flags,
66 4008e2a0SDamien Le Moal struct iomap *iomap, struct iomap *srcmap)
67 4008e2a0SDamien Le Moal {
68 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
69 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
70 4008e2a0SDamien Le Moal struct super_block *sb = inode->i_sb;
71 4008e2a0SDamien Le Moal loff_t isize;
72 4008e2a0SDamien Le Moal
73 4008e2a0SDamien Le Moal /* All write I/Os should always be within the file maximum size */
74 aa7f243fSDamien Le Moal if (WARN_ON_ONCE(offset + length > z->z_capacity))
75 4008e2a0SDamien Le Moal return -EIO;
76 4008e2a0SDamien Le Moal
77 4008e2a0SDamien Le Moal /*
78 4008e2a0SDamien Le Moal * Sequential zones can only accept direct writes. This is already
79 4008e2a0SDamien Le Moal * checked when writes are issued, so warn if we see a page writeback
80 4008e2a0SDamien Le Moal * operation.
81 4008e2a0SDamien Le Moal */
82 aa7f243fSDamien Le Moal if (WARN_ON_ONCE(zonefs_zone_is_seq(z) && !(flags & IOMAP_DIRECT)))
83 4008e2a0SDamien Le Moal return -EIO;
84 4008e2a0SDamien Le Moal
85 4008e2a0SDamien Le Moal /*
86 4008e2a0SDamien Le Moal * For conventional zones, all blocks are always mapped. For sequential
87 4008e2a0SDamien Le Moal * zones, all blocks after always mapped below the inode size (zone
88 4008e2a0SDamien Le Moal * write pointer) and unwriten beyond.
89 4008e2a0SDamien Le Moal */
90 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
91 4008e2a0SDamien Le Moal iomap->bdev = inode->i_sb->s_bdev;
92 4008e2a0SDamien Le Moal iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize);
93 aa7f243fSDamien Le Moal iomap->addr = (z->z_sector << SECTOR_SHIFT) + iomap->offset;
94 4008e2a0SDamien Le Moal isize = i_size_read(inode);
95 4008e2a0SDamien Le Moal if (iomap->offset >= isize) {
96 4008e2a0SDamien Le Moal iomap->type = IOMAP_UNWRITTEN;
97 aa7f243fSDamien Le Moal iomap->length = z->z_capacity - iomap->offset;
98 4008e2a0SDamien Le Moal } else {
99 4008e2a0SDamien Le Moal iomap->type = IOMAP_MAPPED;
100 4008e2a0SDamien Le Moal iomap->length = isize - iomap->offset;
101 4008e2a0SDamien Le Moal }
102 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
103 4008e2a0SDamien Le Moal
104 4008e2a0SDamien Le Moal trace_zonefs_iomap_begin(inode, iomap);
105 4008e2a0SDamien Le Moal
106 4008e2a0SDamien Le Moal return 0;
107 4008e2a0SDamien Le Moal }
108 4008e2a0SDamien Le Moal
109 4008e2a0SDamien Le Moal static const struct iomap_ops zonefs_write_iomap_ops = {
110 4008e2a0SDamien Le Moal .iomap_begin = zonefs_write_iomap_begin,
111 4008e2a0SDamien Le Moal };
112 4008e2a0SDamien Le Moal
zonefs_read_folio(struct file * unused,struct folio * folio)113 4008e2a0SDamien Le Moal static int zonefs_read_folio(struct file *unused, struct folio *folio)
114 4008e2a0SDamien Le Moal {
115 4008e2a0SDamien Le Moal return iomap_read_folio(folio, &zonefs_read_iomap_ops);
116 4008e2a0SDamien Le Moal }
117 4008e2a0SDamien Le Moal
zonefs_readahead(struct readahead_control * rac)118 4008e2a0SDamien Le Moal static void zonefs_readahead(struct readahead_control *rac)
119 4008e2a0SDamien Le Moal {
120 4008e2a0SDamien Le Moal iomap_readahead(rac, &zonefs_read_iomap_ops);
121 4008e2a0SDamien Le Moal }
122 4008e2a0SDamien Le Moal
123 4008e2a0SDamien Le Moal /*
124 4008e2a0SDamien Le Moal * Map blocks for page writeback. This is used only on conventional zone files,
125 4008e2a0SDamien Le Moal * which implies that the page range can only be within the fixed inode size.
126 4008e2a0SDamien Le Moal */
zonefs_write_map_blocks(struct iomap_writepage_ctx * wpc,struct inode * inode,loff_t offset)127 4008e2a0SDamien Le Moal static int zonefs_write_map_blocks(struct iomap_writepage_ctx *wpc,
128 4008e2a0SDamien Le Moal struct inode *inode, loff_t offset)
129 4008e2a0SDamien Le Moal {
130 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
131 4008e2a0SDamien Le Moal
132 aa7f243fSDamien Le Moal if (WARN_ON_ONCE(zonefs_zone_is_seq(z)))
133 4008e2a0SDamien Le Moal return -EIO;
134 4008e2a0SDamien Le Moal if (WARN_ON_ONCE(offset >= i_size_read(inode)))
135 4008e2a0SDamien Le Moal return -EIO;
136 4008e2a0SDamien Le Moal
137 4008e2a0SDamien Le Moal /* If the mapping is already OK, nothing needs to be done */
138 4008e2a0SDamien Le Moal if (offset >= wpc->iomap.offset &&
139 4008e2a0SDamien Le Moal offset < wpc->iomap.offset + wpc->iomap.length)
140 4008e2a0SDamien Le Moal return 0;
141 4008e2a0SDamien Le Moal
142 aa7f243fSDamien Le Moal return zonefs_write_iomap_begin(inode, offset,
143 aa7f243fSDamien Le Moal z->z_capacity - offset,
144 4008e2a0SDamien Le Moal IOMAP_WRITE, &wpc->iomap, NULL);
145 4008e2a0SDamien Le Moal }
146 4008e2a0SDamien Le Moal
147 4008e2a0SDamien Le Moal static const struct iomap_writeback_ops zonefs_writeback_ops = {
148 4008e2a0SDamien Le Moal .map_blocks = zonefs_write_map_blocks,
149 4008e2a0SDamien Le Moal };
150 4008e2a0SDamien Le Moal
zonefs_writepages(struct address_space * mapping,struct writeback_control * wbc)151 4008e2a0SDamien Le Moal static int zonefs_writepages(struct address_space *mapping,
152 4008e2a0SDamien Le Moal struct writeback_control *wbc)
153 4008e2a0SDamien Le Moal {
154 4008e2a0SDamien Le Moal struct iomap_writepage_ctx wpc = { };
155 4008e2a0SDamien Le Moal
156 4008e2a0SDamien Le Moal return iomap_writepages(mapping, wbc, &wpc, &zonefs_writeback_ops);
157 4008e2a0SDamien Le Moal }
158 4008e2a0SDamien Le Moal
zonefs_swap_activate(struct swap_info_struct * sis,struct file * swap_file,sector_t * span)159 4008e2a0SDamien Le Moal static int zonefs_swap_activate(struct swap_info_struct *sis,
160 4008e2a0SDamien Le Moal struct file *swap_file, sector_t *span)
161 4008e2a0SDamien Le Moal {
162 4008e2a0SDamien Le Moal struct inode *inode = file_inode(swap_file);
163 4008e2a0SDamien Le Moal
164 34422914SDamien Le Moal if (zonefs_inode_is_seq(inode)) {
165 4008e2a0SDamien Le Moal zonefs_err(inode->i_sb,
166 4008e2a0SDamien Le Moal "swap file: not a conventional zone file\n");
167 4008e2a0SDamien Le Moal return -EINVAL;
168 4008e2a0SDamien Le Moal }
169 4008e2a0SDamien Le Moal
170 4008e2a0SDamien Le Moal return iomap_swapfile_activate(sis, swap_file, span,
171 4008e2a0SDamien Le Moal &zonefs_read_iomap_ops);
172 4008e2a0SDamien Le Moal }
173 4008e2a0SDamien Le Moal
174 4008e2a0SDamien Le Moal const struct address_space_operations zonefs_file_aops = {
175 4008e2a0SDamien Le Moal .read_folio = zonefs_read_folio,
176 4008e2a0SDamien Le Moal .readahead = zonefs_readahead,
177 4008e2a0SDamien Le Moal .writepages = zonefs_writepages,
178 4ce02c67SRitesh Harjani (IBM) .dirty_folio = iomap_dirty_folio,
179 4008e2a0SDamien Le Moal .release_folio = iomap_release_folio,
180 4008e2a0SDamien Le Moal .invalidate_folio = iomap_invalidate_folio,
181 4008e2a0SDamien Le Moal .migrate_folio = filemap_migrate_folio,
182 4008e2a0SDamien Le Moal .is_partially_uptodate = iomap_is_partially_uptodate,
183 4008e2a0SDamien Le Moal .error_remove_page = generic_error_remove_page,
184 4008e2a0SDamien Le Moal .swap_activate = zonefs_swap_activate,
185 4008e2a0SDamien Le Moal };
186 4008e2a0SDamien Le Moal
zonefs_file_truncate(struct inode * inode,loff_t isize)187 4008e2a0SDamien Le Moal int zonefs_file_truncate(struct inode *inode, loff_t isize)
188 4008e2a0SDamien Le Moal {
189 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
190 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
191 4008e2a0SDamien Le Moal loff_t old_isize;
192 4008e2a0SDamien Le Moal enum req_op op;
193 4008e2a0SDamien Le Moal int ret = 0;
194 4008e2a0SDamien Le Moal
195 4008e2a0SDamien Le Moal /*
196 4008e2a0SDamien Le Moal * Only sequential zone files can be truncated and truncation is allowed
197 4008e2a0SDamien Le Moal * only down to a 0 size, which is equivalent to a zone reset, and to
198 4008e2a0SDamien Le Moal * the maximum file size, which is equivalent to a zone finish.
199 4008e2a0SDamien Le Moal */
200 aa7f243fSDamien Le Moal if (!zonefs_zone_is_seq(z))
201 4008e2a0SDamien Le Moal return -EPERM;
202 4008e2a0SDamien Le Moal
203 4008e2a0SDamien Le Moal if (!isize)
204 4008e2a0SDamien Le Moal op = REQ_OP_ZONE_RESET;
205 aa7f243fSDamien Le Moal else if (isize == z->z_capacity)
206 4008e2a0SDamien Le Moal op = REQ_OP_ZONE_FINISH;
207 4008e2a0SDamien Le Moal else
208 4008e2a0SDamien Le Moal return -EPERM;
209 4008e2a0SDamien Le Moal
210 4008e2a0SDamien Le Moal inode_dio_wait(inode);
211 4008e2a0SDamien Le Moal
212 4008e2a0SDamien Le Moal /* Serialize against page faults */
213 4008e2a0SDamien Le Moal filemap_invalidate_lock(inode->i_mapping);
214 4008e2a0SDamien Le Moal
215 4008e2a0SDamien Le Moal /* Serialize against zonefs_iomap_begin() */
216 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
217 4008e2a0SDamien Le Moal
218 4008e2a0SDamien Le Moal old_isize = i_size_read(inode);
219 4008e2a0SDamien Le Moal if (isize == old_isize)
220 4008e2a0SDamien Le Moal goto unlock;
221 4008e2a0SDamien Le Moal
222 aa7f243fSDamien Le Moal ret = zonefs_inode_zone_mgmt(inode, op);
223 4008e2a0SDamien Le Moal if (ret)
224 4008e2a0SDamien Le Moal goto unlock;
225 4008e2a0SDamien Le Moal
226 4008e2a0SDamien Le Moal /*
227 4008e2a0SDamien Le Moal * If the mount option ZONEFS_MNTOPT_EXPLICIT_OPEN is set,
228 4008e2a0SDamien Le Moal * take care of open zones.
229 4008e2a0SDamien Le Moal */
230 aa7f243fSDamien Le Moal if (z->z_flags & ZONEFS_ZONE_OPEN) {
231 4008e2a0SDamien Le Moal /*
232 4008e2a0SDamien Le Moal * Truncating a zone to EMPTY or FULL is the equivalent of
233 4008e2a0SDamien Le Moal * closing the zone. For a truncation to 0, we need to
234 4008e2a0SDamien Le Moal * re-open the zone to ensure new writes can be processed.
235 4008e2a0SDamien Le Moal * For a truncation to the maximum file size, the zone is
236 4008e2a0SDamien Le Moal * closed and writes cannot be accepted anymore, so clear
237 4008e2a0SDamien Le Moal * the open flag.
238 4008e2a0SDamien Le Moal */
239 4008e2a0SDamien Le Moal if (!isize)
240 aa7f243fSDamien Le Moal ret = zonefs_inode_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
241 4008e2a0SDamien Le Moal else
242 aa7f243fSDamien Le Moal z->z_flags &= ~ZONEFS_ZONE_OPEN;
243 4008e2a0SDamien Le Moal }
244 4008e2a0SDamien Le Moal
245 4008e2a0SDamien Le Moal zonefs_update_stats(inode, isize);
246 4008e2a0SDamien Le Moal truncate_setsize(inode, isize);
247 aa7f243fSDamien Le Moal z->z_wpoffset = isize;
248 aa7f243fSDamien Le Moal zonefs_inode_account_active(inode);
249 4008e2a0SDamien Le Moal
250 4008e2a0SDamien Le Moal unlock:
251 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
252 4008e2a0SDamien Le Moal filemap_invalidate_unlock(inode->i_mapping);
253 4008e2a0SDamien Le Moal
254 4008e2a0SDamien Le Moal return ret;
255 4008e2a0SDamien Le Moal }
256 4008e2a0SDamien Le Moal
zonefs_file_fsync(struct file * file,loff_t start,loff_t end,int datasync)257 4008e2a0SDamien Le Moal static int zonefs_file_fsync(struct file *file, loff_t start, loff_t end,
258 4008e2a0SDamien Le Moal int datasync)
259 4008e2a0SDamien Le Moal {
260 4008e2a0SDamien Le Moal struct inode *inode = file_inode(file);
261 4008e2a0SDamien Le Moal int ret = 0;
262 4008e2a0SDamien Le Moal
263 4008e2a0SDamien Le Moal if (unlikely(IS_IMMUTABLE(inode)))
264 4008e2a0SDamien Le Moal return -EPERM;
265 4008e2a0SDamien Le Moal
266 4008e2a0SDamien Le Moal /*
267 4008e2a0SDamien Le Moal * Since only direct writes are allowed in sequential files, page cache
268 4008e2a0SDamien Le Moal * flush is needed only for conventional zone files.
269 4008e2a0SDamien Le Moal */
270 34422914SDamien Le Moal if (zonefs_inode_is_cnv(inode))
271 4008e2a0SDamien Le Moal ret = file_write_and_wait_range(file, start, end);
272 4008e2a0SDamien Le Moal if (!ret)
273 4008e2a0SDamien Le Moal ret = blkdev_issue_flush(inode->i_sb->s_bdev);
274 4008e2a0SDamien Le Moal
275 4008e2a0SDamien Le Moal if (ret)
276 4008e2a0SDamien Le Moal zonefs_io_error(inode, true);
277 4008e2a0SDamien Le Moal
278 4008e2a0SDamien Le Moal return ret;
279 4008e2a0SDamien Le Moal }
280 4008e2a0SDamien Le Moal
zonefs_filemap_page_mkwrite(struct vm_fault * vmf)281 4008e2a0SDamien Le Moal static vm_fault_t zonefs_filemap_page_mkwrite(struct vm_fault *vmf)
282 4008e2a0SDamien Le Moal {
283 4008e2a0SDamien Le Moal struct inode *inode = file_inode(vmf->vma->vm_file);
284 4008e2a0SDamien Le Moal vm_fault_t ret;
285 4008e2a0SDamien Le Moal
286 4008e2a0SDamien Le Moal if (unlikely(IS_IMMUTABLE(inode)))
287 4008e2a0SDamien Le Moal return VM_FAULT_SIGBUS;
288 4008e2a0SDamien Le Moal
289 4008e2a0SDamien Le Moal /*
290 4008e2a0SDamien Le Moal * Sanity check: only conventional zone files can have shared
291 4008e2a0SDamien Le Moal * writeable mappings.
292 4008e2a0SDamien Le Moal */
293 34422914SDamien Le Moal if (zonefs_inode_is_seq(inode))
294 4008e2a0SDamien Le Moal return VM_FAULT_NOPAGE;
295 4008e2a0SDamien Le Moal
296 4008e2a0SDamien Le Moal sb_start_pagefault(inode->i_sb);
297 4008e2a0SDamien Le Moal file_update_time(vmf->vma->vm_file);
298 4008e2a0SDamien Le Moal
299 4008e2a0SDamien Le Moal /* Serialize against truncates */
300 4008e2a0SDamien Le Moal filemap_invalidate_lock_shared(inode->i_mapping);
301 4008e2a0SDamien Le Moal ret = iomap_page_mkwrite(vmf, &zonefs_write_iomap_ops);
302 4008e2a0SDamien Le Moal filemap_invalidate_unlock_shared(inode->i_mapping);
303 4008e2a0SDamien Le Moal
304 4008e2a0SDamien Le Moal sb_end_pagefault(inode->i_sb);
305 4008e2a0SDamien Le Moal return ret;
306 4008e2a0SDamien Le Moal }
307 4008e2a0SDamien Le Moal
308 4008e2a0SDamien Le Moal static const struct vm_operations_struct zonefs_file_vm_ops = {
309 4008e2a0SDamien Le Moal .fault = filemap_fault,
310 4008e2a0SDamien Le Moal .map_pages = filemap_map_pages,
311 4008e2a0SDamien Le Moal .page_mkwrite = zonefs_filemap_page_mkwrite,
312 4008e2a0SDamien Le Moal };
313 4008e2a0SDamien Le Moal
zonefs_file_mmap(struct file * file,struct vm_area_struct * vma)314 4008e2a0SDamien Le Moal static int zonefs_file_mmap(struct file *file, struct vm_area_struct *vma)
315 4008e2a0SDamien Le Moal {
316 4008e2a0SDamien Le Moal /*
317 4008e2a0SDamien Le Moal * Conventional zones accept random writes, so their files can support
318 4008e2a0SDamien Le Moal * shared writable mappings. For sequential zone files, only read
319 4008e2a0SDamien Le Moal * mappings are possible since there are no guarantees for write
320 4008e2a0SDamien Le Moal * ordering between msync() and page cache writeback.
321 4008e2a0SDamien Le Moal */
322 34422914SDamien Le Moal if (zonefs_inode_is_seq(file_inode(file)) &&
323 4008e2a0SDamien Le Moal (vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
324 4008e2a0SDamien Le Moal return -EINVAL;
325 4008e2a0SDamien Le Moal
326 4008e2a0SDamien Le Moal file_accessed(file);
327 4008e2a0SDamien Le Moal vma->vm_ops = &zonefs_file_vm_ops;
328 4008e2a0SDamien Le Moal
329 4008e2a0SDamien Le Moal return 0;
330 4008e2a0SDamien Le Moal }
331 4008e2a0SDamien Le Moal
zonefs_file_llseek(struct file * file,loff_t offset,int whence)332 4008e2a0SDamien Le Moal static loff_t zonefs_file_llseek(struct file *file, loff_t offset, int whence)
333 4008e2a0SDamien Le Moal {
334 4008e2a0SDamien Le Moal loff_t isize = i_size_read(file_inode(file));
335 4008e2a0SDamien Le Moal
336 4008e2a0SDamien Le Moal /*
337 4008e2a0SDamien Le Moal * Seeks are limited to below the zone size for conventional zones
338 4008e2a0SDamien Le Moal * and below the zone write pointer for sequential zones. In both
339 4008e2a0SDamien Le Moal * cases, this limit is the inode size.
340 4008e2a0SDamien Le Moal */
341 4008e2a0SDamien Le Moal return generic_file_llseek_size(file, offset, whence, isize, isize);
342 4008e2a0SDamien Le Moal }
343 4008e2a0SDamien Le Moal
zonefs_file_write_dio_end_io(struct kiocb * iocb,ssize_t size,int error,unsigned int flags)344 4008e2a0SDamien Le Moal static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
345 4008e2a0SDamien Le Moal int error, unsigned int flags)
346 4008e2a0SDamien Le Moal {
347 4008e2a0SDamien Le Moal struct inode *inode = file_inode(iocb->ki_filp);
348 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
349 4008e2a0SDamien Le Moal
350 4008e2a0SDamien Le Moal if (error) {
351 *6d5eae9aSDamien Le Moal /*
352 *6d5eae9aSDamien Le Moal * For Sync IOs, error recovery is called from
353 *6d5eae9aSDamien Le Moal * zonefs_file_dio_write().
354 *6d5eae9aSDamien Le Moal */
355 *6d5eae9aSDamien Le Moal if (!is_sync_kiocb(iocb))
356 4008e2a0SDamien Le Moal zonefs_io_error(inode, true);
357 4008e2a0SDamien Le Moal return error;
358 4008e2a0SDamien Le Moal }
359 4008e2a0SDamien Le Moal
360 aa7f243fSDamien Le Moal if (size && zonefs_inode_is_seq(inode)) {
361 4008e2a0SDamien Le Moal /*
362 4008e2a0SDamien Le Moal * Note that we may be seeing completions out of order,
363 4008e2a0SDamien Le Moal * but that is not a problem since a write completed
364 4008e2a0SDamien Le Moal * successfully necessarily means that all preceding writes
365 4008e2a0SDamien Le Moal * were also successful. So we can safely increase the inode
366 4008e2a0SDamien Le Moal * size to the write end location.
367 4008e2a0SDamien Le Moal */
368 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
369 4008e2a0SDamien Le Moal if (i_size_read(inode) < iocb->ki_pos + size) {
370 4008e2a0SDamien Le Moal zonefs_update_stats(inode, iocb->ki_pos + size);
371 4008e2a0SDamien Le Moal zonefs_i_size_write(inode, iocb->ki_pos + size);
372 4008e2a0SDamien Le Moal }
373 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
374 4008e2a0SDamien Le Moal }
375 4008e2a0SDamien Le Moal
376 4008e2a0SDamien Le Moal return 0;
377 4008e2a0SDamien Le Moal }
378 4008e2a0SDamien Le Moal
379 4008e2a0SDamien Le Moal static const struct iomap_dio_ops zonefs_write_dio_ops = {
380 4008e2a0SDamien Le Moal .end_io = zonefs_file_write_dio_end_io,
381 4008e2a0SDamien Le Moal };
382 4008e2a0SDamien Le Moal
383 4008e2a0SDamien Le Moal /*
384 4008e2a0SDamien Le Moal * Do not exceed the LFS limits nor the file zone size. If pos is under the
385 4008e2a0SDamien Le Moal * limit it becomes a short access. If it exceeds the limit, return -EFBIG.
386 4008e2a0SDamien Le Moal */
zonefs_write_check_limits(struct file * file,loff_t pos,loff_t count)387 4008e2a0SDamien Le Moal static loff_t zonefs_write_check_limits(struct file *file, loff_t pos,
388 4008e2a0SDamien Le Moal loff_t count)
389 4008e2a0SDamien Le Moal {
390 4008e2a0SDamien Le Moal struct inode *inode = file_inode(file);
391 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
392 4008e2a0SDamien Le Moal loff_t limit = rlimit(RLIMIT_FSIZE);
393 aa7f243fSDamien Le Moal loff_t max_size = z->z_capacity;
394 4008e2a0SDamien Le Moal
395 4008e2a0SDamien Le Moal if (limit != RLIM_INFINITY) {
396 4008e2a0SDamien Le Moal if (pos >= limit) {
397 4008e2a0SDamien Le Moal send_sig(SIGXFSZ, current, 0);
398 4008e2a0SDamien Le Moal return -EFBIG;
399 4008e2a0SDamien Le Moal }
400 4008e2a0SDamien Le Moal count = min(count, limit - pos);
401 4008e2a0SDamien Le Moal }
402 4008e2a0SDamien Le Moal
403 4008e2a0SDamien Le Moal if (!(file->f_flags & O_LARGEFILE))
404 4008e2a0SDamien Le Moal max_size = min_t(loff_t, MAX_NON_LFS, max_size);
405 4008e2a0SDamien Le Moal
406 4008e2a0SDamien Le Moal if (unlikely(pos >= max_size))
407 4008e2a0SDamien Le Moal return -EFBIG;
408 4008e2a0SDamien Le Moal
409 4008e2a0SDamien Le Moal return min(count, max_size - pos);
410 4008e2a0SDamien Le Moal }
411 4008e2a0SDamien Le Moal
zonefs_write_checks(struct kiocb * iocb,struct iov_iter * from)412 4008e2a0SDamien Le Moal static ssize_t zonefs_write_checks(struct kiocb *iocb, struct iov_iter *from)
413 4008e2a0SDamien Le Moal {
414 4008e2a0SDamien Le Moal struct file *file = iocb->ki_filp;
415 4008e2a0SDamien Le Moal struct inode *inode = file_inode(file);
416 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
417 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
418 4008e2a0SDamien Le Moal loff_t count;
419 4008e2a0SDamien Le Moal
420 4008e2a0SDamien Le Moal if (IS_SWAPFILE(inode))
421 4008e2a0SDamien Le Moal return -ETXTBSY;
422 4008e2a0SDamien Le Moal
423 4008e2a0SDamien Le Moal if (!iov_iter_count(from))
424 4008e2a0SDamien Le Moal return 0;
425 4008e2a0SDamien Le Moal
426 4008e2a0SDamien Le Moal if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
427 4008e2a0SDamien Le Moal return -EINVAL;
428 4008e2a0SDamien Le Moal
429 4008e2a0SDamien Le Moal if (iocb->ki_flags & IOCB_APPEND) {
430 aa7f243fSDamien Le Moal if (zonefs_zone_is_cnv(z))
431 4008e2a0SDamien Le Moal return -EINVAL;
432 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
433 aa7f243fSDamien Le Moal iocb->ki_pos = z->z_wpoffset;
434 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
435 4008e2a0SDamien Le Moal }
436 4008e2a0SDamien Le Moal
437 4008e2a0SDamien Le Moal count = zonefs_write_check_limits(file, iocb->ki_pos,
438 4008e2a0SDamien Le Moal iov_iter_count(from));
439 4008e2a0SDamien Le Moal if (count < 0)
440 4008e2a0SDamien Le Moal return count;
441 4008e2a0SDamien Le Moal
442 4008e2a0SDamien Le Moal iov_iter_truncate(from, count);
443 4008e2a0SDamien Le Moal return iov_iter_count(from);
444 4008e2a0SDamien Le Moal }
445 4008e2a0SDamien Le Moal
446 4008e2a0SDamien Le Moal /*
447 4008e2a0SDamien Le Moal * Handle direct writes. For sequential zone files, this is the only possible
448 4008e2a0SDamien Le Moal * write path. For these files, check that the user is issuing writes
449 4008e2a0SDamien Le Moal * sequentially from the end of the file. This code assumes that the block layer
450 4008e2a0SDamien Le Moal * delivers write requests to the device in sequential order. This is always the
451 4008e2a0SDamien Le Moal * case if a block IO scheduler implementing the ELEVATOR_F_ZBD_SEQ_WRITE
452 4008e2a0SDamien Le Moal * elevator feature is being used (e.g. mq-deadline). The block layer always
453 4008e2a0SDamien Le Moal * automatically select such an elevator for zoned block devices during the
454 4008e2a0SDamien Le Moal * device initialization.
455 4008e2a0SDamien Le Moal */
zonefs_file_dio_write(struct kiocb * iocb,struct iov_iter * from)456 4008e2a0SDamien Le Moal static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
457 4008e2a0SDamien Le Moal {
458 4008e2a0SDamien Le Moal struct inode *inode = file_inode(iocb->ki_filp);
459 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
460 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
461 4008e2a0SDamien Le Moal struct super_block *sb = inode->i_sb;
462 4008e2a0SDamien Le Moal ssize_t ret, count;
463 4008e2a0SDamien Le Moal
464 4008e2a0SDamien Le Moal /*
465 4008e2a0SDamien Le Moal * For async direct IOs to sequential zone files, refuse IOCB_NOWAIT
466 4008e2a0SDamien Le Moal * as this can cause write reordering (e.g. the first aio gets EAGAIN
467 4008e2a0SDamien Le Moal * on the inode lock but the second goes through but is now unaligned).
468 4008e2a0SDamien Le Moal */
469 fe9da61fSDamien Le Moal if (zonefs_zone_is_seq(z) && !is_sync_kiocb(iocb) &&
470 fe9da61fSDamien Le Moal (iocb->ki_flags & IOCB_NOWAIT))
471 4008e2a0SDamien Le Moal return -EOPNOTSUPP;
472 4008e2a0SDamien Le Moal
473 4008e2a0SDamien Le Moal if (iocb->ki_flags & IOCB_NOWAIT) {
474 4008e2a0SDamien Le Moal if (!inode_trylock(inode))
475 4008e2a0SDamien Le Moal return -EAGAIN;
476 4008e2a0SDamien Le Moal } else {
477 4008e2a0SDamien Le Moal inode_lock(inode);
478 4008e2a0SDamien Le Moal }
479 4008e2a0SDamien Le Moal
480 4008e2a0SDamien Le Moal count = zonefs_write_checks(iocb, from);
481 4008e2a0SDamien Le Moal if (count <= 0) {
482 4008e2a0SDamien Le Moal ret = count;
483 4008e2a0SDamien Le Moal goto inode_unlock;
484 4008e2a0SDamien Le Moal }
485 4008e2a0SDamien Le Moal
486 4008e2a0SDamien Le Moal if ((iocb->ki_pos | count) & (sb->s_blocksize - 1)) {
487 4008e2a0SDamien Le Moal ret = -EINVAL;
488 4008e2a0SDamien Le Moal goto inode_unlock;
489 4008e2a0SDamien Le Moal }
490 4008e2a0SDamien Le Moal
491 4008e2a0SDamien Le Moal /* Enforce sequential writes (append only) in sequential zones */
492 aa7f243fSDamien Le Moal if (zonefs_zone_is_seq(z)) {
493 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
494 aa7f243fSDamien Le Moal if (iocb->ki_pos != z->z_wpoffset) {
495 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
496 4008e2a0SDamien Le Moal ret = -EINVAL;
497 4008e2a0SDamien Le Moal goto inode_unlock;
498 4008e2a0SDamien Le Moal }
499 *6d5eae9aSDamien Le Moal /*
500 *6d5eae9aSDamien Le Moal * Advance the zone write pointer offset. This assumes that the
501 *6d5eae9aSDamien Le Moal * IO will succeed, which is OK to do because we do not allow
502 *6d5eae9aSDamien Le Moal * partial writes (IOMAP_DIO_PARTIAL is not set) and if the IO
503 *6d5eae9aSDamien Le Moal * fails, the error path will correct the write pointer offset.
504 *6d5eae9aSDamien Le Moal */
505 *6d5eae9aSDamien Le Moal z->z_wpoffset += count;
506 *6d5eae9aSDamien Le Moal zonefs_inode_account_active(inode);
507 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
508 16d7fd3cSDamien Le Moal }
509 16d7fd3cSDamien Le Moal
510 77af13baSDamien Le Moal /*
511 77af13baSDamien Le Moal * iomap_dio_rw() may return ENOTBLK if there was an issue with
512 16d7fd3cSDamien Le Moal * page invalidation. Overwrite that error code with EBUSY so that
513 16d7fd3cSDamien Le Moal * the user can make sense of the error.
514 77af13baSDamien Le Moal */
515 4008e2a0SDamien Le Moal ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops,
516 fe9da61fSDamien Le Moal &zonefs_write_dio_ops, 0, NULL, 0);
517 77af13baSDamien Le Moal if (ret == -ENOTBLK)
518 77af13baSDamien Le Moal ret = -EBUSY;
519 77af13baSDamien Le Moal
520 4008e2a0SDamien Le Moal /*
521 *6d5eae9aSDamien Le Moal * For a failed IO or partial completion, trigger error recovery
522 *6d5eae9aSDamien Le Moal * to update the zone write pointer offset to a correct value.
523 *6d5eae9aSDamien Le Moal * For asynchronous IOs, zonefs_file_write_dio_end_io() may already
524 *6d5eae9aSDamien Le Moal * have executed error recovery if the IO already completed when we
525 *6d5eae9aSDamien Le Moal * reach here. However, we cannot know that and execute error recovery
526 *6d5eae9aSDamien Le Moal * again (that will not change anything).
527 4008e2a0SDamien Le Moal */
528 *6d5eae9aSDamien Le Moal if (zonefs_zone_is_seq(z)) {
529 *6d5eae9aSDamien Le Moal if (ret > 0 && ret != count)
530 *6d5eae9aSDamien Le Moal ret = -EIO;
531 *6d5eae9aSDamien Le Moal if (ret < 0 && ret != -EIOCBQUEUED)
532 *6d5eae9aSDamien Le Moal zonefs_io_error(inode, true);
533 4008e2a0SDamien Le Moal }
534 4008e2a0SDamien Le Moal
535 4008e2a0SDamien Le Moal inode_unlock:
536 4008e2a0SDamien Le Moal inode_unlock(inode);
537 4008e2a0SDamien Le Moal
538 4008e2a0SDamien Le Moal return ret;
539 4008e2a0SDamien Le Moal }
540 4008e2a0SDamien Le Moal
zonefs_file_buffered_write(struct kiocb * iocb,struct iov_iter * from)541 4008e2a0SDamien Le Moal static ssize_t zonefs_file_buffered_write(struct kiocb *iocb,
542 4008e2a0SDamien Le Moal struct iov_iter *from)
543 4008e2a0SDamien Le Moal {
544 4008e2a0SDamien Le Moal struct inode *inode = file_inode(iocb->ki_filp);
545 4008e2a0SDamien Le Moal ssize_t ret;
546 4008e2a0SDamien Le Moal
547 4008e2a0SDamien Le Moal /*
548 4008e2a0SDamien Le Moal * Direct IO writes are mandatory for sequential zone files so that the
549 4008e2a0SDamien Le Moal * write IO issuing order is preserved.
550 4008e2a0SDamien Le Moal */
551 34422914SDamien Le Moal if (zonefs_inode_is_seq(inode))
552 4008e2a0SDamien Le Moal return -EIO;
553 4008e2a0SDamien Le Moal
554 4008e2a0SDamien Le Moal if (iocb->ki_flags & IOCB_NOWAIT) {
555 4008e2a0SDamien Le Moal if (!inode_trylock(inode))
556 4008e2a0SDamien Le Moal return -EAGAIN;
557 4008e2a0SDamien Le Moal } else {
558 4008e2a0SDamien Le Moal inode_lock(inode);
559 4008e2a0SDamien Le Moal }
560 4008e2a0SDamien Le Moal
561 4008e2a0SDamien Le Moal ret = zonefs_write_checks(iocb, from);
562 4008e2a0SDamien Le Moal if (ret <= 0)
563 4008e2a0SDamien Le Moal goto inode_unlock;
564 4008e2a0SDamien Le Moal
565 4008e2a0SDamien Le Moal ret = iomap_file_buffered_write(iocb, from, &zonefs_write_iomap_ops);
566 219580eeSChristoph Hellwig if (ret == -EIO)
567 4008e2a0SDamien Le Moal zonefs_io_error(inode, true);
568 4008e2a0SDamien Le Moal
569 4008e2a0SDamien Le Moal inode_unlock:
570 4008e2a0SDamien Le Moal inode_unlock(inode);
571 4008e2a0SDamien Le Moal if (ret > 0)
572 4008e2a0SDamien Le Moal ret = generic_write_sync(iocb, ret);
573 4008e2a0SDamien Le Moal
574 4008e2a0SDamien Le Moal return ret;
575 4008e2a0SDamien Le Moal }
576 4008e2a0SDamien Le Moal
zonefs_file_write_iter(struct kiocb * iocb,struct iov_iter * from)577 4008e2a0SDamien Le Moal static ssize_t zonefs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
578 4008e2a0SDamien Le Moal {
579 4008e2a0SDamien Le Moal struct inode *inode = file_inode(iocb->ki_filp);
580 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
581 4008e2a0SDamien Le Moal
582 4008e2a0SDamien Le Moal if (unlikely(IS_IMMUTABLE(inode)))
583 4008e2a0SDamien Le Moal return -EPERM;
584 4008e2a0SDamien Le Moal
585 4008e2a0SDamien Le Moal if (sb_rdonly(inode->i_sb))
586 4008e2a0SDamien Le Moal return -EROFS;
587 4008e2a0SDamien Le Moal
588 aa7f243fSDamien Le Moal /* Write operations beyond the zone capacity are not allowed */
589 aa7f243fSDamien Le Moal if (iocb->ki_pos >= z->z_capacity)
590 4008e2a0SDamien Le Moal return -EFBIG;
591 4008e2a0SDamien Le Moal
592 4008e2a0SDamien Le Moal if (iocb->ki_flags & IOCB_DIRECT) {
593 4008e2a0SDamien Le Moal ssize_t ret = zonefs_file_dio_write(iocb, from);
594 4008e2a0SDamien Le Moal
595 4008e2a0SDamien Le Moal if (ret != -ENOTBLK)
596 4008e2a0SDamien Le Moal return ret;
597 4008e2a0SDamien Le Moal }
598 4008e2a0SDamien Le Moal
599 4008e2a0SDamien Le Moal return zonefs_file_buffered_write(iocb, from);
600 4008e2a0SDamien Le Moal }
601 4008e2a0SDamien Le Moal
zonefs_file_read_dio_end_io(struct kiocb * iocb,ssize_t size,int error,unsigned int flags)602 4008e2a0SDamien Le Moal static int zonefs_file_read_dio_end_io(struct kiocb *iocb, ssize_t size,
603 4008e2a0SDamien Le Moal int error, unsigned int flags)
604 4008e2a0SDamien Le Moal {
605 4008e2a0SDamien Le Moal if (error) {
606 4008e2a0SDamien Le Moal zonefs_io_error(file_inode(iocb->ki_filp), false);
607 4008e2a0SDamien Le Moal return error;
608 4008e2a0SDamien Le Moal }
609 4008e2a0SDamien Le Moal
610 4008e2a0SDamien Le Moal return 0;
611 4008e2a0SDamien Le Moal }
612 4008e2a0SDamien Le Moal
613 4008e2a0SDamien Le Moal static const struct iomap_dio_ops zonefs_read_dio_ops = {
614 4008e2a0SDamien Le Moal .end_io = zonefs_file_read_dio_end_io,
615 4008e2a0SDamien Le Moal };
616 4008e2a0SDamien Le Moal
zonefs_file_read_iter(struct kiocb * iocb,struct iov_iter * to)617 4008e2a0SDamien Le Moal static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
618 4008e2a0SDamien Le Moal {
619 4008e2a0SDamien Le Moal struct inode *inode = file_inode(iocb->ki_filp);
620 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
621 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
622 4008e2a0SDamien Le Moal struct super_block *sb = inode->i_sb;
623 4008e2a0SDamien Le Moal loff_t isize;
624 4008e2a0SDamien Le Moal ssize_t ret;
625 4008e2a0SDamien Le Moal
626 4008e2a0SDamien Le Moal /* Offline zones cannot be read */
627 4008e2a0SDamien Le Moal if (unlikely(IS_IMMUTABLE(inode) && !(inode->i_mode & 0777)))
628 4008e2a0SDamien Le Moal return -EPERM;
629 4008e2a0SDamien Le Moal
630 aa7f243fSDamien Le Moal if (iocb->ki_pos >= z->z_capacity)
631 4008e2a0SDamien Le Moal return 0;
632 4008e2a0SDamien Le Moal
633 4008e2a0SDamien Le Moal if (iocb->ki_flags & IOCB_NOWAIT) {
634 4008e2a0SDamien Le Moal if (!inode_trylock_shared(inode))
635 4008e2a0SDamien Le Moal return -EAGAIN;
636 4008e2a0SDamien Le Moal } else {
637 4008e2a0SDamien Le Moal inode_lock_shared(inode);
638 4008e2a0SDamien Le Moal }
639 4008e2a0SDamien Le Moal
640 4008e2a0SDamien Le Moal /* Limit read operations to written data */
641 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
642 4008e2a0SDamien Le Moal isize = i_size_read(inode);
643 4008e2a0SDamien Le Moal if (iocb->ki_pos >= isize) {
644 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
645 4008e2a0SDamien Le Moal ret = 0;
646 4008e2a0SDamien Le Moal goto inode_unlock;
647 4008e2a0SDamien Le Moal }
648 4008e2a0SDamien Le Moal iov_iter_truncate(to, isize - iocb->ki_pos);
649 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
650 4008e2a0SDamien Le Moal
651 4008e2a0SDamien Le Moal if (iocb->ki_flags & IOCB_DIRECT) {
652 4008e2a0SDamien Le Moal size_t count = iov_iter_count(to);
653 4008e2a0SDamien Le Moal
654 4008e2a0SDamien Le Moal if ((iocb->ki_pos | count) & (sb->s_blocksize - 1)) {
655 4008e2a0SDamien Le Moal ret = -EINVAL;
656 4008e2a0SDamien Le Moal goto inode_unlock;
657 4008e2a0SDamien Le Moal }
658 4008e2a0SDamien Le Moal file_accessed(iocb->ki_filp);
659 4008e2a0SDamien Le Moal ret = iomap_dio_rw(iocb, to, &zonefs_read_iomap_ops,
660 4008e2a0SDamien Le Moal &zonefs_read_dio_ops, 0, NULL, 0);
661 4008e2a0SDamien Le Moal } else {
662 4008e2a0SDamien Le Moal ret = generic_file_read_iter(iocb, to);
663 4008e2a0SDamien Le Moal if (ret == -EIO)
664 4008e2a0SDamien Le Moal zonefs_io_error(inode, false);
665 4008e2a0SDamien Le Moal }
666 4008e2a0SDamien Le Moal
667 4008e2a0SDamien Le Moal inode_unlock:
668 4008e2a0SDamien Le Moal inode_unlock_shared(inode);
669 4008e2a0SDamien Le Moal
670 4008e2a0SDamien Le Moal return ret;
671 4008e2a0SDamien Le Moal }
672 4008e2a0SDamien Le Moal
zonefs_file_splice_read(struct file * in,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags)673 6ef48ec3SDavid Howells static ssize_t zonefs_file_splice_read(struct file *in, loff_t *ppos,
674 6ef48ec3SDavid Howells struct pipe_inode_info *pipe,
675 6ef48ec3SDavid Howells size_t len, unsigned int flags)
676 6ef48ec3SDavid Howells {
677 6ef48ec3SDavid Howells struct inode *inode = file_inode(in);
678 6ef48ec3SDavid Howells struct zonefs_inode_info *zi = ZONEFS_I(inode);
679 6ef48ec3SDavid Howells struct zonefs_zone *z = zonefs_inode_zone(inode);
680 6ef48ec3SDavid Howells loff_t isize;
681 6ef48ec3SDavid Howells ssize_t ret = 0;
682 6ef48ec3SDavid Howells
683 6ef48ec3SDavid Howells /* Offline zones cannot be read */
684 6ef48ec3SDavid Howells if (unlikely(IS_IMMUTABLE(inode) && !(inode->i_mode & 0777)))
685 6ef48ec3SDavid Howells return -EPERM;
686 6ef48ec3SDavid Howells
687 6ef48ec3SDavid Howells if (*ppos >= z->z_capacity)
688 6ef48ec3SDavid Howells return 0;
689 6ef48ec3SDavid Howells
690 6ef48ec3SDavid Howells inode_lock_shared(inode);
691 6ef48ec3SDavid Howells
692 6ef48ec3SDavid Howells /* Limit read operations to written data */
693 6ef48ec3SDavid Howells mutex_lock(&zi->i_truncate_mutex);
694 6ef48ec3SDavid Howells isize = i_size_read(inode);
695 6ef48ec3SDavid Howells if (*ppos >= isize)
696 6ef48ec3SDavid Howells len = 0;
697 6ef48ec3SDavid Howells else
698 6ef48ec3SDavid Howells len = min_t(loff_t, len, isize - *ppos);
699 6ef48ec3SDavid Howells mutex_unlock(&zi->i_truncate_mutex);
700 6ef48ec3SDavid Howells
701 6ef48ec3SDavid Howells if (len > 0) {
702 6ef48ec3SDavid Howells ret = filemap_splice_read(in, ppos, pipe, len, flags);
703 6ef48ec3SDavid Howells if (ret == -EIO)
704 6ef48ec3SDavid Howells zonefs_io_error(inode, false);
705 6ef48ec3SDavid Howells }
706 6ef48ec3SDavid Howells
707 6ef48ec3SDavid Howells inode_unlock_shared(inode);
708 6ef48ec3SDavid Howells return ret;
709 6ef48ec3SDavid Howells }
710 6ef48ec3SDavid Howells
711 4008e2a0SDamien Le Moal /*
712 4008e2a0SDamien Le Moal * Write open accounting is done only for sequential files.
713 4008e2a0SDamien Le Moal */
zonefs_seq_file_need_wro(struct inode * inode,struct file * file)714 4008e2a0SDamien Le Moal static inline bool zonefs_seq_file_need_wro(struct inode *inode,
715 4008e2a0SDamien Le Moal struct file *file)
716 4008e2a0SDamien Le Moal {
717 34422914SDamien Le Moal if (zonefs_inode_is_cnv(inode))
718 4008e2a0SDamien Le Moal return false;
719 4008e2a0SDamien Le Moal
720 4008e2a0SDamien Le Moal if (!(file->f_mode & FMODE_WRITE))
721 4008e2a0SDamien Le Moal return false;
722 4008e2a0SDamien Le Moal
723 4008e2a0SDamien Le Moal return true;
724 4008e2a0SDamien Le Moal }
725 4008e2a0SDamien Le Moal
zonefs_seq_file_write_open(struct inode * inode)726 4008e2a0SDamien Le Moal static int zonefs_seq_file_write_open(struct inode *inode)
727 4008e2a0SDamien Le Moal {
728 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
729 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
730 4008e2a0SDamien Le Moal int ret = 0;
731 4008e2a0SDamien Le Moal
732 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
733 4008e2a0SDamien Le Moal
734 4008e2a0SDamien Le Moal if (!zi->i_wr_refcnt) {
735 4008e2a0SDamien Le Moal struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
736 4008e2a0SDamien Le Moal unsigned int wro = atomic_inc_return(&sbi->s_wro_seq_files);
737 4008e2a0SDamien Le Moal
738 4008e2a0SDamien Le Moal if (sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) {
739 4008e2a0SDamien Le Moal
740 4008e2a0SDamien Le Moal if (sbi->s_max_wro_seq_files
741 4008e2a0SDamien Le Moal && wro > sbi->s_max_wro_seq_files) {
742 4008e2a0SDamien Le Moal atomic_dec(&sbi->s_wro_seq_files);
743 4008e2a0SDamien Le Moal ret = -EBUSY;
744 4008e2a0SDamien Le Moal goto unlock;
745 4008e2a0SDamien Le Moal }
746 4008e2a0SDamien Le Moal
747 aa7f243fSDamien Le Moal if (i_size_read(inode) < z->z_capacity) {
748 aa7f243fSDamien Le Moal ret = zonefs_inode_zone_mgmt(inode,
749 aa7f243fSDamien Le Moal REQ_OP_ZONE_OPEN);
750 4008e2a0SDamien Le Moal if (ret) {
751 4008e2a0SDamien Le Moal atomic_dec(&sbi->s_wro_seq_files);
752 4008e2a0SDamien Le Moal goto unlock;
753 4008e2a0SDamien Le Moal }
754 aa7f243fSDamien Le Moal z->z_flags |= ZONEFS_ZONE_OPEN;
755 aa7f243fSDamien Le Moal zonefs_inode_account_active(inode);
756 4008e2a0SDamien Le Moal }
757 4008e2a0SDamien Le Moal }
758 4008e2a0SDamien Le Moal }
759 4008e2a0SDamien Le Moal
760 4008e2a0SDamien Le Moal zi->i_wr_refcnt++;
761 4008e2a0SDamien Le Moal
762 4008e2a0SDamien Le Moal unlock:
763 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
764 4008e2a0SDamien Le Moal
765 4008e2a0SDamien Le Moal return ret;
766 4008e2a0SDamien Le Moal }
767 4008e2a0SDamien Le Moal
zonefs_file_open(struct inode * inode,struct file * file)768 4008e2a0SDamien Le Moal static int zonefs_file_open(struct inode *inode, struct file *file)
769 4008e2a0SDamien Le Moal {
770 4008e2a0SDamien Le Moal int ret;
771 4008e2a0SDamien Le Moal
772 8812387dSChristoph Hellwig file->f_mode |= FMODE_CAN_ODIRECT;
773 4008e2a0SDamien Le Moal ret = generic_file_open(inode, file);
774 4008e2a0SDamien Le Moal if (ret)
775 4008e2a0SDamien Le Moal return ret;
776 4008e2a0SDamien Le Moal
777 4008e2a0SDamien Le Moal if (zonefs_seq_file_need_wro(inode, file))
778 4008e2a0SDamien Le Moal return zonefs_seq_file_write_open(inode);
779 4008e2a0SDamien Le Moal
780 4008e2a0SDamien Le Moal return 0;
781 4008e2a0SDamien Le Moal }
782 4008e2a0SDamien Le Moal
zonefs_seq_file_write_close(struct inode * inode)783 4008e2a0SDamien Le Moal static void zonefs_seq_file_write_close(struct inode *inode)
784 4008e2a0SDamien Le Moal {
785 4008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode);
786 aa7f243fSDamien Le Moal struct zonefs_zone *z = zonefs_inode_zone(inode);
787 4008e2a0SDamien Le Moal struct super_block *sb = inode->i_sb;
788 4008e2a0SDamien Le Moal struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
789 4008e2a0SDamien Le Moal int ret = 0;
790 4008e2a0SDamien Le Moal
791 4008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex);
792 4008e2a0SDamien Le Moal
793 4008e2a0SDamien Le Moal zi->i_wr_refcnt--;
794 4008e2a0SDamien Le Moal if (zi->i_wr_refcnt)
795 4008e2a0SDamien Le Moal goto unlock;
796 4008e2a0SDamien Le Moal
797 4008e2a0SDamien Le Moal /*
798 4008e2a0SDamien Le Moal * The file zone may not be open anymore (e.g. the file was truncated to
799 4008e2a0SDamien Le Moal * its maximum size or it was fully written). For this case, we only
800 4008e2a0SDamien Le Moal * need to decrement the write open count.
801 4008e2a0SDamien Le Moal */
802 aa7f243fSDamien Le Moal if (z->z_flags & ZONEFS_ZONE_OPEN) {
803 aa7f243fSDamien Le Moal ret = zonefs_inode_zone_mgmt(inode, REQ_OP_ZONE_CLOSE);
804 4008e2a0SDamien Le Moal if (ret) {
805 4008e2a0SDamien Le Moal __zonefs_io_error(inode, false);
806 4008e2a0SDamien Le Moal /*
807 4008e2a0SDamien Le Moal * Leaving zones explicitly open may lead to a state
808 4008e2a0SDamien Le Moal * where most zones cannot be written (zone resources
809 4008e2a0SDamien Le Moal * exhausted). So take preventive action by remounting
810 4008e2a0SDamien Le Moal * read-only.
811 4008e2a0SDamien Le Moal */
812 aa7f243fSDamien Le Moal if (z->z_flags & ZONEFS_ZONE_OPEN &&
813 4008e2a0SDamien Le Moal !(sb->s_flags & SB_RDONLY)) {
814 4008e2a0SDamien Le Moal zonefs_warn(sb,
815 4008e2a0SDamien Le Moal "closing zone at %llu failed %d\n",
816 aa7f243fSDamien Le Moal z->z_sector, ret);
817 4008e2a0SDamien Le Moal zonefs_warn(sb,
818 4008e2a0SDamien Le Moal "remounting filesystem read-only\n");
819 4008e2a0SDamien Le Moal sb->s_flags |= SB_RDONLY;
820 4008e2a0SDamien Le Moal }
821 4008e2a0SDamien Le Moal goto unlock;
822 4008e2a0SDamien Le Moal }
823 4008e2a0SDamien Le Moal
824 aa7f243fSDamien Le Moal z->z_flags &= ~ZONEFS_ZONE_OPEN;
825 aa7f243fSDamien Le Moal zonefs_inode_account_active(inode);
826 4008e2a0SDamien Le Moal }
827 4008e2a0SDamien Le Moal
828 4008e2a0SDamien Le Moal atomic_dec(&sbi->s_wro_seq_files);
829 4008e2a0SDamien Le Moal
830 4008e2a0SDamien Le Moal unlock:
831 4008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex);
832 4008e2a0SDamien Le Moal }
833 4008e2a0SDamien Le Moal
zonefs_file_release(struct inode * inode,struct file * file)834 4008e2a0SDamien Le Moal static int zonefs_file_release(struct inode *inode, struct file *file)
835 4008e2a0SDamien Le Moal {
836 4008e2a0SDamien Le Moal /*
837 4008e2a0SDamien Le Moal * If we explicitly open a zone we must close it again as well, but the
838 4008e2a0SDamien Le Moal * zone management operation can fail (either due to an IO error or as
839 4008e2a0SDamien Le Moal * the zone has gone offline or read-only). Make sure we don't fail the
840 4008e2a0SDamien Le Moal * close(2) for user-space.
841 4008e2a0SDamien Le Moal */
842 4008e2a0SDamien Le Moal if (zonefs_seq_file_need_wro(inode, file))
843 4008e2a0SDamien Le Moal zonefs_seq_file_write_close(inode);
844 4008e2a0SDamien Le Moal
845 4008e2a0SDamien Le Moal return 0;
846 4008e2a0SDamien Le Moal }
847 4008e2a0SDamien Le Moal
848 4008e2a0SDamien Le Moal const struct file_operations zonefs_file_operations = {
849 4008e2a0SDamien Le Moal .open = zonefs_file_open,
850 4008e2a0SDamien Le Moal .release = zonefs_file_release,
851 4008e2a0SDamien Le Moal .fsync = zonefs_file_fsync,
852 4008e2a0SDamien Le Moal .mmap = zonefs_file_mmap,
853 4008e2a0SDamien Le Moal .llseek = zonefs_file_llseek,
854 4008e2a0SDamien Le Moal .read_iter = zonefs_file_read_iter,
855 4008e2a0SDamien Le Moal .write_iter = zonefs_file_write_iter,
856 6ef48ec3SDavid Howells .splice_read = zonefs_file_splice_read,
857 4008e2a0SDamien Le Moal .splice_write = iter_file_splice_write,
858 4008e2a0SDamien Le Moal .iopoll = iocb_bio_iopoll,
859 4008e2a0SDamien Le Moal };
860