Skip to content

Commit 1ecb146

Browse files
committed
netfs, afs: Use writeback retry to deal with alternate keys
Use a hook in the new writeback code's retry algorithm to rotate the keys once all the outstanding subreqs have failed rather than doing it separately on each subreq. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org
1 parent d41ca44 commit 1ecb146

File tree

5 files changed

+104
-100
lines changed

5 files changed

+104
-100
lines changed

fs/afs/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len,
368368
static void afs_free_request(struct netfs_io_request *rreq)
369369
{
370370
key_put(rreq->netfs_priv);
371+
afs_put_wb_key(rreq->netfs_priv2);
371372
}
372373

373374
static void afs_update_i_size(struct inode *inode, loff_t new_i_size)

fs/afs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ extern int afs_check_volume_status(struct afs_volume *, struct afs_operation *);
16011601
void afs_prepare_write(struct netfs_io_subrequest *subreq);
16021602
void afs_issue_write(struct netfs_io_subrequest *subreq);
16031603
void afs_begin_writeback(struct netfs_io_request *wreq);
1604+
void afs_retry_request(struct netfs_io_request *wreq, struct netfs_io_stream *stream);
16041605
extern int afs_writepages(struct address_space *, struct writeback_control *);
16051606
extern int afs_fsync(struct file *, loff_t, loff_t, int);
16061607
extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf);

fs/afs/write.c

