Skip to content

Commit 9e70501

Browse files
dhowellsbrauner
authored andcommitted
afs: Add more tracepoints to do with tracking validity
Add wrappers to set and clear the callback promise and to mark a directory as invalidated, and add tracepoints to track these events: (1) afs_cb_promise: Log when a callback promise is set on a vnode. (2) afs_vnode_invalid: Log when the server's callback promise for a vnode is no longer valid and we need to refetch the vnode metadata. (3) afs_dir_invalid: Log when the contents of a directory are marked invalid and requiring refetching from the server and the cache invalidating. and two tracepoints to record data version number management: (4) afs_set_dv: Log when the DV is recorded on a vnode. (5) afs_dv_mismatch: Log when the DV recorded on a vnode plus the expected delta for the operation does not match the DV we got back from the server. Signed-off-by: David Howells <[email protected]> Link: https://lore.kernel.org/r/[email protected] cc: Marc Dionne <[email protected]> cc: [email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent 229105e commit 9e70501

File tree

8 files changed

+248
-45
lines changed

8 files changed

+248
-45
lines changed

fs/afs/callback.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static void afs_volume_init_callback(struct afs_volume *volume)
4141

4242
list_for_each_entry(vnode, &volume->open_mmaps, cb_mmap_link) {
4343
if (vnode->cb_v_check != atomic_read(&volume->cb_v_break)) {
44-
atomic64_set(&vnode->cb_expires_at, AFS_NO_CB_PROMISE);
44+
afs_clear_cb_promise(vnode, afs_cb_promise_clear_vol_init_cb);
4545
queue_work(system_unbound_wq, &vnode->cb_work);
4646
}
4747
}
@@ -79,7 +79,7 @@ void __afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reas
7979
_enter("");
8080

8181
clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
82-
if (atomic64_xchg(&vnode->cb_expires_at, AFS_NO_CB_PROMISE) != AFS_NO_CB_PROMISE) {
82+
if (afs_clear_cb_promise(vnode, afs_cb_promise_clear_cb_break)) {
8383
vnode->cb_break++;
8484
vnode->cb_v_check = atomic_read(&vnode->volume->cb_v_break);
8585
afs_clear_permits(vnode);

fs/afs/dir.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
324324

325325
folio = filemap_get_folio(mapping, i);
326326
if (IS_ERR(folio)) {
327-
if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
328-
afs_stat_v(dvnode, n_inval);
327+
afs_invalidate_dir(dvnode, afs_dir_invalid_reclaimed_folio);
329328
folio = __filemap_get_folio(mapping,
330329
i, FGP_LOCK | FGP_CREAT,
331330
mapping->gfp_mask);
@@ -1388,8 +1387,8 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
13881387

13891388
clear_nlink(&vnode->netfs.inode);
13901389
set_bit(AFS_VNODE_DELETED, &vnode->flags);
1391-
atomic64_set(&vnode->cb_expires_at, AFS_NO_CB_PROMISE);
1392-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
1390+
afs_clear_cb_promise(vnode, afs_cb_promise_clear_rmdir);
1391+
afs_invalidate_dir(vnode, afs_dir_invalid_subdir_removed);
13931392
}
13941393
}
13951394

@@ -1851,6 +1850,7 @@ static void afs_rename_success(struct afs_operation *op)
18511850
write_seqlock(&vnode->cb_lock);
18521851

18531852
new_dv = vnode->status.data_version + 1;
1853+
trace_afs_set_dv(vnode, new_dv);
18541854
vnode->status.data_version = new_dv;
18551855
inode_set_iversion_raw(&vnode->netfs.inode, new_dv);
18561856

@@ -2063,8 +2063,7 @@ static bool afs_dir_release_folio(struct folio *folio, gfp_t gfp_flags)
20632063
folio_detach_private(folio);
20642064

20652065
/* The directory will need reloading. */
2066-
if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
2067-
afs_stat_v(dvnode, n_relpg);
2066+
afs_invalidate_dir(dvnode, afs_dir_invalid_release_folio);
20682067
return true;
20692068
}
20702069

