| 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* handling of writes to regular files and writing back to the server |
| 3 | * |
| 4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
| 5 | * Written by David Howells (dhowells@redhat.com) |
| 6 | */ |
| 7 | |
| 8 | #include <linux/backing-dev.h> |
| 9 | #include <linux/slab.h> |
| 10 | #include <linux/fs.h> |
| 11 | #include <linux/pagemap.h> |
| 12 | #include <linux/writeback.h> |
| 13 | #include <linux/pagevec.h> |
| 14 | #include <linux/netfs.h> |
| 15 | #include <trace/events/netfs.h> |
| 16 | #include "internal.h" |
| 17 | |
| 18 | /* |
| 19 | * completion of write to server |
| 20 | */ |
| 21 | static void afs_pages_written_back(struct afs_vnode *vnode, loff_t start, unsigned int len) |
| 22 | { |
| 23 | _enter("{%llx:%llu},{%x @%llx}" , |
| 24 | vnode->fid.vid, vnode->fid.vnode, len, start); |
| 25 | |
| 26 | afs_prune_wb_keys(vnode); |
| 27 | _leave("" ); |
| 28 | } |
| 29 | |
| 30 | /* |
| 31 | * Find a key to use for the writeback. We cached the keys used to author the |
| 32 | * writes on the vnode. wreq->netfs_priv2 will contain the last writeback key |
| 33 | * record used or NULL and we need to start from there if it's set. |
| 34 | * wreq->netfs_priv will be set to the key itself or NULL. |
| 35 | */ |
| 36 | static void afs_get_writeback_key(struct netfs_io_request *wreq) |
| 37 | { |
| 38 | struct afs_wb_key *wbk, *old = wreq->netfs_priv2; |
| 39 | struct afs_vnode *vnode = AFS_FS_I(inode: wreq->inode); |
| 40 | |
| 41 | key_put(key: wreq->netfs_priv); |
| 42 | wreq->netfs_priv = NULL; |
| 43 | wreq->netfs_priv2 = NULL; |
| 44 | |
| 45 | spin_lock(lock: &vnode->wb_lock); |
| 46 | if (old) |
| 47 | wbk = list_next_entry(old, vnode_link); |
| 48 | else |
| 49 | wbk = list_first_entry(&vnode->wb_keys, struct afs_wb_key, vnode_link); |
| 50 | |
| 51 | list_for_each_entry_from(wbk, &vnode->wb_keys, vnode_link) { |
| 52 | _debug("wbk %u" , key_serial(wbk->key)); |
| 53 | if (key_validate(key: wbk->key) == 0) { |
| 54 | refcount_inc(r: &wbk->usage); |
| 55 | wreq->netfs_priv = key_get(key: wbk->key); |
| 56 | wreq->netfs_priv2 = wbk; |
| 57 | _debug("USE WB KEY %u" , key_serial(wbk->key)); |
| 58 | break; |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | spin_unlock(lock: &vnode->wb_lock); |
| 63 | |
| 64 | afs_put_wb_key(old); |
| 65 | } |
| 66 | |
| 67 | static void afs_store_data_success(struct afs_operation *op) |
| 68 | { |
| 69 | struct afs_vnode *vnode = op->file[0].vnode; |
| 70 | |
| 71 | op->ctime = op->file[0].scb.status.mtime_client; |
| 72 | afs_vnode_commit_status(op, &op->file[0]); |
| 73 | if (!afs_op_error(op)) { |
| 74 | afs_pages_written_back(vnode, start: op->store.pos, len: op->store.size); |
| 75 | afs_stat_v(vnode, n_stores); |
| 76 | atomic_long_add(i: op->store.size, v: &afs_v2net(vnode)->n_store_bytes); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | static const struct afs_operation_ops afs_store_data_operation = { |
| 81 | .issue_afs_rpc = afs_fs_store_data, |
| 82 | .issue_yfs_rpc = yfs_fs_store_data, |
| 83 | .success = afs_store_data_success, |
| 84 | }; |
| 85 | |
| 86 | /* |
| 87 | * Prepare a subrequest to write to the server. This sets the max_len |
| 88 | * parameter. |
| 89 | */ |
| 90 | void afs_prepare_write(struct netfs_io_subrequest *subreq) |
| 91 | { |
| 92 | struct netfs_io_stream *stream = &subreq->rreq->io_streams[subreq->stream_nr]; |
| 93 | |
| 94 | //if (test_bit(NETFS_SREQ_RETRYING, &subreq->flags)) |
| 95 | // subreq->max_len = 512 * 1024; |
| 96 | //else |
| 97 | stream->sreq_max_len = 256 * 1024 * 1024; |
| 98 | } |
| 99 | |
| 100 | /* |
| 101 | * Issue a subrequest to write to the server. |
| 102 | */ |
| 103 | static void afs_issue_write_worker(struct work_struct *work) |
| 104 | { |
| 105 | struct netfs_io_subrequest *subreq = container_of(work, struct netfs_io_subrequest, work); |
| 106 | struct netfs_io_request *wreq = subreq->rreq; |
| 107 | struct afs_operation *op; |
| 108 | struct afs_vnode *vnode = AFS_FS_I(inode: wreq->inode); |
| 109 | unsigned long long pos = subreq->start + subreq->transferred; |
| 110 | size_t len = subreq->len - subreq->transferred; |
| 111 | int ret = -ENOKEY; |
| 112 | |
| 113 | _enter("R=%x[%x],%s{%llx:%llu.%u},%llx,%zx" , |
| 114 | wreq->debug_id, subreq->debug_index, |
| 115 | vnode->volume->name, |
| 116 | vnode->fid.vid, |
| 117 | vnode->fid.vnode, |
| 118 | vnode->fid.unique, |
| 119 | pos, len); |
| 120 | |
| 121 | #if 0 // Error injection |
| 122 | if (subreq->debug_index == 3) |
| 123 | return netfs_write_subrequest_terminated(subreq, -ENOANO); |
| 124 | |
| 125 | if (!subreq->retry_count) { |
| 126 | set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags); |
| 127 | return netfs_write_subrequest_terminated(subreq, -EAGAIN); |
| 128 | } |
| 129 | #endif |
| 130 | |
| 131 | op = afs_alloc_operation(wreq->netfs_priv, vnode->volume); |
| 132 | if (IS_ERR(ptr: op)) |
| 133 | return netfs_write_subrequest_terminated(op: subreq, transferred_or_error: -EAGAIN); |
| 134 | |
| 135 | afs_op_set_vnode(op, n: 0, vnode); |
| 136 | op->file[0].dv_delta = 1; |
| 137 | op->file[0].modification = true; |
| 138 | op->store.pos = pos; |
| 139 | op->store.size = len; |
| 140 | op->flags |= AFS_OPERATION_UNINTR; |
| 141 | op->ops = &afs_store_data_operation; |
| 142 | |
| 143 | afs_begin_vnode_operation(op); |
| 144 | |
| 145 | op->store.write_iter = &subreq->io_iter; |
| 146 | op->store.i_size = umax(pos + len, vnode->netfs.remote_i_size); |
| 147 | op->mtime = inode_get_mtime(inode: &vnode->netfs.inode); |
| 148 | |
| 149 | afs_wait_for_operation(op); |
| 150 | ret = afs_put_operation(op); |
| 151 | switch (ret) { |
| 152 | case 0: |
| 153 | __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 154 | break; |
| 155 | case -EACCES: |
| 156 | case -EPERM: |
| 157 | case -ENOKEY: |
| 158 | case -EKEYEXPIRED: |
| 159 | case -EKEYREJECTED: |
| 160 | case -EKEYREVOKED: |
| 161 | /* If there are more keys we can try, use the retry algorithm |
| 162 | * to rotate the keys. |
| 163 | */ |
| 164 | if (wreq->netfs_priv2) |
| 165 | set_bit(NETFS_SREQ_NEED_RETRY, addr: &subreq->flags); |
| 166 | break; |
| 167 | } |
| 168 | |
| 169 | netfs_write_subrequest_terminated(op: subreq, transferred_or_error: ret < 0 ? ret : subreq->len); |
| 170 | } |
| 171 | |
| 172 | void afs_issue_write(struct netfs_io_subrequest *subreq) |
| 173 | { |
| 174 | subreq->work.func = afs_issue_write_worker; |
| 175 | if (!queue_work(wq: system_dfl_wq, work: &subreq->work)) |
| 176 | WARN_ON_ONCE(1); |
| 177 | } |
| 178 | |
| 179 | /* |
| 180 | * Writeback calls this when it finds a folio that needs uploading. This isn't |
| 181 | * called if writeback only has copy-to-cache to deal with. |
| 182 | */ |
| 183 | void afs_begin_writeback(struct netfs_io_request *wreq) |
| 184 | { |
| 185 | if (S_ISREG(wreq->inode->i_mode)) |
| 186 | afs_get_writeback_key(wreq); |
| 187 | } |
| 188 | |
| 189 | /* |
| 190 | * Prepare to retry the writes in request. Use this to try rotating the |
| 191 | * available writeback keys. |
| 192 | */ |
| 193 | void afs_retry_request(struct netfs_io_request *wreq, struct netfs_io_stream *stream) |
| 194 | { |
| 195 | struct netfs_io_subrequest *subreq = |
| 196 | list_first_entry(&stream->subrequests, |
| 197 | struct netfs_io_subrequest, rreq_link); |
| 198 | |
| 199 | switch (wreq->origin) { |
| 200 | case NETFS_READAHEAD: |
| 201 | case NETFS_READPAGE: |
| 202 | case NETFS_READ_GAPS: |
| 203 | case NETFS_READ_SINGLE: |
| 204 | case NETFS_READ_FOR_WRITE: |
| 205 | case NETFS_UNBUFFERED_READ: |
| 206 | case NETFS_DIO_READ: |
| 207 | return; |
| 208 | default: |
| 209 | break; |
| 210 | } |
| 211 | |
| 212 | switch (subreq->error) { |
| 213 | case -EACCES: |
| 214 | case -EPERM: |
| 215 | case -ENOKEY: |
| 216 | case -EKEYEXPIRED: |
| 217 | case -EKEYREJECTED: |
| 218 | case -EKEYREVOKED: |
| 219 | afs_get_writeback_key(wreq); |
| 220 | if (!wreq->netfs_priv) |
| 221 | stream->failed = true; |
| 222 | break; |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | /* |
| 227 | * write some of the pending data back to the server |
| 228 | */ |
| 229 | int afs_writepages(struct address_space *mapping, struct writeback_control *wbc) |
| 230 | { |
| 231 | struct afs_vnode *vnode = AFS_FS_I(inode: mapping->host); |
| 232 | int ret; |
| 233 | |
| 234 | /* We have to be careful as we can end up racing with setattr() |
| 235 | * truncating the pagecache since the caller doesn't take a lock here |
| 236 | * to prevent it. |
| 237 | */ |
| 238 | if (wbc->sync_mode == WB_SYNC_ALL) |
| 239 | down_read(sem: &vnode->validate_lock); |
| 240 | else if (!down_read_trylock(sem: &vnode->validate_lock)) |
| 241 | return 0; |
| 242 | |
| 243 | ret = netfs_writepages(mapping, wbc); |
| 244 | up_read(sem: &vnode->validate_lock); |
| 245 | return ret; |
| 246 | } |
| 247 | |
| 248 | /* |
| 249 | * flush any dirty pages for this process, and check for write errors. |
| 250 | * - the return status from this call provides a reliable indication of |
| 251 | * whether any write errors occurred for this process. |
| 252 | */ |
| 253 | int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
| 254 | { |
| 255 | struct afs_vnode *vnode = AFS_FS_I(inode: file_inode(f: file)); |
| 256 | struct afs_file *af = file->private_data; |
| 257 | int ret; |
| 258 | |
| 259 | _enter("{%llx:%llu},{n=%pD},%d" , |
| 260 | vnode->fid.vid, vnode->fid.vnode, file, |
| 261 | datasync); |
| 262 | |
| 263 | ret = afs_validate(vnode, key: af->key); |
| 264 | if (ret < 0) |
| 265 | return ret; |
| 266 | |
| 267 | return file_write_and_wait_range(file, start, end); |
| 268 | } |
| 269 | |
| 270 | /* |
| 271 | * notification that a previously read-only page is about to become writable |
| 272 | * - if it returns an error, the caller will deliver a bus error signal |
| 273 | */ |
| 274 | vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) |
| 275 | { |
| 276 | struct file *file = vmf->vma->vm_file; |
| 277 | |
| 278 | if (afs_validate(vnode: AFS_FS_I(inode: file_inode(f: file)), key: afs_file_key(file)) < 0) |
| 279 | return VM_FAULT_SIGBUS; |
| 280 | return netfs_page_mkwrite(vmf, NULL); |
| 281 | } |
| 282 | |
| 283 | /* |
| 284 | * Prune the keys cached for writeback. The caller must hold vnode->wb_lock. |
| 285 | */ |
| 286 | void afs_prune_wb_keys(struct afs_vnode *vnode) |
| 287 | { |
| 288 | LIST_HEAD(graveyard); |
| 289 | struct afs_wb_key *wbk, *tmp; |
| 290 | |
| 291 | /* Discard unused keys */ |
| 292 | spin_lock(lock: &vnode->wb_lock); |
| 293 | |
| 294 | if (!mapping_tagged(mapping: &vnode->netfs.inode.i_data, PAGECACHE_TAG_WRITEBACK) && |
| 295 | !mapping_tagged(mapping: &vnode->netfs.inode.i_data, PAGECACHE_TAG_DIRTY)) { |
| 296 | list_for_each_entry_safe(wbk, tmp, &vnode->wb_keys, vnode_link) { |
| 297 | if (refcount_read(r: &wbk->usage) == 1) |
| 298 | list_move(list: &wbk->vnode_link, head: &graveyard); |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | spin_unlock(lock: &vnode->wb_lock); |
| 303 | |
| 304 | while (!list_empty(head: &graveyard)) { |
| 305 | wbk = list_entry(graveyard.next, struct afs_wb_key, vnode_link); |
| 306 | list_del(entry: &wbk->vnode_link); |
| 307 | afs_put_wb_key(wbk); |
| 308 | } |
| 309 | } |
| 310 | |