Commit | Line | Data |
---|---|---|
1f327613 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
147b31cf | 2 | /* |
147b31cf EVH |
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> | |
147b31cf EVH |
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> | |
147b31cf | 15 | #include <linux/pagemap.h> |
e8edc6e0 | 16 | #include <linux/sched.h> |
d7bdba1c | 17 | #include <linux/swap.h> |
e2e40f2c | 18 | #include <linux/uio.h> |
eb497943 | 19 | #include <linux/netfs.h> |
bd238fb4 LI |
20 | #include <net/9p/9p.h> |
21 | #include <net/9p/client.h> | |
80105ed2 | 22 | #include <trace/events/netfs.h> |
147b31cf | 23 | |
147b31cf | 24 | #include "v9fs.h" |
147b31cf | 25 | #include "v9fs_vfs.h" |
60e78d2c | 26 | #include "cache.h" |
7263cebe | 27 | #include "fid.h" |
147b31cf | 28 | |
80105ed2 DH |
29 | static void v9fs_upload_to_server(struct netfs_io_subrequest *subreq) |
30 | { | |
80105ed2 | 31 | struct p9_fid *fid = subreq->rreq->netfs_priv; |
252cf7b2 | 32 | int err, len; |
80105ed2 DH |
33 | |
34 | trace_netfs_sreq(subreq, netfs_sreq_trace_submit); | |
252cf7b2 DH |
35 | len = p9_client_write(fid, subreq->start, &subreq->io_iter, &err); |
36 | netfs_write_subrequest_terminated(subreq, len ?: err, false); | |
80105ed2 DH |
37 | } |
38 | ||
39 | static void v9fs_upload_to_server_worker(struct work_struct *work) | |
40 | { | |
41 | struct netfs_io_subrequest *subreq = | |
42 | container_of(work, struct netfs_io_subrequest, work); | |
43 | ||
44 | v9fs_upload_to_server(subreq); | |
45 | } | |
46 | ||
47 | /* | |
48 | * Set up write requests for a writeback slice. We need to add a write request | |
49 | * for each write we want to make. | |
50 | */ | |
51 | static void v9fs_create_write_requests(struct netfs_io_request *wreq, loff_t start, size_t len) | |
52 | { | |
53 | struct netfs_io_subrequest *subreq; | |
54 | ||
55 | subreq = netfs_create_write_request(wreq, NETFS_UPLOAD_TO_SERVER, | |
56 | start, len, v9fs_upload_to_server_worker); | |
57 | if (subreq) | |
58 | netfs_queue_write_request(subreq); | |
59 | } | |
60 | ||
147b31cf | 61 | /** |
f18a3785 | 62 | * v9fs_issue_read - Issue a read from 9P |
eb497943 | 63 | * @subreq: The read to make |
147b31cf | 64 | */ |
f18a3785 | 65 | static void v9fs_issue_read(struct netfs_io_subrequest *subreq) |
147b31cf | 66 | { |
6a19114b | 67 | struct netfs_io_request *rreq = subreq->rreq; |
eb497943 | 68 | struct p9_fid *fid = rreq->netfs_priv; |
eb497943 | 69 | int total, err; |
e03abc0c | 70 | |
80105ed2 DH |
71 | total = p9_client_read(fid, subreq->start + subreq->transferred, |
72 | &subreq->io_iter, &err); | |
19d1c326 DM |
73 | |
74 | /* if we just extended the file size, any portion not in | |
75 | * cache won't be on server and is zeroes */ | |
76 | __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); | |
77 | ||
eb497943 DH |
78 | netfs_subreq_terminated(subreq, err ?: total, false); |
79 | } | |
60e78d2c | 80 | |
eb497943 | 81 | /** |
80105ed2 | 82 | * v9fs_init_request - Initialise a request |
eb497943 DH |
83 | * @rreq: The read request |
84 | * @file: The file being read from | |
85 | */ | |
2de16041 | 86 | static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) |
eb497943 | 87 | { |
80105ed2 DH |
88 | struct p9_fid *fid; |
89 | bool writing = (rreq->origin == NETFS_READ_FOR_WRITE || | |
90 | rreq->origin == NETFS_WRITEBACK || | |
91 | rreq->origin == NETFS_WRITETHROUGH || | |
80105ed2 DH |
92 | rreq->origin == NETFS_UNBUFFERED_WRITE || |
93 | rreq->origin == NETFS_DIO_WRITE); | |
94 | ||
95 | if (file) { | |
96 | fid = file->private_data; | |
6c2c1e00 DH |
97 | if (!fid) |
98 | goto no_fid; | |
80105ed2 DH |
99 | p9_fid_get(fid); |
100 | } else { | |
101 | fid = v9fs_fid_find_inode(rreq->inode, writing, INVALID_UID, true); | |
6c2c1e00 DH |
102 | if (!fid) |
103 | goto no_fid; | |
80105ed2 | 104 | } |
b0017602 DM |
105 | |
106 | /* we might need to read from a fid that was opened write-only | |
107 | * for read-modify-write of page cache, use the writeback fid | |
108 | * for that */ | |
80105ed2 | 109 | WARN_ON(rreq->origin == NETFS_READ_FOR_WRITE && !(fid->mode & P9_ORDWR)); |
eb497943 | 110 | rreq->netfs_priv = fid; |
2de16041 | 111 | return 0; |
6c2c1e00 DH |
112 | |
113 | no_fid: | |
114 | WARN_ONCE(1, "folio expected an open fid inode->i_ino=%lx\n", | |
115 | rreq->inode->i_ino); | |
116 | return -EINVAL; | |
eb497943 | 117 | } |
147b31cf | 118 | |
eb497943 | 119 | /** |
40a81101 DH |
120 | * v9fs_free_request - Cleanup request initialized by v9fs_init_rreq |
121 | * @rreq: The I/O request to clean up | |
eb497943 | 122 | */ |
40a81101 | 123 | static void v9fs_free_request(struct netfs_io_request *rreq) |
eb497943 | 124 | { |
40a81101 | 125 | struct p9_fid *fid = rreq->netfs_priv; |
147b31cf | 126 | |
b48dbb99 | 127 | p9_fid_put(fid); |
eb497943 | 128 | } |
60e78d2c | 129 | |
bc899ee1 | 130 | const struct netfs_request_ops v9fs_req_ops = { |
6a19114b | 131 | .init_request = v9fs_init_request, |
40a81101 | 132 | .free_request = v9fs_free_request, |
f18a3785 | 133 | .issue_read = v9fs_issue_read, |
80105ed2 | 134 | .create_write_requests = v9fs_create_write_requests, |
eb497943 DH |
135 | }; |
136 | ||
f5e54d6e | 137 | const struct address_space_operations v9fs_addr_operations = { |
80105ed2 DH |
138 | .read_folio = netfs_read_folio, |
139 | .readahead = netfs_readahead, | |
140 | .dirty_folio = netfs_dirty_folio, | |
141 | .release_folio = netfs_release_folio, | |
142 | .invalidate_folio = netfs_invalidate_folio, | |
80105ed2 DH |
143 | .direct_IO = noop_direct_IO, |
144 | .writepages = netfs_writepages, | |
147b31cf | 145 | }; |