@@ -2081,8 +2080,7 @@ static void afs_dir_invalidate_folio(struct folio *folio, size_t offset,
20812080
BUG_ON(!folio_test_locked(folio));
20822081

20832082
/* The directory will need reloading. */
2084-
if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
2085-
afs_stat_v(dvnode, n_inval);
2083+
afs_invalidate_dir(dvnode, afs_dir_invalid_inval_folio);
20862084

20872085
/* we clean up only if the entire folio is being invalidated */
20882086
if (offset == 0 && length == folio_size(folio))

fs/afs/dir_edit.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ static struct folio *afs_dir_get_folio(struct afs_vnode *vnode, pgoff_t index)
116116
FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
117117
mapping->gfp_mask);
118118
if (IS_ERR(folio)) {
119-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
119+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_get_block);
120120
return NULL;
121121
}
122122
if (!folio_test_private(folio))
@@ -220,7 +220,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
220220
i_size = i_size_read(&vnode->netfs.inode);
221221
if (i_size > AFS_DIR_BLOCK_SIZE * AFS_DIR_MAX_BLOCKS ||
222222
(i_size & (AFS_DIR_BLOCK_SIZE - 1))) {
223-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
223+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_add_bad_size);
224224
return;
225225
}
226226

@@ -299,7 +299,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
299299
* succeeded. Download the directory again.
300300
*/
301301
trace_afs_edit_dir(vnode, why, afs_edit_dir_create_nospc, 0, 0, 0, 0, name->name);
302-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
302+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_add_no_slots);
303303
goto out_unmap;
304304

305305
new_directory:
@@ -358,7 +358,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
358358
goto out_unmap;
359359

360360
error_too_many_blocks:
361-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
361+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_add_too_many_blocks);
362362
error:
363363
trace_afs_edit_dir(vnode, why, afs_edit_dir_create_error, 0, 0, 0, 0, name->name);
364364
goto out_unmap;
@@ -388,7 +388,7 @@ void afs_edit_dir_remove(struct afs_vnode *vnode,
388388
if (i_size < AFS_DIR_BLOCK_SIZE ||
389389
i_size > AFS_DIR_BLOCK_SIZE * AFS_DIR_MAX_BLOCKS ||
390390
(i_size & (AFS_DIR_BLOCK_SIZE - 1))) {
391-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
391+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_rem_bad_size);
392392
return;
393393
}
394394
nr_blocks = i_size / AFS_DIR_BLOCK_SIZE;
@@ -440,7 +440,7 @@ void afs_edit_dir_remove(struct afs_vnode *vnode,
440440
/* Didn't find the dirent to clobber. Download the directory again. */
441441
trace_afs_edit_dir(vnode, why, afs_edit_dir_delete_noent,
442442
0, 0, 0, 0, name->name);
443-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
443+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_rem_wrong_name);
444444
goto out_unmap;
445445

446446
found_dirent:
@@ -510,7 +510,7 @@ void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_d
510510

511511
i_size = i_size_read(&vnode->netfs.inode);
512512
if (i_size < AFS_DIR_BLOCK_SIZE) {
513-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
513+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_upd_bad_size);
514514
return;
515515
}
516516
nr_blocks = i_size / AFS_DIR_BLOCK_SIZE;
@@ -542,7 +542,7 @@ void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_d
542542
/* Didn't find the dirent to clobber. Download the directory again. */
543543
trace_afs_edit_dir(vnode, why, afs_edit_dir_update_nodd,
544544
0, 0, 0, 0, "..");
545-
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
545+
afs_invalidate_dir(vnode, afs_dir_invalid_edit_upd_no_dd);
546546
goto out;
547547

548548
found_dirent:

fs/afs/inode.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,17 @@ static int afs_inode_init_from_status(struct afs_operation *op,
140140
afs_set_netfs_context(vnode);
141141

142142
vnode->invalid_before = status->data_version;
143+
trace_afs_set_dv(vnode, status->data_version);
143144
inode_set_iversion_raw(&vnode->netfs.inode, status->data_version);
144145

145146
if (!vp->scb.have_cb) {
146147
/* it's a symlink we just created (the fileserver
147148
* didn't give us a callback) */
148-
atomic64_set(&vnode->cb_expires_at, AFS_NO_CB_PROMISE);
149+
afs_clear_cb_promise(vnode, afs_cb_promise_set_new_symlink);
149150
} else {
150151
vnode->cb_server = op->server;
151-
atomic64_set(&vnode->cb_expires_at, vp->scb.callback.expires_at);
152+
afs_set_cb_promise(vnode, vp->scb.callback.expires_at,
153+
afs_cb_promise_set_new_inode);
152154
}
153155

154156
write_sequnlock(&vnode->cb_lock);
@@ -207,12 +209,17 @@ static void afs_apply_status(struct afs_operation *op,
207209
if (vp->update_ctime)
208210
inode_set_ctime_to_ts(inode, op->ctime);
209211

210-
if (vnode->status.data_version != status->data_version)
212+
if (vnode->status.data_version != status->data_version) {
213+
trace_afs_set_dv(vnode, status->data_version);
211214
data_changed = true;
215+
}
212216

213217
vnode->status = *status;
214218

215219
if (vp->dv_before + vp->dv_delta != status->data_version) {
220+
trace_afs_dv_mismatch(vnode, vp->dv_before, vp->dv_delta,
221+
status->data_version);
222+
216223
if (vnode->cb_ro_snapshot == atomic_read(&vnode->volume->cb_ro_snapshot) &&
217224
atomic64_read(&vnode->cb_expires_at) != AFS_NO_CB_PROMISE)
218225
pr_warn("kAFS: vnode modified {%llx:%llu} %llx->%llx %s (op=%x)\n",
@@ -223,12 +230,10 @@ static void afs_apply_status(struct afs_operation *op,
223230
op->debug_id);
224231

225232
vnode->invalid_before = status->data_version;
226-
if (vnode->status.type == AFS_FTYPE_DIR) {
227-
if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
228-
afs_stat_v(vnode, n_inval);
229-
} else {
233+
if (vnode->status.type == AFS_FTYPE_DIR)
234+
afs_invalidate_dir(vnode, afs_dir_invalid_dv_mismatch);
235+
else
230236
set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
231-
}
232237
change_size = true;
233238
data_changed = true;
234239
unexpected_jump = true;
@@ -273,7 +278,7 @@ static void afs_apply_callback(struct afs_operation *op,
273278
if (!afs_cb_is_broken(vp->cb_break_before, vnode)) {
274279
if (op->volume->type == AFSVL_RWVOL)
275280
vnode->cb_server = op->server;
276-
atomic64_set(&vnode->cb_expires_at, cb->expires_at);
281+
afs_set_cb_promise(vnode, cb->expires_at, afs_cb_promise_set_apply_cb);
277282
}
278283
}
279284

fs/afs/internal.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,38 @@ static inline int afs_bad(struct afs_vnode *vnode, enum afs_file_error where)
17131713
return -EIO;
17141714
}
17151715

1716+
/*
1717+
* Set the callback promise on a vnode.
1718+
*/
1719+
static inline void afs_set_cb_promise(struct afs_vnode *vnode, time64_t expires_at,
1720+
enum afs_cb_promise_trace trace)
1721+
{
1722+
atomic64_set(&vnode->cb_expires_at, expires_at);
1723+
trace_afs_cb_promise(vnode, trace);
1724+
}
1725+
1726+
/*
1727+
* Clear the callback promise on a vnode, returning true if it was promised.
1728+
*/
1729+
static inline bool afs_clear_cb_promise(struct afs_vnode *vnode,
1730+
enum afs_cb_promise_trace trace)
1731+
{
1732+
trace_afs_cb_promise(vnode, trace);
1733+
return atomic64_xchg(&vnode->cb_expires_at, AFS_NO_CB_PROMISE) != AFS_NO_CB_PROMISE;
1734+
}
1735+
1736+
/*
1737+
* Mark a directory as being invalid.
1738+
*/
1739+
static inline void afs_invalidate_dir(struct afs_vnode *dvnode,
1740+
enum afs_dir_invalid_trace trace)
1741+
{
1742+
if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
1743+
trace_afs_dir_invalid(dvnode, trace);
1744+
afs_stat_v(dvnode, n_inval);
1745+
}
1746+
}
1747+
17161748
/*****************************************************************************/
17171749
/*
17181750
* debug tracing

fs/afs/rotate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ static bool afs_start_fs_iteration(struct afs_operation *op,
9999
write_seqlock(&vnode->cb_lock);
100100
ASSERTCMP(cb_server, ==, vnode->cb_server);
101101
vnode->cb_server = NULL;
102-
if (atomic64_xchg(&vnode->cb_expires_at, AFS_NO_CB_PROMISE) != AFS_NO_CB_PROMISE)
102+
if (afs_clear_cb_promise(vnode, afs_cb_promise_clear_rotate_server))
103103
vnode->cb_break++;
104104
write_sequnlock(&vnode->cb_lock);
105105
}
@@ -583,7 +583,7 @@ bool afs_select_fileserver(struct afs_operation *op)
583583
if (vnode->cb_server != server) {
584584
vnode->cb_server = server;
585585
vnode->cb_v_check = atomic_read(&vnode->volume->cb_v_break);
586-
atomic64_set(&vnode->cb_expires_at, AFS_NO_CB_PROMISE);
586+
afs_clear_cb_promise(vnode, afs_cb_promise_clear_server_change);
587587
}
588588

589589
retry_server:

fs/afs/validation.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,31 @@
120120
bool afs_check_validity(const struct afs_vnode *vnode)
121121
{
122122
const struct afs_volume *volume = vnode->volume;
123+
enum afs_vnode_invalid_trace trace = afs_vnode_valid_trace;
124+
time64_t cb_expires_at = atomic64_read(&vnode->cb_expires_at);
123125
time64_t deadline = ktime_get_real_seconds() + 10;
124126

125127
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
126128
return true;
127129

128-
if (atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break) ||
129-
atomic64_read(&vnode->cb_expires_at) <= deadline ||
130-
volume->cb_expires_at <= deadline ||
131-
vnode->cb_ro_snapshot != atomic_read(&volume->cb_ro_snapshot) ||
132-
vnode->cb_scrub != atomic_read(&volume->cb_scrub) ||
133-
test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
134-
_debug("inval");
135-
return false;
136-
}
137-
138-
return true;
130+
if (atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break))
131+
trace = afs_vnode_invalid_trace_cb_v_break;
132+
else if (cb_expires_at == AFS_NO_CB_PROMISE)
133+
trace = afs_vnode_invalid_trace_no_cb_promise;
134+
else if (cb_expires_at <= deadline)
135+
trace = afs_vnode_invalid_trace_expired;
136+
else if (volume->cb_expires_at <= deadline)
137+
trace = afs_vnode_invalid_trace_vol_expired;
138+
else if (vnode->cb_ro_snapshot != atomic_read(&volume->cb_ro_snapshot))
139+
trace = afs_vnode_invalid_trace_cb_ro_snapshot;
140+
else if (vnode->cb_scrub != atomic_read(&volume->cb_scrub))
141+
trace = afs_vnode_invalid_trace_cb_scrub;
142+
else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
143+
trace = afs_vnode_invalid_trace_zap_data;
144+
else
145+
return true;
146+
trace_afs_vnode_invalid(vnode, trace);
147+
return false;
139148
}
140149

141150
/*

0 commit comments

Comments
 (0)