Linux Audio

Check our new training course

Loading...
v6.9.4
  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 */
 21static 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.  *_wbk will contain the last writeback key used or NULL
 33 * and we need to start from there if it's set.
 
 34 */
 35static int afs_get_writeback_key(struct afs_vnode *vnode,
 36				 struct afs_wb_key **_wbk)
 37{
 38	struct afs_wb_key *wbk = NULL;
 39	struct list_head *p;
 40	int ret = -ENOKEY, ret2;
 
 
 
 41
 42	spin_lock(&vnode->wb_lock);
 43	if (*_wbk)
 44		p = (*_wbk)->vnode_link.next;
 45	else
 46		p = vnode->wb_keys.next;
 47
 48	while (p != &vnode->wb_keys) {
 49		wbk = list_entry(p, struct afs_wb_key, vnode_link);
 50		_debug("wbk %u", key_serial(wbk->key));
 51		ret2 = key_validate(wbk->key);
 52		if (ret2 == 0) {
 53			refcount_inc(&wbk->usage);
 
 
 54			_debug("USE WB KEY %u", key_serial(wbk->key));
 55			break;
 56		}
 57
 58		wbk = NULL;
 59		if (ret == -ENOKEY)
 60			ret = ret2;
 61		p = p->next;
 62	}
 63
 64	spin_unlock(&vnode->wb_lock);
 65	if (*_wbk)
 66		afs_put_wb_key(*_wbk);
 67	*_wbk = wbk;
 68	return 0;
 69}
 70
 71static void afs_store_data_success(struct afs_operation *op)
 72{
 73	struct afs_vnode *vnode = op->file[0].vnode;
 74
 75	op->ctime = op->file[0].scb.status.mtime_client;
 76	afs_vnode_commit_status(op, &op->file[0]);
 77	if (!afs_op_error(op)) {
 78		if (!op->store.laundering)
 79			afs_pages_written_back(vnode, op->store.pos, op->store.size);
 80		afs_stat_v(vnode, n_stores);
 81		atomic_long_add(op->store.size, &afs_v2net(vnode)->n_store_bytes);
 82	}
 83}
 84
 85static const struct afs_operation_ops afs_store_data_operation = {
 86	.issue_afs_rpc	= afs_fs_store_data,
 87	.issue_yfs_rpc	= yfs_fs_store_data,
 88	.success	= afs_store_data_success,
 89};
 90
 91/*
 92 * write to a file
 
 93 */
 94static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t pos,
 95			  bool laundering)
 96{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 97	struct afs_operation *op;
 98	struct afs_wb_key *wbk = NULL;
 99	loff_t size = iov_iter_count(iter);
 
100	int ret = -ENOKEY;
101
102	_enter("%s{%llx:%llu.%u},%llx,%llx",
 
103	       vnode->volume->name,
104	       vnode->fid.vid,
105	       vnode->fid.vnode,
106	       vnode->fid.unique,
107	       size, pos);
108
109	ret = afs_get_writeback_key(vnode, &wbk);
110	if (ret) {
111		_leave(" = %d [no keys]", ret);
112		return ret;
 
 
 
113	}
 
114
115	op = afs_alloc_operation(wbk->key, vnode->volume);
116	if (IS_ERR(op)) {
117		afs_put_wb_key(wbk);
118		return -ENOMEM;
119	}
120
121	afs_op_set_vnode(op, 0, vnode);
122	op->file[0].dv_delta = 1;
123	op->file[0].modification = true;
124	op->store.pos = pos;
125	op->store.size = size;
126	op->store.laundering = laundering;
127	op->flags |= AFS_OPERATION_UNINTR;
128	op->ops = &afs_store_data_operation;
129
130try_next_key:
131	afs_begin_vnode_operation(op);
132
133	op->store.write_iter = iter;
134	op->store.i_size = max(pos + size, vnode->netfs.remote_i_size);
135	op->mtime = inode_get_mtime(&vnode->netfs.inode);
136
137	afs_wait_for_operation(op);
138
139	switch (afs_op_error(op)) {
 
 
 
140	case -EACCES:
141	case -EPERM:
142	case -ENOKEY:
143	case -EKEYEXPIRED:
144	case -EKEYREJECTED:
145	case -EKEYREVOKED:
146		_debug("next");
147
148		ret = afs_get_writeback_key(vnode, &wbk);
149		if (ret == 0) {
150			key_put(op->key);
151			op->key = key_get(wbk->key);
152			goto try_next_key;
153		}
154		break;
155	}
156
157	afs_put_wb_key(wbk);
158	_leave(" = %d", afs_op_error(op));
159	return afs_put_operation(op);
160}
161
162static void afs_upload_to_server(struct netfs_io_subrequest *subreq)
163{
164	struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode);
165	ssize_t ret;
166
167	_enter("%x[%x],%zx",
168	       subreq->rreq->debug_id, subreq->debug_index, subreq->io_iter.count);
169
170	trace_netfs_sreq(subreq, netfs_sreq_trace_submit);
171	ret = afs_store_data(vnode, &subreq->io_iter, subreq->start,
172			     subreq->rreq->origin == NETFS_LAUNDER_WRITE);
173	netfs_write_subrequest_terminated(subreq, ret < 0 ? ret : subreq->len,
174					  false);
175}
176
177static void afs_upload_to_server_worker(struct work_struct *work)
 
 
 
 
178{
179	struct netfs_io_subrequest *subreq =
180		container_of(work, struct netfs_io_subrequest, work);
181
182	afs_upload_to_server(subreq);
183}
184
185/*
186 * Set up write requests for a writeback slice.  We need to add a write request
187 * for each write we want to make.
188 */
189void afs_create_write_requests(struct netfs_io_request *wreq, loff_t start, size_t len)
190{
191	struct netfs_io_subrequest *subreq;
192
193	_enter("%x,%llx-%llx", wreq->debug_id, start, start + len);
194
195	subreq = netfs_create_write_request(wreq, NETFS_UPLOAD_TO_SERVER,
196					    start, len, afs_upload_to_server_worker);
197	if (subreq)
198		netfs_queue_write_request(subreq);
 
 
 
 
 
 
 
 
199}
200
201/*
202 * write some of the pending data back to the server
203 */
204int afs_writepages(struct address_space *mapping, struct writeback_control *wbc)
205{
206	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
207	int ret;
208
209	/* We have to be careful as we can end up racing with setattr()
210	 * truncating the pagecache since the caller doesn't take a lock here
211	 * to prevent it.
212	 */
213	if (wbc->sync_mode == WB_SYNC_ALL)
214		down_read(&vnode->validate_lock);
215	else if (!down_read_trylock(&vnode->validate_lock))
216		return 0;
217
218	ret = netfs_writepages(mapping, wbc);
219	up_read(&vnode->validate_lock);
220	return ret;
221}
222
223/*
224 * flush any dirty pages for this process, and check for write errors.
225 * - the return status from this call provides a reliable indication of
226 *   whether any write errors occurred for this process.
227 */
228int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
229{
230	struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
231	struct afs_file *af = file->private_data;
232	int ret;
233
234	_enter("{%llx:%llu},{n=%pD},%d",
235	       vnode->fid.vid, vnode->fid.vnode, file,
236	       datasync);
237
238	ret = afs_validate(vnode, af->key);
239	if (ret < 0)
240		return ret;
241
242	return file_write_and_wait_range(file, start, end);
243}
244
245/*
246 * notification that a previously read-only page is about to become writable
247 * - if it returns an error, the caller will deliver a bus error signal
248 */
249vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
250{
251	struct file *file = vmf->vma->vm_file;
252
253	if (afs_validate(AFS_FS_I(file_inode(file)), afs_file_key(file)) < 0)
254		return VM_FAULT_SIGBUS;
255	return netfs_page_mkwrite(vmf, NULL);
256}
257
258/*
259 * Prune the keys cached for writeback.  The caller must hold vnode->wb_lock.
260 */
261void afs_prune_wb_keys(struct afs_vnode *vnode)
262{
263	LIST_HEAD(graveyard);
264	struct afs_wb_key *wbk, *tmp;
265
266	/* Discard unused keys */
267	spin_lock(&vnode->wb_lock);
268
269	if (!mapping_tagged(&vnode->netfs.inode.i_data, PAGECACHE_TAG_WRITEBACK) &&
270	    !mapping_tagged(&vnode->netfs.inode.i_data, PAGECACHE_TAG_DIRTY)) {
271		list_for_each_entry_safe(wbk, tmp, &vnode->wb_keys, vnode_link) {
272			if (refcount_read(&wbk->usage) == 1)
273				list_move(&wbk->vnode_link, &graveyard);
274		}
275	}
276
277	spin_unlock(&vnode->wb_lock);
278
279	while (!list_empty(&graveyard)) {
280		wbk = list_entry(graveyard.next, struct afs_wb_key, vnode_link);
281		list_del(&wbk->vnode_link);
282		afs_put_wb_key(wbk);
283	}
284}
v6.13.7
  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 */
 21static 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 */
 36static 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(wreq->inode);
 40
 41	key_put(wreq->netfs_priv);
 42	wreq->netfs_priv = NULL;
 43	wreq->netfs_priv2 = NULL;
 44
 45	spin_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(wbk->key) == 0) {
 
 54			refcount_inc(&wbk->usage);
 55			wreq->netfs_priv = key_get(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(&vnode->wb_lock);
 63
 64	afs_put_wb_key(old);
 
 
 65}
 66
 67static 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, op->store.pos, op->store.size);
 
 75		afs_stat_v(vnode, n_stores);
 76		atomic_long_add(op->store.size, &afs_v2net(vnode)->n_store_bytes);
 77	}
 78}
 79
 80static 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 */
 90void 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 */