Lines changed: 93 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -29,43 +29,39 @@ static void afs_pages_written_back(struct afs_vnode *vnode, loff_t start, unsign
2929

3030
/*
3131
* 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.
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.
3435
*/
35-
static int afs_get_writeback_key(struct afs_vnode *vnode,
36-
struct afs_wb_key **_wbk)
36+
static void afs_get_writeback_key(struct netfs_io_request *wreq)
3737
{
38-
struct afs_wb_key *wbk = NULL;
39-
struct list_head *p;
40-
int ret = -ENOKEY, ret2;
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;
4144

4245
spin_lock(&vnode->wb_lock);
43-
if (*_wbk)
44-
p = (*_wbk)->vnode_link.next;
46+
if (old)
47+
wbk = list_next_entry(old, vnode_link);
4548
else
46-
p = vnode->wb_keys.next;
49+
wbk = list_first_entry(&vnode->wb_keys, struct afs_wb_key, vnode_link);
4750

48-
while (p != &vnode->wb_keys) {
49-
wbk = list_entry(p, struct afs_wb_key, vnode_link);
51+
list_for_each_entry_from(wbk, &vnode->wb_keys, vnode_link) {
5052
_debug("wbk %u", key_serial(wbk->key));
51-
ret2 = key_validate(wbk->key);
52-
if (ret2 == 0) {
53+
if (key_validate(wbk->key) == 0) {
5354
refcount_inc(&wbk->usage);
55+
wreq->netfs_priv = key_get(wbk->key);
56+
wreq->netfs_priv2 = wbk;
5457
_debug("USE WB KEY %u", key_serial(wbk->key));
5558
break;
5659
}
57-
58-
wbk = NULL;
59-
if (ret == -ENOKEY)
60-
ret = ret2;
61-
p = p->next;
6260
}
6361

6462
spin_unlock(&vnode->wb_lock);
65-
if (*_wbk)
66-
afs_put_wb_key(*_wbk);
67-
*_wbk = wbk;
68-
return 0;
63+
64+
afs_put_wb_key(old);
6965
}
7066

7167
static void afs_store_data_success(struct afs_operation *op)
@@ -88,72 +84,91 @@ static const struct afs_operation_ops afs_store_data_operation = {
8884
};
8985

9086
/*
91-
* write to a file
87+
* Prepare a subrequest to write to the server. This sets the max_len
88+
* parameter.
9289
*/
93-
static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t pos)
90+
void afs_prepare_write(struct netfs_io_subrequest *subreq)
9491
{
92+
//if (test_bit(NETFS_SREQ_RETRYING, &subreq->flags))
93+
// subreq->max_len = 512 * 1024;
94+
//else
95+
subreq->max_len = 256 * 1024 * 1024;
96+
}
97+
98+
/*
99+
* Issue a subrequest to write to the server.
100+
*/
101+
static void afs_issue_write_worker(struct work_struct *work)
102+
{
103+
struct netfs_io_subrequest *subreq = container_of(work, struct netfs_io_subrequest, work);
104+
struct netfs_io_request *wreq = subreq->rreq;
95105
struct afs_operation *op;
96-
struct afs_wb_key *wbk = NULL;
97-
loff_t size = iov_iter_count(iter);
106+
struct afs_vnode *vnode = AFS_FS_I(wreq->inode);
107+
unsigned long long pos = subreq->start + subreq->transferred;
108+
size_t len = subreq->len - subreq->transferred;
98109
int ret = -ENOKEY;
99110

100-
_enter("%s{%llx:%llu.%u},%llx,%llx",
111+
_enter("R=%x[%x],%s{%llx:%llu.%u},%llx,%zx",
112+
wreq->debug_id, subreq->debug_index,
101113
vnode->volume->name,
102114
vnode->fid.vid,
103115
vnode->fid.vnode,
104116
vnode->fid.unique,
105-
size, pos);
117+
pos, len);
106118

107-
ret = afs_get_writeback_key(vnode, &wbk);
108-
if (ret) {
109-
_leave(" = %d [no keys]", ret);
110-
return ret;
111-
}
119+
#if 0 // Error injection
120+
if (subreq->debug_index == 3)
121+
return netfs_write_subrequest_terminated(subreq, -ENOANO, false);
112122

113-
op = afs_alloc_operation(wbk->key, vnode->volume);
114-
if (IS_ERR(op)) {
115-
afs_put_wb_key(wbk);
116-
return -ENOMEM;
123+
if (!test_bit(NETFS_SREQ_RETRYING, &subreq->flags)) {
124+
set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
125+
return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
117126
}
127+
#endif
128+
129+
op = afs_alloc_operation(wreq->netfs_priv, vnode->volume);
130+
if (IS_ERR(op))
131+
return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
118132

119133
afs_op_set_vnode(op, 0, vnode);
120-
op->file[0].dv_delta = 1;
134+
op->file[0].dv_delta = 1;
121135
op->file[0].modification = true;
122-
op->store.pos = pos;
123-
op->store.size = size;
124-
op->flags |= AFS_OPERATION_UNINTR;
125-
op->ops = &afs_store_data_operation;
136+
op->store.pos = pos;
137+
op->store.size = len;
138+
op->flags |= AFS_OPERATION_UNINTR;
139+
op->ops = &afs_store_data_operation;
126140

127-
try_next_key:
128141
afs_begin_vnode_operation(op);
129142

130-
op->store.write_iter = iter;
131-
op->store.i_size = max(pos + size, vnode->netfs.remote_i_size);
132-
op->mtime = inode_get_mtime(&vnode->netfs.inode);
143+
op->store.write_iter = &subreq->io_iter;
144+
op->store.i_size = umax(pos + len, vnode->netfs.remote_i_size);
145+
op->mtime = inode_get_mtime(&vnode->netfs.inode);
133146

134147
afs_wait_for_operation(op);
135-
136-
switch (afs_op_error(op)) {
148+
ret = afs_put_operation(op);
149+
switch (ret) {
137150
case -EACCES:
138151
case -EPERM:
139152
case -ENOKEY:
140153
case -EKEYEXPIRED:
141154
case -EKEYREJECTED:
142155
case -EKEYREVOKED:
143-
_debug("next");
144-
145-
ret = afs_get_writeback_key(vnode, &wbk);
146-
if (ret == 0) {
147-
key_put(op->key);
148-
op->key = key_get(wbk->key);
149-
goto try_next_key;
150-
}
156+
/* If there are more keys we can try, use the retry algorithm
157+
* to rotate the keys.
158+
*/
159+
if (wreq->netfs_priv2)
160+
set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
151161
break;
152162
}
153163

154-
afs_put_wb_key(wbk);
155-
_leave(" = %d", afs_op_error(op));
156-
return afs_put_operation(op);
164+
netfs_write_subrequest_terminated(subreq, ret < 0 ? ret : subreq->len, false);
165+
}
166+
167+
void afs_issue_write(struct netfs_io_subrequest *subreq)
168+
{
169+
subreq->work.func = afs_issue_write_worker;
170+
if (!queue_work(system_unbound_wq, &subreq->work))
171+
WARN_ON_ONCE(1);
157172
}
158173

159174
/*
@@ -162,52 +177,32 @@ static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t
162177
*/
163178
void afs_begin_writeback(struct netfs_io_request *wreq)
164179
{
180+
afs_get_writeback_key(wreq);
165181
wreq->io_streams[0].avail = true;
166182
}
167183

168184
/*
169-
* Prepare a subrequest to write to the server. This sets the max_len
170-
* parameter.
171-
*/
172-
void afs_prepare_write(struct netfs_io_subrequest *subreq)
173-
{
174-
//if (test_bit(NETFS_SREQ_RETRYING, &subreq->flags))
175-
// subreq->max_len = 512 * 1024;
176-
//else
177-
subreq->max_len = 256 * 1024 * 1024;
178-
}
179-
180-
/*
181-
* Issue a subrequest to write to the server.
185+
* Prepare to retry the writes in request. Use this to try rotating the
186+
* available writeback keys.
182187
*/
183-
static void afs_issue_write_worker(struct work_struct *work)
188+
void afs_retry_request(struct netfs_io_request *wreq, struct netfs_io_stream *stream)
184189
{
185-
struct netfs_io_subrequest *subreq = container_of(work, struct netfs_io_subrequest, work);
186-
struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode);
187-
ssize_t ret;
188-
189-
_enter("%x[%x],%zx",
190-
subreq->rreq->debug_id, subreq->debug_index, subreq->io_iter.count);
191-
192-
#if 0 // Error injection
193-
if (subreq->debug_index == 3)
194-
return netfs_write_subrequest_terminated(subreq, -ENOANO, false);
190+
struct netfs_io_subrequest *subreq =
191+
list_first_entry(&stream->subrequests,
192+
struct netfs_io_subrequest, rreq_link);
195193

196-
if (!test_bit(NETFS_SREQ_RETRYING, &subreq->flags)) {
197-
set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
198-
return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
194+
switch (subreq->error) {
195+
case -EACCES:
196+
case -EPERM:
197+
case -ENOKEY:
198+
case -EKEYEXPIRED:
199+
case -EKEYREJECTED:
200+
case -EKEYREVOKED:
201+
afs_get_writeback_key(wreq);
202+
if (!wreq->netfs_priv)
203+
stream->failed = true;
204+
break;
199205
}
200-
#endif
201-
202-
ret = afs_store_data(vnode, &subreq->io_iter, subreq->start);
203-
netfs_write_subrequest_terminated(subreq, ret < 0 ? ret : subreq->len, false);
204-
}
205-
206-
void afs_issue_write(struct netfs_io_subrequest *subreq)
207-
{
208-
subreq->work.func = afs_issue_write_worker;
209-
if (!queue_work(system_unbound_wq, &subreq->work))
210-
WARN_ON_ONCE(1);
211206
}
212207

213208
/*

fs/netfs/write_collect.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
163163

164164
_enter("R=%x[%x:]", wreq->debug_id, stream->stream_nr);
165165

166+
if (list_empty(&stream->subrequests))
167+
return;
168+
169+
if (stream->source == NETFS_UPLOAD_TO_SERVER &&
170+
wreq->netfs_ops->retry_request)
171+
wreq->netfs_ops->retry_request(wreq, stream);
172+
166173
if (unlikely(stream->failed))
167174
return;
168175

@@ -182,8 +189,6 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
182189
return;
183190
}
184191

185-
if (list_empty(&stream->subrequests))
186-
return;
187192
next = stream->subrequests.next;
188193

189194
do {

include/linux/netfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ struct netfs_io_request {
235235
struct iov_iter iter; /* Unencrypted-side iterator */
236236
struct iov_iter io_iter; /* I/O (Encrypted-side) iterator */
237237
void *netfs_priv; /* Private data for the netfs */
238+
void *netfs_priv2; /* Private data for the netfs */
238239
struct bio_vec *direct_bv; /* DIO buffer list (when handling iovec-iter) */
239240
unsigned int direct_bv_count; /* Number of elements in direct_bv[] */
240241
unsigned int debug_id;
@@ -306,6 +307,7 @@ struct netfs_request_ops {
306307
void (*begin_writeback)(struct netfs_io_request *wreq);
307308
void (*prepare_write)(struct netfs_io_subrequest *subreq);
308309
void (*issue_write)(struct netfs_io_subrequest *subreq);
310+
void (*retry_request)(struct netfs_io_request *wreq, struct netfs_io_stream *stream);
309311
void (*invalidate_cache)(struct netfs_io_request *wreq);
310312
};
311313

0 commit comments

Comments
 (0)