mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-08-09 06:14:34 +02:00
Add the debugfs and trace plumbing used to trigger and observe manual client reset. The reset interface exposes a trigger file for operator-initiated reset and a status file for tracking the most recent run. The tracepoints record scheduling, completion, and blocked caller behavior so reset progress can be diagnosed from the client side. debugfs layout under /sys/kernel/debug/ceph/<client>/reset/: trigger - write to initiate a manual reset status - read to see the most recent reset result The reset directory is cleaned up via debugfs_remove_recursive() on the parent, so individual file dentries are not stored. Tracepoints: ceph_client_reset_schedule - reset queued ceph_client_reset_complete - reset finished (success or failure) ceph_client_reset_blocked - caller blocked waiting for reset ceph_client_reset_unblocked - caller unblocked after reset All tracepoints use a null-safe access for monc.auth->global_id to guard against early-init or late-teardown edge cases. Signed-off-by: Alex Markuze <amarkuze@redhat.com> Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com> Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
302 lines
6.8 KiB
C
302 lines
6.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/* Ceph filesystem support module tracepoints
|
|
*
|
|
* Copyright (C) 2025 IONOS SE. All Rights Reserved.
|
|
* Written by Max Kellermann (max.kellermann@ionos.com)
|
|
*/
|
|
#undef TRACE_SYSTEM
|
|
#define TRACE_SYSTEM ceph
|
|
|
|
#if !defined(_TRACE_CEPH_H) || defined(TRACE_HEADER_MULTI_READ)
|
|
#define _TRACE_CEPH_H
|
|
|
|
#include <linux/tracepoint.h>
|
|
|
|
#define ceph_mdsc_suspend_reasons \
|
|
EM(ceph_mdsc_suspend_reason_no_mdsmap, "no-mdsmap") \
|
|
EM(ceph_mdsc_suspend_reason_no_active_mds, "no-active-mds") \
|
|
EM(ceph_mdsc_suspend_reason_rejected, "rejected") \
|
|
E_(ceph_mdsc_suspend_reason_session, "session")
|
|
|
|
#ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
|
#define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
|
|
|
#undef EM
|
|
#undef E_
|
|
#define EM(a, b) a,
|
|
#define E_(a, b) a
|
|
|
|
enum ceph_mdsc_suspend_reason { ceph_mdsc_suspend_reasons } __mode(byte);
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Export enum symbols via userspace.
|
|
*/
|
|
#undef EM
|
|
#undef E_
|
|
#define EM(a, b) TRACE_DEFINE_ENUM(a);
|
|
#define E_(a, b) TRACE_DEFINE_ENUM(a);
|
|
|
|
ceph_mdsc_suspend_reasons;
|
|
|
|
/*
|
|
* Now redefine the EM() and E_() macros to map the enums to the strings that
|
|
* will be printed in the output.
|
|
*/
|
|
#undef EM
|
|
#undef E_
|
|
#define EM(a, b) { a, b },
|
|
#define E_(a, b) { a, b }
|
|
|
|
TRACE_EVENT(ceph_mdsc_submit_request,
|
|
TP_PROTO(struct ceph_mds_client *mdsc,
|
|
struct ceph_mds_request *req),
|
|
|
|
TP_ARGS(mdsc, req),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(u64, tid)
|
|
__field(int, op)
|
|
__field(u64, ino)
|
|
__field(u64, snap)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
struct inode *inode;
|
|
|
|
__entry->tid = req->r_tid;
|
|
__entry->op = req->r_op;
|
|
|
|
inode = req->r_inode;
|
|
if (inode == NULL && req->r_dentry)
|
|
inode = d_inode(req->r_dentry);
|
|
|
|
if (inode) {
|
|
__entry->ino = ceph_ino(inode);
|
|
__entry->snap = ceph_snap(inode);
|
|
} else {
|
|
__entry->ino = __entry->snap = 0;
|
|
}
|
|
),
|
|
|
|
TP_printk("R=%llu op=%s ino=%llx,%llx",
|
|
__entry->tid,
|
|
ceph_mds_op_name(__entry->op),
|
|
__entry->ino, __entry->snap)
|
|
);
|
|
|
|
TRACE_EVENT(ceph_mdsc_suspend_request,
|
|
TP_PROTO(struct ceph_mds_client *mdsc,
|
|
struct ceph_mds_session *session,
|
|
struct ceph_mds_request *req,
|
|
enum ceph_mdsc_suspend_reason reason),
|
|
|
|
TP_ARGS(mdsc, session, req, reason),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(u64, tid)
|
|
__field(int, op)
|
|
__field(int, mds)
|
|
__field(enum ceph_mdsc_suspend_reason, reason)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->tid = req->r_tid;
|
|
__entry->op = req->r_op;
|
|
__entry->mds = session ? session->s_mds : -1;
|
|
__entry->reason = reason;
|
|
),
|
|
|
|
TP_printk("R=%llu op=%s reason=%s",
|
|
__entry->tid,
|
|
ceph_mds_op_name(__entry->op),
|
|
__print_symbolic(__entry->reason, ceph_mdsc_suspend_reasons))
|
|
);
|
|
|
|
TRACE_EVENT(ceph_mdsc_resume_request,
|
|
TP_PROTO(struct ceph_mds_client *mdsc,
|
|
struct ceph_mds_request *req),
|
|
|
|
TP_ARGS(mdsc, req),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(u64, tid)
|
|
__field(int, op)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->tid = req->r_tid;
|
|
__entry->op = req->r_op;
|
|
),
|
|
|
|
TP_printk("R=%llu op=%s",
|
|
__entry->tid,
|
|
ceph_mds_op_name(__entry->op))
|
|
);
|
|
|
|
TRACE_EVENT(ceph_mdsc_send_request,
|
|
TP_PROTO(struct ceph_mds_session *session,
|
|
struct ceph_mds_request *req),
|
|
|
|
TP_ARGS(session, req),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(u64, tid)
|
|
__field(int, op)
|
|
__field(int, mds)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->tid = req->r_tid;
|
|
__entry->op = req->r_op;
|
|
__entry->mds = session->s_mds;
|
|
),
|
|
|
|
TP_printk("R=%llu op=%s mds=%d",
|
|
__entry->tid,
|
|
ceph_mds_op_name(__entry->op),
|
|
__entry->mds)
|
|
);
|
|
|
|
TRACE_EVENT(ceph_mdsc_complete_request,
|
|
TP_PROTO(struct ceph_mds_client *mdsc,
|
|
struct ceph_mds_request *req),
|
|
|
|
TP_ARGS(mdsc, req),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(u64, tid)
|
|
__field(int, op)
|
|
__field(int, err)
|
|
__field(unsigned long, latency_ns)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->tid = req->r_tid;
|
|
__entry->op = req->r_op;
|
|
__entry->err = req->r_err;
|
|
__entry->latency_ns = req->r_end_latency - req->r_start_latency;
|
|
),
|
|
|
|
TP_printk("R=%llu op=%s err=%d latency_ns=%lu",
|
|
__entry->tid,
|
|
ceph_mds_op_name(__entry->op),
|
|
__entry->err,
|
|
__entry->latency_ns)
|
|
);
|
|
|
|
TRACE_EVENT(ceph_handle_caps,
|
|
TP_PROTO(struct ceph_mds_client *mdsc,
|
|
struct ceph_mds_session *session,
|
|
int op,
|
|
const struct ceph_vino *vino,
|
|
struct ceph_inode_info *inode,
|
|
u32 seq, u32 mseq, u32 issue_seq),
|
|
|
|
TP_ARGS(mdsc, session, op, vino, inode, seq, mseq, issue_seq),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(int, mds)
|
|
__field(int, op)
|
|
__field(u64, ino)
|
|
__field(u64, snap)
|
|
__field(u32, seq)
|
|
__field(u32, mseq)
|
|
__field(u32, issue_seq)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->mds = session->s_mds;
|
|
__entry->op = op;
|
|
__entry->ino = vino->ino;
|
|
__entry->snap = vino->snap;
|
|
__entry->seq = seq;
|
|
__entry->mseq = mseq;
|
|
__entry->issue_seq = issue_seq;
|
|
),
|
|
|
|
TP_printk("mds=%d op=%s vino=%llx.%llx seq=%u iseq=%u mseq=%u",
|
|
__entry->mds,
|
|
ceph_cap_op_name(__entry->op),
|
|
__entry->ino,
|
|
__entry->snap,
|
|
__entry->seq,
|
|
__entry->issue_seq,
|
|
__entry->mseq)
|
|
);
|
|
|
|
/*
|
|
* Client reset tracepoints - identify the client by its monitor-
|
|
* assigned global_id so traces remain meaningful when kernel pointer
|
|
* hashing is enabled.
|
|
*/
|
|
TRACE_EVENT(ceph_client_reset_schedule,
|
|
TP_PROTO(const struct ceph_mds_client *mdsc, const char *reason),
|
|
TP_ARGS(mdsc, reason),
|
|
TP_STRUCT__entry(
|
|
__field(u64, client_id)
|
|
__string(reason, reason ? reason : "")
|
|
),
|
|
TP_fast_assign(
|
|
__entry->client_id = mdsc->fsc->client->monc.auth ?
|
|
mdsc->fsc->client->monc.auth->global_id : 0;
|
|
__assign_str(reason);
|
|
),
|
|
TP_printk("client_id=%llu reason=%s",
|
|
__entry->client_id, __get_str(reason))
|
|
);
|
|
|
|
TRACE_EVENT(ceph_client_reset_complete,
|
|
TP_PROTO(const struct ceph_mds_client *mdsc, int ret),
|
|
TP_ARGS(mdsc, ret),
|
|
TP_STRUCT__entry(
|
|
__field(u64, client_id)
|
|
__field(int, ret)
|
|
),
|
|
TP_fast_assign(
|
|
__entry->client_id = mdsc->fsc->client->monc.auth ?
|
|
mdsc->fsc->client->monc.auth->global_id : 0;
|
|
__entry->ret = ret;
|
|
),
|
|
TP_printk("client_id=%llu ret=%d", __entry->client_id, __entry->ret)
|
|
);
|
|
|
|
TRACE_EVENT(ceph_client_reset_blocked,
|
|
TP_PROTO(const struct ceph_mds_client *mdsc, int blocked_count),
|
|
TP_ARGS(mdsc, blocked_count),
|
|
TP_STRUCT__entry(
|
|
__field(u64, client_id)
|
|
__field(int, blocked_count)
|
|
),
|
|
TP_fast_assign(
|
|
__entry->client_id = mdsc->fsc->client->monc.auth ?
|
|
mdsc->fsc->client->monc.auth->global_id : 0;
|
|
__entry->blocked_count = blocked_count;
|
|
),
|
|
TP_printk("client_id=%llu blocked_count=%d", __entry->client_id,
|
|
__entry->blocked_count)
|
|
);
|
|
|
|
TRACE_EVENT(ceph_client_reset_unblocked,
|
|
TP_PROTO(const struct ceph_mds_client *mdsc, int ret),
|
|
TP_ARGS(mdsc, ret),
|
|
TP_STRUCT__entry(
|
|
__field(u64, client_id)
|
|
__field(int, ret)
|
|
),
|
|
TP_fast_assign(
|
|
__entry->client_id = mdsc->fsc->client->monc.auth ?
|
|
mdsc->fsc->client->monc.auth->global_id : 0;
|
|
__entry->ret = ret;
|
|
),
|
|
TP_printk("client_id=%llu ret=%d", __entry->client_id, __entry->ret)
|
|
);
|
|
|
|
#undef EM
|
|
#undef E_
|
|
#endif /* _TRACE_CEPH_H */
|
|
|
|
/* This part must be outside protection */
|
|
#include <trace/define_trace.h>
|