1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * This file contians vfs address (mmap) ops for 9P2000. 4 * 5 * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com> 6 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/errno.h> 11 #include <linux/fs.h> 12 #include <linux/file.h> 13 #include <linux/stat.h> 14 #include <linux/string.h> 15 #include <linux/pagemap.h> 16 #include <linux/sched.h> 17 #include <linux/swap.h> 18 #include <linux/uio.h> 19 #include <linux/netfs.h> 20 #include <net/9p/9p.h> 21 #include <net/9p/client.h> 22 23 #include "v9fs.h" 24 #include "v9fs_vfs.h" 25 #include "cache.h" 26 #include "fid.h" 27 28 /** 29 * v9fs_issue_read - Issue a read from 9P 30 * @subreq: The read to make 31 */ 32 static void v9fs_issue_read(struct netfs_io_subrequest *subreq) 33 { 34 struct netfs_io_request *rreq = subreq->rreq; 35 struct p9_fid *fid = rreq->netfs_priv; 36 struct iov_iter to; 37 loff_t pos = subreq->start + subreq->transferred; 38 size_t len = subreq->len - subreq->transferred; 39 int total, err; 40 41 iov_iter_xarray(&to, ITER_DEST, &rreq->mapping->i_pages, pos, len); 42 43 total = p9_client_read(fid, pos, &to, &err); 44 45 /* if we just extended the file size, any portion not in 46 * cache won't be on server and is zeroes */ 47 __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); 48 49 netfs_subreq_terminated(subreq, err ?: total, false); 50 } 51 52 /** 53 * v9fs_init_request - Initialise a read request 54 * @rreq: The read request 55 * @file: The file being read from 56 */ 57 static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) 58 { 59 struct inode *inode = file_inode(file); 60 struct v9fs_inode *v9inode = V9FS_I(inode); 61 struct p9_fid *fid = file->private_data; 62 63 BUG_ON(!fid); 64 65 /* we might need to read from a fid that was opened write-only 66 * for read-modify-write of page cache, use the writeback fid 67 * for that */ 68 if (rreq->origin == NETFS_READ_FOR_WRITE && 69 (fid->mode & O_ACCMODE) == O_WRONLY) { 70 fid = v9inode->writeback_fid; 71 BUG_ON(!fid); 72 } 73 74 p9_fid_get(fid); 75 rreq->netfs_priv = fid; 76 return 0; 77 } 78 79 /** 80 * v9fs_free_request - Cleanup request initialized by v9fs_init_rreq 81 * @rreq: The I/O request to clean up 82 */ 83 static void v9fs_free_request(struct netfs_io_request *rreq) 84 { 85 struct p9_fid *fid = rreq->netfs_priv; 86 87 p9_fid_put(fid); 88 } 89 90 /** 91 * v9fs_begin_cache_operation - Begin a cache operation for a read 92 * @rreq: The read request 93 */ 94 static int v9fs_begin_cache_operation(struct netfs_io_request *rreq) 95 { 96 #ifdef CONFIG_9P_FSCACHE 97 struct fscache_cookie *cookie = v9fs_inode_cookie(V9FS_I(rreq->inode)); 98 99 return fscache_begin_read_operation(&rreq->cache_resources, cookie); 100 #else 101 return -ENOBUFS; 102 #endif 103 } 104 105 const struct netfs_request_ops v9fs_req_ops = { 106 .init_request = v9fs_init_request, 107 .free_request = v9fs_free_request, 108 .begin_cache_operation = v9fs_begin_cache_operation, 109 .issue_read = v9fs_issue_read, 110 }; 111 112 /** 113 * v9fs_release_folio - release the private state associated with a folio 114 * @folio: The folio to be released 115 * @gfp: The caller's allocation restrictions 116 * 117 * Returns true if the page can be released, false otherwise. 118 */ 119 120 static bool v9fs_release_folio(struct folio *folio, gfp_t gfp) 121 { 122 struct inode *inode = folio_inode(folio); 123 124 if (folio_test_private(folio)) 125 return false; 126 #ifdef CONFIG_9P_FSCACHE 127 if (folio_test_fscache(folio)) { 128 if (current_is_kswapd() || !(gfp & __GFP_FS)) 129 return false; 130 folio_wait_fscache(folio); 131 } 132 #endif 133 fscache_note_page_release(v9fs_inode_cookie(V9FS_I(inode))); 134 return true; 135 } 136 137 static void v9fs_invalidate_folio(struct folio *folio, size_t offset, 138 size_t length) 139 { 140 folio_wait_fscache(folio); 141 } 142 143 static void v9fs_write_to_cache_done(void *priv, ssize_t transferred_or_error, 144 bool was_async) 145 { 146 struct v9fs_inode *v9inode = priv; 147 __le32 version; 148 149 if (IS_ERR_VALUE(transferred_or_error) && 150 transferred_or_error != -ENOBUFS) { 151 version = cpu_to_le32(v9inode->qid.version); 152 fscache_invalidate(v9fs_inode_cookie(v9inode), &version, 153 i_size_read(&v9inode->netfs.inode), 0); 154 } 155 } 156 157 static int v9fs_vfs_write_folio_locked(struct folio *folio) 158 { 159 struct inode *inode = folio_inode(folio); 160 struct v9fs_inode *v9inode = V9FS_I(inode); 161 struct fscache_cookie *cookie = v9fs_inode_cookie(v9inode); 162 loff_t start = folio_pos(folio); 163 loff_t i_size = i_size_read(inode); 164 struct iov_iter from; 165 size_t len = folio_size(folio); 166 int err; 167 168 if (start >= i_size) 169 return 0; /* Simultaneous truncation occurred */ 170 171 len = min_t(loff_t, i_size - start, len); 172 173 iov_iter_xarray(&from, ITER_SOURCE, &folio_mapping(folio)->i_pages, start, len); 174 175 /* We should have writeback_fid always set */ 176 BUG_ON(!v9inode->writeback_fid); 177 178 folio_wait_fscache(folio); 179 folio_start_writeback(folio); 180 181 p9_client_write(v9inode->writeback_fid, start, &from, &err); 182 183 if (err == 0 && 184 fscache_cookie_enabled(cookie) && 185 test_bit(FSCACHE_COOKIE_IS_CACHING, &cookie->flags)) { 186 folio_start_fscache(folio); 187 fscache_write_to_cache(v9fs_inode_cookie(v9inode), 188 folio_mapping(folio), start, len, i_size, 189 v9fs_write_to_cache_done, v9inode, 190 true); 191 } 192 193 folio_end_writeback(folio); 194 return err; 195 } 196 197 static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) 198 { 199 struct folio *folio = page_folio(page); 200 int retval; 201 202 p9_debug(P9_DEBUG_VFS, "folio %p\n", folio); 203 204 retval = v9fs_vfs_write_folio_locked(folio); 205 if (retval < 0) { 206 if (retval == -EAGAIN) { 207 folio_redirty_for_writepage(wbc, folio); 208 retval = 0; 209 } else { 210 mapping_set_error(folio_mapping(folio), retval); 211 } 212 } else 213 retval = 0; 214 215 folio_unlock(folio); 216 return retval; 217 } 218 219 static int v9fs_launder_folio(struct folio *folio) 220 { 221 int retval; 222 223 if (folio_clear_dirty_for_io(folio)) { 224 retval = v9fs_vfs_write_folio_locked(folio); 225 if (retval) 226 return retval; 227 } 228 folio_wait_fscache(folio); 229 return 0; 230 } 231 232 /** 233 * v9fs_direct_IO - 9P address space operation for direct I/O 234 * @iocb: target I/O control block 235 * @iter: The data/buffer to use 236 * 237 * The presence of v9fs_direct_IO() in the address space ops vector 238 * allowes open() O_DIRECT flags which would have failed otherwise. 239 * 240 * In the non-cached mode, we shunt off direct read and write requests before 241 * the VFS gets them, so this method should never be called. 242 * 243 * Direct IO is not 'yet' supported in the cached mode. Hence when 244 * this routine is called through generic_file_aio_read(), the read/write fails 245 * with an error. 246 * 247 */ 248 static ssize_t 249 v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 250 { 251 struct file *file = iocb->ki_filp; 252 loff_t pos = iocb->ki_pos; 253 ssize_t n; 254 int err = 0; 255 256 if (iov_iter_rw(iter) == WRITE) { 257 n = p9_client_write(file->private_data, pos, iter, &err); 258 if (n) { 259 struct inode *inode = file_inode(file); 260 loff_t i_size = i_size_read(inode); 261 262 if (pos + n > i_size) 263 inode_add_bytes(inode, pos + n - i_size); 264 } 265 } else { 266 n = p9_client_read(file->private_data, pos, iter, &err); 267 } 268 return n ? n : err; 269 } 270 271 static int v9fs_write_begin(struct file *filp, struct address_space *mapping, 272 loff_t pos, unsigned int len, 273 struct page **subpagep, void **fsdata) 274 { 275 int retval; 276 struct folio *folio; 277 struct v9fs_inode *v9inode = V9FS_I(mapping->host); 278 279 p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); 280 281 /* Prefetch area to be written into the cache if we're caching this 282 * file. We need to do this before we get a lock on the page in case 283 * there's more than one writer competing for the same cache block. 284 */ 285 retval = netfs_write_begin(&v9inode->netfs, filp, mapping, pos, len, &folio, fsdata); 286 if (retval < 0) 287 return retval; 288 289 *subpagep = &folio->page; 290 return retval; 291 } 292 293 static int v9fs_write_end(struct file *filp, struct address_space *mapping, 294 loff_t pos, unsigned int len, unsigned int copied, 295 struct page *subpage, void *fsdata) 296 { 297 loff_t last_pos = pos + copied; 298 struct folio *folio = page_folio(subpage); 299 struct inode *inode = mapping->host; 300 struct v9fs_inode *v9inode = V9FS_I(inode); 301 302 p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); 303 304 if (!folio_test_uptodate(folio)) { 305 if (unlikely(copied < len)) { 306 copied = 0; 307 goto out; 308 } 309 310 folio_mark_uptodate(folio); 311 } 312 313 /* 314 * No need to use i_size_read() here, the i_size 315 * cannot change under us because we hold the i_mutex. 316 */ 317 if (last_pos > inode->i_size) { 318 inode_add_bytes(inode, last_pos - inode->i_size); 319 i_size_write(inode, last_pos); 320 fscache_update_cookie(v9fs_inode_cookie(v9inode), NULL, &last_pos); 321 } 322 folio_mark_dirty(folio); 323 out: 324 folio_unlock(folio); 325 folio_put(folio); 326 327 return copied; 328 } 329 330 #ifdef CONFIG_9P_FSCACHE 331 /* 332 * Mark a page as having been made dirty and thus needing writeback. We also 333 * need to pin the cache object to write back to. 334 */ 335 static bool v9fs_dirty_folio(struct address_space *mapping, struct folio *folio) 336 { 337 struct v9fs_inode *v9inode = V9FS_I(mapping->host); 338 339 return fscache_dirty_folio(mapping, folio, v9fs_inode_cookie(v9inode)); 340 } 341 #else 342 #define v9fs_dirty_folio filemap_dirty_folio 343 #endif 344 345 const struct address_space_operations v9fs_addr_operations = { 346 .read_folio = netfs_read_folio, 347 .readahead = netfs_readahead, 348 .dirty_folio = v9fs_dirty_folio, 349 .writepage = v9fs_vfs_writepage, 350 .write_begin = v9fs_write_begin, 351 .write_end = v9fs_write_end, 352 .release_folio = v9fs_release_folio, 353 .invalidate_folio = v9fs_invalidate_folio, 354 .launder_folio = v9fs_launder_folio, 355 .direct_IO = v9fs_direct_IO, 356 }; 357