Lines Matching +full:out +full:- +full:volume +full:- +full:limit
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* vnode and volume validity verification.
19 * (2) On a RW volume, in response to certain vnode (inode)-accessing RPC
20 * calls, the server maintains a time-limited per-vnode promise that it
24 * Note that a vnode-level callbacks may also be sent for other reasons,
27 * (3) On a RO (or Backup) volume, in response to certain vnode-accessing RPC
28 * calls, each server maintains a time-limited per-volume promise that it
29 * will send us a CB.CallBack request if the RO volume is updated to a
30 * snapshot of the RW volume ("vos release"). This is an atomic event
31 * that cuts over all instances of the RO volume across multiple servers
34 * Note that a volume-level callbacks may also be sent for other reasons,
35 * such as the volumeserver taking over control of the volume from the
38 * Note also that each server maintains an independent time limit on an
41 * (4) Certain RPC calls include a volume information record "VolSync" in
42 * their reply. This contains a creation date for the volume that should
43 * remain unchanged for a RW volume (but will be changed if the volume is
45 * when a RO volume is released.
49 * ->cb_v_break. A counter of events that might mean that the contents of
50 * a volume have been altered since we last checked a vnode.
52 * ->cb_v_check. A counter of the number of events that we've sent a
56 * ->cb_scrub. A counter of the number of regression events for which we
59 * ->cb_ro_snapshot. A counter of the number of times that we've
60 * recognised that a RO volume has been updated.
62 * ->cb_break. A counter of events that might mean that the contents of a
65 * ->cb_expires_at. The time at which the callback promise expires or
70 * (1) When a volume-level CB.CallBack occurs, we increment ->cb_v_break on
71 * the volume and reset ->cb_expires_at (ie. set AFS_NO_CB_PROMISE) on the
72 * volume and volume's server record.
74 * (2) When a CB.InitCallBackState occurs, we treat this as a volume-level
75 * callback break on all the volumes that have been using that volume
76 * (ie. increment ->cb_v_break and reset ->cb_expires_at).
78 * (3) When a vnode-level CB.CallBack occurs, we increment ->cb_break on the
79 * vnode and reset its ->cb_expires_at. If the vnode is mmapped, we also
84 * validity of a vnode. This first checks to see if ->cb_v_check and
85 * ->cb_v_break match, and if they don't, we lock volume->cb_check_lock
88 * After checking the volume, we check the vnode. If there's a mismatch
89 * between the volume counters and the vnode's mirrors of those counters,
90 * we lock vnode->validate_lock and issue an FS.FetchStatus on the vnode.
95 * (A) If the Creation timestamp has changed on a RW volume or regressed
96 * on a RO volume, we try to increment ->cb_scrub; if it advances on a
97 * RO volume, we assume "vos release" happened and try to increment
98 * ->cb_ro_snapshot.
101 * ->cb_scrub.
107 * volume->cb_v_check is then set to ->cb_v_break.
110 * parsed and used to set the promise in ->cb_expires_at for the vnode,
111 * the volume and the volume's server record.
113 * (7) If ->cb_scrub is seen to have advanced, we invalidate the pagecache for
118 * Check the validity of a vnode/inode and its parent volume.
122 const struct afs_volume *volume = vnode->volume; in afs_check_validity() local
124 time64_t cb_expires_at = atomic64_read(&vnode->cb_expires_at); in afs_check_validity()
127 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) in afs_check_validity()
130 if (atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break)) in afs_check_validity()
136 else if (volume->cb_expires_at <= deadline) in afs_check_validity()
138 else if (vnode->cb_ro_snapshot != atomic_read(&volume->cb_ro_snapshot)) in afs_check_validity()
140 else if (vnode->cb_scrub != atomic_read(&volume->cb_scrub)) in afs_check_validity()
142 else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) in afs_check_validity()
153 static bool __afs_is_server_excluded(struct afs_operation *op, struct afs_volume *volume) in __afs_is_server_excluded() argument
162 slist = rcu_dereference(volume->servers); in __afs_is_server_excluded()
163 for (i = 0; i < slist->nr_servers; i++) { in __afs_is_server_excluded()
164 se = &slist->servers[i]; in __afs_is_server_excluded()
165 if (op->server == se->server) { in __afs_is_server_excluded()
166 is_excluded = test_bit(AFS_SE_EXCLUDED, &se->flags); in __afs_is_server_excluded()
176 * Update the volume's server list when the creation time changes and see if
179 static int afs_is_server_excluded(struct afs_operation *op, struct afs_volume *volume) in afs_is_server_excluded() argument
183 if (__afs_is_server_excluded(op, volume)) in afs_is_server_excluded()
186 set_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags); in afs_is_server_excluded()
187 ret = afs_check_volume_status(op->volume, op); in afs_is_server_excluded()
191 return __afs_is_server_excluded(op, volume); in afs_is_server_excluded()
195 * Handle a change to the volume creation time in the VolSync record.
197 static int afs_update_volume_creation_time(struct afs_operation *op, struct afs_volume *volume) in afs_update_volume_creation_time() argument
200 time64_t cur = volume->creation_time; in afs_update_volume_creation_time()
201 time64_t old = op->pre_volsync.creation; in afs_update_volume_creation_time()
202 time64_t new = op->volsync.creation; in afs_update_volume_creation_time()
205 _enter("%llx,%llx,%llx->%llx", volume->vid, cur, old, new); in afs_update_volume_creation_time()
208 volume->creation_time = new; in afs_update_volume_creation_time()
224 * our caches. For a RW vol, this will only change if the volume is in afs_update_volume_creation_time()
226 * the volume is updated to a new snapshot (eg. "vos release"). in afs_update_volume_creation_time()
228 if (volume->type == AFSVL_RWVOL) in afs_update_volume_creation_time()
230 if (volume->type == AFSVL_BACKVOL) { in afs_update_volume_creation_time()
236 /* We have an RO volume, we need to query the VL server and look at the in afs_update_volume_creation_time()
237 * server flags to see if RW->RO replication is in progress. in afs_update_volume_creation_time()
239 ret = afs_is_server_excluded(op, volume); in afs_update_volume_creation_time()
243 snap = atomic_read(&volume->cb_ro_snapshot); in afs_update_volume_creation_time()
244 trace_afs_cb_v_break(volume->vid, snap, afs_cb_break_volume_excluded); in afs_update_volume_creation_time()
249 snap = atomic_inc_return(&volume->cb_ro_snapshot); in afs_update_volume_creation_time()
250 trace_afs_cb_v_break(volume->vid, snap, afs_cb_break_for_vos_release); in afs_update_volume_creation_time()
251 volume->creation_time = new; in afs_update_volume_creation_time()
255 atomic_inc(&volume->cb_scrub); in afs_update_volume_creation_time()
256 trace_afs_cb_v_break(volume->vid, 0, afs_cb_break_for_creation_regress); in afs_update_volume_creation_time()
257 volume->creation_time = new; in afs_update_volume_creation_time()
262 * Handle a change to the volume update time in the VolSync record.
264 static void afs_update_volume_update_time(struct afs_operation *op, struct afs_volume *volume) in afs_update_volume_update_time() argument
267 time64_t cur = volume->update_time; in afs_update_volume_update_time()
268 time64_t old = op->pre_volsync.update; in afs_update_volume_update_time()
269 time64_t new = op->volsync.update; in afs_update_volume_update_time()
271 _enter("%llx,%llx,%llx->%llx", volume->vid, cur, old, new); in afs_update_volume_update_time()
274 volume->update_time = new; in afs_update_volume_update_time()
281 /* If the volume update time changes in an unexpected way, we need to in afs_update_volume_update_time()
284 * volume is updated to a new snapshot (eg. "vos release"). in afs_update_volume_update_time()
296 atomic_inc(&volume->cb_scrub); in afs_update_volume_update_time()
297 trace_afs_cb_v_break(volume->vid, 0, reason); in afs_update_volume_update_time()
299 volume->update_time = new; in afs_update_volume_update_time()
303 static int afs_update_volume_times(struct afs_operation *op, struct afs_volume *volume) in afs_update_volume_times() argument
307 if (likely(op->volsync.creation == volume->creation_time && in afs_update_volume_times()
308 op->volsync.update == volume->update_time)) in afs_update_volume_times()
311 mutex_lock(&volume->volsync_lock); in afs_update_volume_times()
312 if (op->volsync.creation != volume->creation_time) { in afs_update_volume_times()
313 ret = afs_update_volume_creation_time(op, volume); in afs_update_volume_times()
315 goto out; in afs_update_volume_times()
317 if (op->volsync.update != volume->update_time) in afs_update_volume_times()
318 afs_update_volume_update_time(op, volume); in afs_update_volume_times()
319 out: in afs_update_volume_times()
320 mutex_unlock(&volume->volsync_lock); in afs_update_volume_times()
325 * Update the state of a volume, including recording the expiration time of the
330 struct afs_server_list *slist = op->server_list; in afs_update_volume_state()
331 struct afs_server_entry *se = &slist->servers[op->server_index]; in afs_update_volume_state()
332 struct afs_callback *cb = &op->file[0].scb.callback; in afs_update_volume_state()
333 struct afs_volume *volume = op->volume; in afs_update_volume_state() local
334 unsigned int cb_v_break = atomic_read(&volume->cb_v_break); in afs_update_volume_state()
335 unsigned int cb_v_check = atomic_read(&volume->cb_v_check); in afs_update_volume_state()
338 _enter("%llx", op->volume->vid); in afs_update_volume_state()
340 if (op->volsync.creation != TIME64_MIN || op->volsync.update != TIME64_MIN) { in afs_update_volume_state()
341 ret = afs_update_volume_times(op, volume); in afs_update_volume_state()
348 if (op->cb_v_break == cb_v_break && in afs_update_volume_state()
349 (op->file[0].scb.have_cb || op->file[1].scb.have_cb)) { in afs_update_volume_state()
350 time64_t expires_at = cb->expires_at; in afs_update_volume_state()
352 if (!op->file[0].scb.have_cb) in afs_update_volume_state()
353 expires_at = op->file[1].scb.callback.expires_at; in afs_update_volume_state()
355 se->cb_expires_at = expires_at; in afs_update_volume_state()
356 volume->cb_expires_at = expires_at; in afs_update_volume_state()
358 if (cb_v_check < op->cb_v_break) in afs_update_volume_state()
359 atomic_cmpxchg(&volume->cb_v_check, cb_v_check, op->cb_v_break); in afs_update_volume_state()
365 * - might also want to ditch all the outstanding writes and dirty pages
369 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); in afs_zap_data()
373 /* nuke all the non-dirty pages that aren't locked, mapped or being in afs_zap_data()
376 if (S_ISREG(vnode->netfs.inode.i_mode)) in afs_zap_data()
377 filemap_invalidate_inode(&vnode->netfs.inode, true, 0, LLONG_MAX); in afs_zap_data()
379 filemap_invalidate_inode(&vnode->netfs.inode, false, 0, LLONG_MAX); in afs_zap_data()
384 * - there are several things we need to check
385 * - parent dir data changes (rm, rmdir, rename, mkdir, create, link,
387 * - parent dir metadata changed (security changes)
388 * - dentry data changed (write, truncate)
389 * - dentry metadata changed (security changes)
393 struct afs_volume *volume = vnode->volume; in afs_validate() local
400 vnode->fid.vid, vnode->fid.vnode, vnode->flags, in afs_validate()
404 return test_bit(AFS_VNODE_DELETED, &vnode->flags) ? -ESTALE : 0; in afs_validate()
406 ret = down_write_killable(&vnode->validate_lock); in afs_validate()
410 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { in afs_validate()
411 ret = -ESTALE; in afs_validate()
415 /* Validate a volume after the v_break has changed or the volume in afs_validate()
416 * callback expired. We only want to do this once per volume per in afs_validate()
420 if (volume->cb_expires_at <= deadline || in afs_validate()
421 atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break)) { in afs_validate()
422 ret = mutex_lock_interruptible(&volume->cb_check_lock); in afs_validate()
428 cb_ro_snapshot = atomic_read(&volume->cb_ro_snapshot); in afs_validate()
429 cb_scrub = atomic_read(&volume->cb_scrub); in afs_validate()
430 if (vnode->cb_ro_snapshot != cb_ro_snapshot || in afs_validate()
431 vnode->cb_scrub != cb_scrub) in afs_validate()
432 unmap_mapping_pages(vnode->netfs.inode.i_mapping, 0, 0, false); in afs_validate()
434 if (vnode->cb_ro_snapshot != cb_ro_snapshot || in afs_validate()
435 vnode->cb_scrub != cb_scrub || in afs_validate()
436 volume->cb_expires_at <= deadline || in afs_validate()
437 atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break) || in afs_validate()
438 atomic64_read(&vnode->cb_expires_at) <= deadline in afs_validate()
442 if (ret == -ENOENT) { in afs_validate()
443 set_bit(AFS_VNODE_DELETED, &vnode->flags); in afs_validate()
444 ret = -ESTALE; in afs_validate()
449 _debug("new promise [fl=%lx]", vnode->flags); in afs_validate()
452 /* We can drop the volume lock now as. */ in afs_validate()
454 mutex_unlock(&volume->cb_check_lock); in afs_validate()
458 cb_ro_snapshot = atomic_read(&volume->cb_ro_snapshot); in afs_validate()
459 cb_scrub = atomic_read(&volume->cb_scrub); in afs_validate()
461 vnode->cb_ro_snapshot, cb_ro_snapshot, in afs_validate()
462 vnode->cb_scrub, cb_scrub); in afs_validate()
463 if (vnode->cb_scrub != cb_scrub) in afs_validate()
465 vnode->cb_ro_snapshot = cb_ro_snapshot; in afs_validate()
466 vnode->cb_scrub = cb_scrub; in afs_validate()
470 zap |= test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags); in afs_validate()
473 up_write(&vnode->validate_lock); in afs_validate()
479 mutex_unlock(&volume->cb_check_lock); in afs_validate()
480 up_write(&vnode->validate_lock); in afs_validate()