xref: /openbmc/linux/fs/zonefs/file.c (revision c595db6d7c8bcf87ef42204391fa890e5950e566)
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