summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-06-20 13:12:16 -0400
committerDavid Howells <dhowells@redhat.com>2019-06-20 13:12:16 -0400
commit051d25250b55c215a2254a0130d46fbd38bcbcc0 (patch)
tree0e53a2801fb6f964d85e663435041c01943cb878
parentfa59f52f5b1412c373813e24e7cbe5ab44518ed8 (diff)
afs: Add some callback management tracepoints
Add a couple of tracepoints to track callback management: (1) afs_cb_miss - Logs when we were unable to apply a callback, either due to the inode being discarded or due to a competing thread applying a callback first. (2) afs_cb_break - Logs when we attempted to clear the noted callback promise, either due to the server explicitly breaking the callback, the callback promise lapsing or a local event obsoleting it. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--fs/afs/callback.c16
-rw-r--r--fs/afs/dir.c4
-rw-r--r--fs/afs/inode.c17
-rw-r--r--fs/afs/internal.h8
-rw-r--r--include/trace/events/afs.h69
5 files changed, 97 insertions, 17 deletions
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 915010464572..d66cd0364243 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -212,7 +212,7 @@ void afs_init_callback_state(struct afs_server *server)
212/* 212/*
213 * actually break a callback 213 * actually break a callback
214 */ 214 */
215void __afs_break_callback(struct afs_vnode *vnode) 215void __afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reason)
216{ 216{
217 _enter(""); 217 _enter("");
218 218
@@ -223,13 +223,17 @@ void __afs_break_callback(struct afs_vnode *vnode)
223 223
224 if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB) 224 if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB)
225 afs_lock_may_be_available(vnode); 225 afs_lock_may_be_available(vnode);
226
227 trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, true);
228 } else {
229 trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, false);
226 } 230 }
227} 231}
228 232
229void afs_break_callback(struct afs_vnode *vnode) 233void afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reason)
230{ 234{
231 write_seqlock(&vnode->cb_lock); 235 write_seqlock(&vnode->cb_lock);
232 __afs_break_callback(vnode); 236 __afs_break_callback(vnode, reason);
233 write_sequnlock(&vnode->cb_lock); 237 write_sequnlock(&vnode->cb_lock);
234} 238}
235 239
@@ -277,6 +281,8 @@ static void afs_break_one_callback(struct afs_server *server,
277 281
278 write_lock(&volume->cb_v_break_lock); 282 write_lock(&volume->cb_v_break_lock);
279 volume->cb_v_break++; 283 volume->cb_v_break++;
284 trace_afs_cb_break(fid, volume->cb_v_break,
285 afs_cb_break_for_volume_callback, false);
280 write_unlock(&volume->cb_v_break_lock); 286 write_unlock(&volume->cb_v_break_lock);
281 } else { 287 } else {
282 data.volume = NULL; 288 data.volume = NULL;
@@ -285,8 +291,10 @@ static void afs_break_one_callback(struct afs_server *server,
285 afs_iget5_test, &data); 291 afs_iget5_test, &data);
286 if (inode) { 292 if (inode) {
287 vnode = AFS_FS_I(inode); 293 vnode = AFS_FS_I(inode);
288 afs_break_callback(vnode); 294 afs_break_callback(vnode, afs_cb_break_for_callback);
289 iput(inode); 295 iput(inode);
296 } else {
297 trace_afs_cb_miss(fid, afs_cb_break_for_callback);
290 } 298 }
291 } 299 }
292 } 300 }
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 93fd51c3bdae..e8c58c94eb61 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -1367,12 +1367,12 @@ static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry,
1367 drop_nlink(&vnode->vfs_inode); 1367 drop_nlink(&vnode->vfs_inode);
1368 if (vnode->vfs_inode.i_nlink == 0) { 1368 if (vnode->vfs_inode.i_nlink == 0) {
1369 set_bit(AFS_VNODE_DELETED, &vnode->flags); 1369 set_bit(AFS_VNODE_DELETED, &vnode->flags);
1370 __afs_break_callback(vnode); 1370 __afs_break_callback(vnode, afs_cb_break_for_unlink);
1371 } 1371 }
1372 write_sequnlock(&vnode->cb_lock); 1372 write_sequnlock(&vnode->cb_lock);
1373 ret = 0; 1373 ret = 0;
1374 } else { 1374 } else {
1375 afs_break_callback(vnode); 1375 afs_break_callback(vnode, afs_cb_break_for_unlink);
1376 1376
1377 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 1377 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
1378 kdebug("AFS_VNODE_DELETED"); 1378 kdebug("AFS_VNODE_DELETED");
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 18a50d4febcf..7b1c18c32f48 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -283,7 +283,7 @@ void afs_vnode_commit_status(struct afs_fs_cursor *fc,
283 if (scb->status.abort_code == VNOVNODE) { 283 if (scb->status.abort_code == VNOVNODE) {
284 set_bit(AFS_VNODE_DELETED, &vnode->flags); 284 set_bit(AFS_VNODE_DELETED, &vnode->flags);
285 clear_nlink(&vnode->vfs_inode); 285 clear_nlink(&vnode->vfs_inode);
286 __afs_break_callback(vnode); 286 __afs_break_callback(vnode, afs_cb_break_for_deleted);
287 } 287 }
288 } else { 288 } else {
289 if (scb->have_status) 289 if (scb->have_status)
@@ -594,8 +594,9 @@ bool afs_check_validity(struct afs_vnode *vnode)
594 struct afs_cb_interest *cbi; 594 struct afs_cb_interest *cbi;
595 struct afs_server *server; 595 struct afs_server *server;
596 struct afs_volume *volume = vnode->volume; 596 struct afs_volume *volume = vnode->volume;
597 enum afs_cb_break_reason need_clear = afs_cb_break_no_break;
597 time64_t now = ktime_get_real_seconds(); 598 time64_t now = ktime_get_real_seconds();
598 bool valid, need_clear = false; 599 bool valid;
599 unsigned int cb_break, cb_s_break, cb_v_break; 600 unsigned int cb_break, cb_s_break, cb_v_break;
600 int seq = 0; 601 int seq = 0;
601 602
@@ -613,13 +614,13 @@ bool afs_check_validity(struct afs_vnode *vnode)
613 vnode->cb_v_break != cb_v_break) { 614 vnode->cb_v_break != cb_v_break) {
614 vnode->cb_s_break = cb_s_break; 615 vnode->cb_s_break = cb_s_break;
615 vnode->cb_v_break = cb_v_break; 616 vnode->cb_v_break = cb_v_break;
616 need_clear = true; 617 need_clear = afs_cb_break_for_vsbreak;
617 valid = false; 618 valid = false;
618 } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { 619 } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
619 need_clear = true; 620 need_clear = afs_cb_break_for_zap;
620 valid = false; 621 valid = false;
621 } else if (vnode->cb_expires_at - 10 <= now) { 622 } else if (vnode->cb_expires_at - 10 <= now) {
622 need_clear = true; 623 need_clear = afs_cb_break_for_lapsed;
623 valid = false; 624 valid = false;
624 } else { 625 } else {
625 valid = true; 626 valid = true;
@@ -635,10 +636,12 @@ bool afs_check_validity(struct afs_vnode *vnode)
635 636
636 done_seqretry(&vnode->cb_lock, seq); 637 done_seqretry(&vnode->cb_lock, seq);
637 638
638 if (need_clear) { 639 if (need_clear != afs_cb_break_no_break) {
639 write_seqlock(&vnode->cb_lock); 640 write_seqlock(&vnode->cb_lock);
640 if (cb_break == vnode->cb_break) 641 if (cb_break == vnode->cb_break)
641 __afs_break_callback(vnode); 642 __afs_break_callback(vnode, need_clear);
643 else
644 trace_afs_cb_miss(&vnode->fid, need_clear);
642 write_sequnlock(&vnode->cb_lock); 645 write_sequnlock(&vnode->cb_lock);
643 valid = false; 646 valid = false;
644 } 647 }
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 8252d69bd3e4..4d9b3e9a422a 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -848,9 +848,9 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def;
848 * callback.c 848 * callback.c
849 */ 849 */
850extern void afs_init_callback_state(struct afs_server *); 850extern void afs_init_callback_state(struct afs_server *);
851extern void __afs_break_callback(struct afs_vnode *); 851extern void __afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason);
852extern void afs_break_callback(struct afs_vnode *); 852extern void afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason);
853extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*); 853extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break *);
854 854
855extern int afs_register_server_cb_interest(struct afs_vnode *, 855extern int afs_register_server_cb_interest(struct afs_vnode *,
856 struct afs_server_list *, unsigned int); 856 struct afs_server_list *, unsigned int);
@@ -1438,7 +1438,7 @@ static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc,
1438{ 1438{
1439 if (fc->ac.error == -ENOENT) { 1439 if (fc->ac.error == -ENOENT) {
1440 set_bit(AFS_VNODE_DELETED, &vnode->flags); 1440 set_bit(AFS_VNODE_DELETED, &vnode->flags);
1441 afs_break_callback(vnode); 1441 afs_break_callback(vnode, afs_cb_break_for_deleted);
1442 } 1442 }
1443} 1443}
1444 1444
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h
index 562f854ac4bf..34628e207849 100644
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -195,6 +195,17 @@ enum afs_flock_operation {
195 afs_flock_op_wake, 195 afs_flock_op_wake,
196}; 196};
197 197
198enum afs_cb_break_reason {
199 afs_cb_break_no_break,
200 afs_cb_break_for_callback,
201 afs_cb_break_for_deleted,
202 afs_cb_break_for_lapsed,
203 afs_cb_break_for_unlink,
204 afs_cb_break_for_vsbreak,
205 afs_cb_break_for_volume_callback,
206 afs_cb_break_for_zap,
207};
208
198#endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */ 209#endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */
199 210
200/* 211/*
@@ -374,6 +385,16 @@ enum afs_flock_operation {
374 EM(afs_flock_op_unlock, "UNLOCK ") \ 385 EM(afs_flock_op_unlock, "UNLOCK ") \
375 E_(afs_flock_op_wake, "WAKE ") 386 E_(afs_flock_op_wake, "WAKE ")
376 387
388#define afs_cb_break_reasons \
389 EM(afs_cb_break_no_break, "no-break") \
390 EM(afs_cb_break_for_callback, "break-cb") \
391 EM(afs_cb_break_for_deleted, "break-del") \
392 EM(afs_cb_break_for_lapsed, "break-lapsed") \
393 EM(afs_cb_break_for_unlink, "break-unlink") \
394 EM(afs_cb_break_for_vsbreak, "break-vs") \
395 EM(afs_cb_break_for_volume_callback, "break-v-cb") \
396 E_(afs_cb_break_for_zap, "break-zap")
397
377/* 398/*
378 * Export enum symbols via userspace. 399 * Export enum symbols via userspace.
379 */ 400 */
@@ -392,6 +413,7 @@ afs_io_errors;
392afs_file_errors; 413afs_file_errors;
393afs_flock_types; 414afs_flock_types;
394afs_flock_operations; 415afs_flock_operations;
416afs_cb_break_reasons;
395 417
396/* 418/*
397 * Now redefine the EM() and E_() macros to map the enums to the strings that 419 * Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -1171,6 +1193,53 @@ TRACE_EVENT(afs_get_tree,
1171 __entry->cell, __entry->volume, __entry->vid) 1193 __entry->cell, __entry->volume, __entry->vid)
1172 ); 1194 );
1173 1195
1196TRACE_EVENT(afs_cb_break,
1197 TP_PROTO(struct afs_fid *fid, unsigned int cb_break,
1198 enum afs_cb_break_reason reason, bool skipped),
1199
1200 TP_ARGS(fid, cb_break, reason, skipped),
1201
1202 TP_STRUCT__entry(
1203 __field_struct(struct afs_fid, fid )
1204 __field(unsigned int, cb_break )
1205 __field(enum afs_cb_break_reason, reason )
1206 __field(bool, skipped )
1207 ),
1208
1209 TP_fast_assign(
1210 __entry->fid = *fid;
1211 __entry->cb_break = cb_break;
1212 __entry->reason = reason;
1213 __entry->skipped = skipped;
1214 ),
1215
1216 TP_printk("%llx:%llx:%x b=%x s=%u %s",
1217 __entry->fid.vid, __entry->fid.vnode, __entry->fid.unique,
1218 __entry->cb_break,
1219 __entry->skipped,
1220 __print_symbolic(__entry->reason, afs_cb_break_reasons))
1221 );
1222
1223TRACE_EVENT(afs_cb_miss,
1224 TP_PROTO(struct afs_fid *fid, enum afs_cb_break_reason reason),
1225
1226 TP_ARGS(fid, reason),
1227
1228 TP_STRUCT__entry(
1229 __field_struct(struct afs_fid, fid )
1230 __field(enum afs_cb_break_reason, reason )
1231 ),
1232
1233 TP_fast_assign(
1234 __entry->fid = *fid;
1235 __entry->reason = reason;
1236 ),
1237
1238 TP_printk(" %llx:%llx:%x %s",
1239 __entry->fid.vid, __entry->fid.vnode, __entry->fid.unique,
1240 __print_symbolic(__entry->reason, afs_cb_break_reasons))
1241 );
1242
1174#endif /* _TRACE_AFS_H */ 1243#endif /* _TRACE_AFS_H */
1175 1244
1176/* This part must be outside protection */ 1245/* This part must be outside protection */