103static 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(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, false);
124
125	if (!subreq->retry_count) {
126		set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
127		return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
128	}
129#endif
130
131	op = afs_alloc_operation(wreq->netfs_priv, vnode->volume);
132	if (IS_ERR(op))
133		return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
 
 
134
135	afs_op_set_vnode(op, 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(&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, &subreq->flags);
 
 
 
166		break;
167	}
168
169	netfs_write_subrequest_terminated(subreq, ret < 0 ? ret : subreq->len, false);
 
 
170}
171
172void afs_issue_write(struct netfs_io_subrequest *subreq)
173{
174	subreq->work.func = afs_issue_write_worker;
175	if (!queue_work(system_unbound_wq, &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 */
183void afs_begin_writeback(struct netfs_io_request *wreq)
184{
185	afs_get_writeback_key(wreq);
186	wreq->io_streams[0].avail = true;
 
 
187}
188
189/*
190 * Prepare to retry the writes in request.  Use this to try rotating the
191 * available writeback keys.
192 */
193void 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 (subreq->error) {
200	case -EACCES:
201	case -EPERM:
202	case -ENOKEY:
203	case -EKEYEXPIRED:
204	case -EKEYREJECTED:
205	case -EKEYREVOKED:
206		afs_get_writeback_key(wreq);
207		if (!wreq->netfs_priv)
208			stream->failed = true;
209		break;
210	}
211}
212
213/*
214 * write some of the pending data back to the server
215 */
216int afs_writepages(struct address_space *mapping, struct writeback_control *wbc)
217{
218	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
219	int ret;
220
221	/* We have to be careful as we can end up racing with setattr()
222	 * truncating the pagecache since the caller doesn't take a lock here
223	 * to prevent it.
224	 */
225	if (wbc->sync_mode == WB_SYNC_ALL)
226		down_read(&vnode->validate_lock);
227	else if (!down_read_trylock(&vnode->validate_lock))
228		return 0;
229
230	ret = netfs_writepages(mapping, wbc);
231	up_read(&vnode->validate_lock);
232	return ret;
233}
234
235/*
236 * flush any dirty pages for this process, and check for write errors.
237 * - the return status from this call provides a reliable indication of
238 *   whether any write errors occurred for this process.
239 */
240int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
241{
242	struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
243	struct afs_file *af = file->private_data;
244	int ret;
245
246	_enter("{%llx:%llu},{n=%pD},%d",
247	       vnode->fid.vid, vnode->fid.vnode, file,
248	       datasync);
249
250	ret = afs_validate(vnode, af->key);
251	if (ret < 0)
252		return ret;
253
254	return file_write_and_wait_range(file, start, end);
255}
256
257/*
258 * notification that a previously read-only page is about to become writable
259 * - if it returns an error, the caller will deliver a bus error signal
260 */
261vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
262{
263	struct file *file = vmf->vma->vm_file;
264
265	if (afs_validate(AFS_FS_I(file_inode(file)), afs_file_key(file)) < 0)
266		return VM_FAULT_SIGBUS;
267	return netfs_page_mkwrite(vmf, NULL);
268}
269
270/*
271 * Prune the keys cached for writeback.  The caller must hold vnode->wb_lock.
272 */
273void afs_prune_wb_keys(struct afs_vnode *vnode)
274{
275	LIST_HEAD(graveyard);
276	struct afs_wb_key *wbk, *tmp;
277
278	/* Discard unused keys */
279	spin_lock(&vnode->wb_lock);
280
281	if (!mapping_tagged(&vnode->netfs.inode.i_data, PAGECACHE_TAG_WRITEBACK) &&
282	    !mapping_tagged(&vnode->netfs.inode.i_data, PAGECACHE_TAG_DIRTY)) {
283		list_for_each_entry_safe(wbk, tmp, &vnode->wb_keys, vnode_link) {
284			if (refcount_read(&wbk->usage) == 1)
285				list_move(&wbk->vnode_link, &graveyard);
286		}
287	}
288
289	spin_unlock(&vnode->wb_lock);
290
291	while (!list_empty(&graveyard)) {
292		wbk = list_entry(graveyard.next, struct afs_wb_key, vnode_link);
293		list_del(&wbk->vnode_link);
294		afs_put_wb_key(wbk);
295	}
296}