1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Fileserver-directed operation handling.
4 * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
8 #include <linux/kernel.h>
9 #include <linux/slab.h>
13 static atomic_t afs_operation_debug_counter
;
16 * Create an operation against a volume.
18 struct afs_operation
*afs_alloc_operation(struct key
*key
, struct afs_volume
*volume
)
20 struct afs_operation
*op
;
24 op
= kzalloc(sizeof(*op
), GFP_KERNEL
);
26 return ERR_PTR(-ENOMEM
);
29 key
= afs_request_key(volume
->cell
);
39 op
->volume
= afs_get_volume(volume
, afs_volume_trace_get_new_op
);
40 op
->net
= volume
->cell
->net
;
41 op
->cb_v_break
= atomic_read(&volume
->cb_v_break
);
42 op
->pre_volsync
.creation
= volume
->creation_time
;
43 op
->pre_volsync
.update
= volume
->update_time
;
44 op
->debug_id
= atomic_inc_return(&afs_operation_debug_counter
);
45 op
->nr_iterations
= -1;
46 afs_op_set_error(op
, -EDESTADDRREQ
);
48 _leave(" = [op=%08x]", op
->debug_id
);
53 * Lock the vnode(s) being operated upon.
55 static bool afs_get_io_locks(struct afs_operation
*op
)
57 struct afs_vnode
*vnode
= op
->file
[0].vnode
;
58 struct afs_vnode
*vnode2
= op
->file
[1].vnode
;
62 if (op
->flags
& AFS_OPERATION_UNINTR
) {
63 mutex_lock(&vnode
->io_lock
);
64 op
->flags
|= AFS_OPERATION_LOCK_0
;
69 if (!vnode2
|| !op
->file
[1].need_io_lock
|| vnode
== vnode2
)
75 if (mutex_lock_interruptible(&vnode
->io_lock
) < 0) {
76 afs_op_set_error(op
, -ERESTARTSYS
);
77 op
->flags
|= AFS_OPERATION_STOP
;
81 op
->flags
|= AFS_OPERATION_LOCK_0
;
84 if (mutex_lock_interruptible_nested(&vnode2
->io_lock
, 1) < 0) {
85 afs_op_set_error(op
, -ERESTARTSYS
);
86 op
->flags
|= AFS_OPERATION_STOP
;
87 mutex_unlock(&vnode
->io_lock
);
88 op
->flags
&= ~AFS_OPERATION_LOCK_0
;
92 op
->flags
|= AFS_OPERATION_LOCK_1
;
99 static void afs_drop_io_locks(struct afs_operation
*op
)
101 struct afs_vnode
*vnode
= op
->file
[0].vnode
;
102 struct afs_vnode
*vnode2
= op
->file
[1].vnode
;
106 if (op
->flags
& AFS_OPERATION_LOCK_1
)
107 mutex_unlock(&vnode2
->io_lock
);
108 if (op
->flags
& AFS_OPERATION_LOCK_0
)
109 mutex_unlock(&vnode
->io_lock
);
112 static void afs_prepare_vnode(struct afs_operation
*op
, struct afs_vnode_param
*vp
,
115 struct afs_vnode
*vnode
= vp
->vnode
;
118 vp
->fid
= vnode
->fid
;
119 vp
->dv_before
= vnode
->status
.data_version
;
120 vp
->cb_break_before
= afs_calc_vnode_cb_break(vnode
);
121 if (vnode
->lock_state
!= AFS_VNODE_LOCK_NONE
)
122 op
->flags
|= AFS_OPERATION_CUR_ONLY
;
123 if (vp
->modification
)
124 set_bit(AFS_VNODE_MODIFYING
, &vnode
->flags
);
128 _debug("PREP[%u] {%llx:%llu.%u}",
129 index
, vp
->fid
.vid
, vp
->fid
.vnode
, vp
->fid
.unique
);
133 * Begin an operation on the fileserver.
135 * Fileserver operations are serialised on the server by vnode, so we serialise
136 * them here also using the io_lock.
138 bool afs_begin_vnode_operation(struct afs_operation
*op
)
140 struct afs_vnode
*vnode
= op
->file
[0].vnode
;
146 if (op
->file
[0].need_io_lock
)
147 if (!afs_get_io_locks(op
))
150 afs_prepare_vnode(op
, &op
->file
[0], 0);
151 afs_prepare_vnode(op
, &op
->file
[1], 1);
152 op
->cb_v_break
= atomic_read(&op
->volume
->cb_v_break
);
158 * Tidy up a filesystem cursor and unlock the vnode.
160 static void afs_end_vnode_operation(struct afs_operation
*op
)
164 switch (afs_op_error(op
)) {
169 afs_dump_edestaddrreq(op
);
173 afs_drop_io_locks(op
);
177 * Wait for an in-progress operation to complete.
179 void afs_wait_for_operation(struct afs_operation
*op
)
183 while (afs_select_fileserver(op
)) {
184 op
->call_responded
= false;
186 op
->call_abort_code
= 0;
187 if (test_bit(AFS_SERVER_FL_IS_YFS
, &op
->server
->flags
) &&
188 op
->ops
->issue_yfs_rpc
)
189 op
->ops
->issue_yfs_rpc(op
);
190 else if (op
->ops
->issue_afs_rpc
)
191 op
->ops
->issue_afs_rpc(op
);
193 op
->call_error
= -ENOTSUPP
;
196 afs_wait_for_call_to_complete(op
->call
);
197 op
->call_abort_code
= op
->call
->abort_code
;
198 op
->call_error
= op
->call
->error
;
199 op
->call_responded
= op
->call
->responded
;
200 afs_put_call(op
->call
);
204 if (op
->call_responded
&& op
->server
)
205 set_bit(AFS_SERVER_FL_RESPONDING
, &op
->server
->flags
);
207 if (!afs_op_error(op
)) {
209 op
->ops
->success(op
);
210 } else if (op
->cumul_error
.aborted
) {
211 if (op
->ops
->aborted
)
212 op
->ops
->aborted(op
);
218 afs_end_vnode_operation(op
);
220 if (!afs_op_error(op
) && op
->ops
->edit_dir
) {
222 op
->ops
->edit_dir(op
);
228 * Dispose of an operation.
230 int afs_put_operation(struct afs_operation
*op
)
232 struct afs_addr_list
*alist
;
233 int i
, ret
= afs_op_error(op
);
235 _enter("op=%08x,%d", op
->debug_id
, ret
);
237 if (op
->ops
&& op
->ops
->put
)
239 if (op
->file
[0].modification
)
240 clear_bit(AFS_VNODE_MODIFYING
, &op
->file
[0].vnode
->flags
);
241 if (op
->file
[1].modification
&& op
->file
[1].vnode
!= op
->file
[0].vnode
)
242 clear_bit(AFS_VNODE_MODIFYING
, &op
->file
[1].vnode
->flags
);
243 if (op
->file
[0].put_vnode
)
244 iput(&op
->file
[0].vnode
->netfs
.inode
);
245 if (op
->file
[1].put_vnode
)
246 iput(&op
->file
[1].vnode
->netfs
.inode
);
248 if (op
->more_files
) {
249 for (i
= 0; i
< op
->nr_files
- 2; i
++)
250 if (op
->more_files
[i
].put_vnode
)
251 iput(&op
->more_files
[i
].vnode
->netfs
.inode
);
252 kfree(op
->more_files
);
256 alist
= op
->estate
->addresses
;
258 if (op
->call_responded
&&
259 op
->addr_index
!= alist
->preferred
&&
260 test_bit(alist
->preferred
, &op
->addr_tried
))
261 WRITE_ONCE(alist
->preferred
, op
->addr_index
);
265 afs_clear_server_states(op
);
266 afs_put_serverlist(op
->net
, op
->server_list
);
267 afs_put_volume(op
->volume
, afs_volume_trace_put_put_op
);
273 int afs_do_sync_operation(struct afs_operation
*op
)
275 afs_begin_vnode_operation(op
);
276 afs_wait_for_operation(op
);
277 return afs_put_operation(op
);