summaryrefslogtreecommitdiff
path: root/include/trace
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-10-07 08:01:02 -1000
committerTejun Heo <tj@kernel.org>2026-10-07 08:01:02 -1000
commit92b542db38bf7cb4de583b2ca37febc549db0ce4 (patch)
tree30dcfdb338f7fdba597e1ec9314c2006df86f525 /include/trace
parentfee1265a725725dac0ff7459f912d69558798b36 (diff)
parentd1a4549a3645e55cc9ade09e360280590b3c9559 (diff)
downloadlinux-next-92b542db38bf7cb4de583b2ca37febc549db0ce4.tar.gz
linux-next-92b542db38bf7cb4de583b2ca37febc549db0ce4.zip
Merge branch 'for-7.3-fixes' into for-next
Diffstat (limited to 'include/trace')
-rw-r--r--include/trace/events/btrfs.h39
-rw-r--r--include/trace/events/cachefiles.h203
-rw-r--r--include/trace/events/ceph.h67
-rw-r--r--include/trace/events/damon.h8
-rw-r--r--include/trace/events/dma.h5
-rw-r--r--include/trace/events/f2fs.h23
-rw-r--r--include/trace/events/huge_memory.h2
-rw-r--r--include/trace/events/icmp.h15
-rw-r--r--include/trace/events/landlock.h1060
-rw-r--r--include/trace/events/lock.h10
-rw-r--r--include/trace/events/memory-failure.h6
-rw-r--r--include/trace/events/migrate.h11
-rw-r--r--include/trace/events/mmflags.h17
-rw-r--r--include/trace/events/mptcp.h6
-rw-r--r--include/trace/events/netfs.h30
-rw-r--r--include/trace/events/pagemap.h8
-rw-r--r--include/trace/events/qcom_geni_i2c.h82
-rw-r--r--include/trace/events/qcom_geni_se.h157
-rw-r--r--include/trace/events/qcom_geni_serial.h7
-rw-r--r--include/trace/events/rcu.h7
-rw-r--r--include/trace/events/sched_ext.h28
-rw-r--r--include/trace/events/timer.h2
-rw-r--r--include/trace/trace_events.h23
23 files changed, 1581 insertions, 235 deletions
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index 4c5c47c5edb7..6ecfab97c1a9 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -689,6 +689,41 @@ DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first,
TP_ARGS(inode, ordered)
);
+/*
+ * The writepage fixup worker deferred a block because this still-running
+ * ordered extent covers it.
+ */
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_writepage_fixup_defer,
+
+ TP_PROTO(const struct btrfs_inode *inode,
+ const struct btrfs_ordered_extent *ordered),
+
+ TP_ARGS(inode, ordered)
+);
+
+/* The writepage fixup worker reserved space for a block and set delalloc. */
+TRACE_EVENT(btrfs_writepage_fixup_reserve,
+
+ TP_PROTO(const struct btrfs_inode *inode, u64 start, u32 len),
+
+ TP_ARGS(inode, start, len),
+
+ TP_STRUCT__entry_btrfs(
+ __field( u64, ino )
+ __field( u64, start )
+ __field( u32, len )
+ ),
+
+ TP_fast_assign_btrfs(inode->root->fs_info,
+ __entry->ino = btrfs_ino(inode);
+ __entry->start = start;
+ __entry->len = len;
+ ),
+
+ TP_printk_btrfs("ino=%llu start=%llu len=%u",
+ __entry->ino, __entry->start, __entry->len)
+);
+
DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_split,
TP_PROTO(const struct btrfs_inode *inode,
@@ -1578,9 +1613,9 @@ TRACE_EVENT(btrfs_sync_log_enter,
__entry->log_transid_committed =
data_race(root->log_transid_committed);
__entry->log_committing =
- atomic_read(&root->log_commit[ctx->log_transid % 2]);
+ data_race(root->log_commit[ctx->log_transid % 2]);
__entry->log_committing_prev =
- atomic_read(&root->log_commit[(ctx->log_transid + 1) % 2]);
+ data_race(root->log_commit[(ctx->log_transid + 1) % 2]);
__entry->log_writers = atomic_read(&root->log_writers);
),
diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h
index 6e3b1424eea4..e3101410e8b2 100644
--- a/include/trace/events/cachefiles.h
+++ b/include/trace/events/cachefiles.h
@@ -31,10 +31,6 @@ enum cachefiles_obj_ref_trace {
cachefiles_obj_see_lookup_failed,
cachefiles_obj_see_withdraw_cookie,
cachefiles_obj_see_withdrawal,
- cachefiles_obj_get_ondemand_fd,
- cachefiles_obj_put_ondemand_fd,
- cachefiles_obj_get_read_req,
- cachefiles_obj_put_read_req,
};
enum fscache_why_object_killed {
@@ -129,11 +125,7 @@ enum cachefiles_error_trace {
EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \
EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \
EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \
- EM(cachefiles_obj_see_withdrawal, "SEE withdrawal") \
- EM(cachefiles_obj_get_ondemand_fd, "GET ondemand_fd") \
- EM(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd") \
- EM(cachefiles_obj_get_read_req, "GET read_req") \
- E_(cachefiles_obj_put_read_req, "PUT read_req")
+ E_(cachefiles_obj_see_withdrawal, "SEE withdrawal")
#define cachefiles_coherency_traces \
EM(cachefiles_coherency_check_aux, "BAD aux ") \
@@ -380,7 +372,7 @@ TRACE_EVENT(cachefiles_rename,
TRACE_EVENT(cachefiles_coherency,
TP_PROTO(struct cachefiles_object *obj,
ino_t ino,
- u64 disk_aux,
+ const void *disk_aux,
enum cachefiles_content content,
enum cachefiles_coherency_trace why),
@@ -397,12 +389,27 @@ TRACE_EVENT(cachefiles_coherency,
),
TP_fast_assign(
+ union {
+ __be16 s[4];
+ __be64 ll;
+ } x;
+
__entry->obj = obj->debug_id;
__entry->why = why;
__entry->content = content;
__entry->ino = ino;
__entry->aux = be64_to_cpup((__be64 *)obj->cookie->inline_aux);
- __entry->disk_aux = disk_aux;
+
+ /* cachefiles_xattr::data is 2-byte aligned but not 8-byte aligned. */
+ if (disk_aux) {
+ x.s[0] = ((__be16 *)disk_aux)[0];
+ x.s[1] = ((__be16 *)disk_aux)[1];
+ x.s[2] = ((__be16 *)disk_aux)[2];
+ x.s[3] = ((__be16 *)disk_aux)[3];
+ __entry->disk_aux = be64_to_cpu(x.ll);
+ } else {
+ __entry->disk_aux = 0;
+ }
),
TP_printk("o=%08x %s B=%llx c=%u aux=%llx dsk=%llx",
@@ -687,180 +694,6 @@ TRACE_EVENT(cachefiles_io_error,
__entry->error)
);
-TRACE_EVENT(cachefiles_ondemand_open,
- TP_PROTO(struct cachefiles_object *obj, struct cachefiles_msg *msg,
- struct cachefiles_open *load),
-
- TP_ARGS(obj, msg, load),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, msg_id)
- __field(unsigned int, object_id)
- __field(unsigned int, fd)
- __field(unsigned int, flags)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->msg_id = msg->msg_id;
- __entry->object_id = msg->object_id;
- __entry->fd = load->fd;
- __entry->flags = load->flags;
- ),
-
- TP_printk("o=%08x mid=%x oid=%x fd=%d f=%x",
- __entry->obj,
- __entry->msg_id,
- __entry->object_id,
- __entry->fd,
- __entry->flags)
- );
-
-TRACE_EVENT(cachefiles_ondemand_copen,
- TP_PROTO(struct cachefiles_object *obj, unsigned int msg_id,
- long len),
-
- TP_ARGS(obj, msg_id, len),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, msg_id)
- __field(long, len)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->msg_id = msg_id;
- __entry->len = len;
- ),
-
- TP_printk("o=%08x mid=%x l=%lx",
- __entry->obj,
- __entry->msg_id,
- __entry->len)
- );
-
-TRACE_EVENT(cachefiles_ondemand_close,
- TP_PROTO(struct cachefiles_object *obj, struct cachefiles_msg *msg),
-
- TP_ARGS(obj, msg),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, msg_id)
- __field(unsigned int, object_id)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->msg_id = msg->msg_id;
- __entry->object_id = msg->object_id;
- ),
-
- TP_printk("o=%08x mid=%x oid=%x",
- __entry->obj,
- __entry->msg_id,
- __entry->object_id)
- );
-
-TRACE_EVENT(cachefiles_ondemand_read,
- TP_PROTO(struct cachefiles_object *obj, struct cachefiles_msg *msg,
- struct cachefiles_read *load),
-
- TP_ARGS(obj, msg, load),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, msg_id)
- __field(unsigned int, object_id)
- __field(loff_t, start)
- __field(size_t, len)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->msg_id = msg->msg_id;
- __entry->object_id = msg->object_id;
- __entry->start = load->off;
- __entry->len = load->len;
- ),
-
- TP_printk("o=%08x mid=%x oid=%x s=%llx l=%zx",
- __entry->obj,
- __entry->msg_id,
- __entry->object_id,
- __entry->start,
- __entry->len)
- );
-
-TRACE_EVENT(cachefiles_ondemand_cread,
- TP_PROTO(struct cachefiles_object *obj, unsigned int msg_id),
-
- TP_ARGS(obj, msg_id),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, msg_id)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->msg_id = msg_id;
- ),
-
- TP_printk("o=%08x mid=%x",
- __entry->obj,
- __entry->msg_id)
- );
-
-TRACE_EVENT(cachefiles_ondemand_fd_write,
- TP_PROTO(struct cachefiles_object *obj, struct inode *backer,
- loff_t start, size_t len),
-
- TP_ARGS(obj, backer, start, len),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, backer)
- __field(loff_t, start)
- __field(size_t, len)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->backer = backer->i_ino;
- __entry->start = start;
- __entry->len = len;
- ),
-
- TP_printk("o=%08x iB=%x s=%llx l=%zx",
- __entry->obj,
- __entry->backer,
- __entry->start,
- __entry->len)
- );
-
-TRACE_EVENT(cachefiles_ondemand_fd_release,
- TP_PROTO(struct cachefiles_object *obj, int object_id),
-
- TP_ARGS(obj, object_id),
-
- TP_STRUCT__entry(
- __field(unsigned int, obj)
- __field(unsigned int, object_id)
- ),
-
- TP_fast_assign(
- __entry->obj = obj ? obj->debug_id : 0;
- __entry->object_id = object_id;
- ),
-
- TP_printk("o=%08x oid=%x",
- __entry->obj,
- __entry->object_id)
- );
-
#endif /* _TRACE_CACHEFILES_H */
/* This part must be outside protection */
diff --git a/include/trace/events/ceph.h b/include/trace/events/ceph.h
index 08cb0659fbfc..1b990632f62b 100644
--- a/include/trace/events/ceph.h
+++ b/include/trace/events/ceph.h
@@ -226,6 +226,73 @@ TRACE_EVENT(ceph_handle_caps,
__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 */
diff --git a/include/trace/events/damon.h b/include/trace/events/damon.h
index 78388538acf4..8851727ae162 100644
--- a/include/trace/events/damon.h
+++ b/include/trace/events/damon.h
@@ -78,9 +78,11 @@ TRACE_EVENT_CONDITION(damos_before_apply,
TP_PROTO(unsigned int context_idx, unsigned int scheme_idx,
unsigned int target_idx, struct damon_region *r,
- unsigned int nr_regions, bool do_trace),
+ unsigned int nr_accesses, unsigned int nr_regions,
+ bool do_trace),
- TP_ARGS(context_idx, scheme_idx, target_idx, r, nr_regions, do_trace),
+ TP_ARGS(context_idx, scheme_idx, target_idx, r, nr_accesses,
+ nr_regions, do_trace),
TP_CONDITION(do_trace),
@@ -101,7 +103,7 @@ TRACE_EVENT_CONDITION(damos_before_apply,
__entry->target_idx = target_idx;
__entry->start = r->ar.start;
__entry->end = r->ar.end;
- __entry->nr_accesses = r->nr_accesses_bp / 10000;
+ __entry->nr_accesses = nr_accesses;
__entry->age = r->age;
__entry->nr_regions = nr_regions;
),
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index 31c9ddf72c9d..b06d8f99922d 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -35,7 +35,8 @@ TRACE_DEFINE_ENUM(DMA_NONE);
{ DMA_ATTR_MMIO, "MMIO" }, \
{ DMA_ATTR_DEBUGGING_IGNORE_CACHELINES, "CACHELINES_OVERLAP" }, \
{ DMA_ATTR_REQUIRE_COHERENT, "REQUIRE_COHERENT" }, \
- { DMA_ATTR_CC_SHARED, "CC_SHARED" })
+ { DMA_ATTR_CC_SHARED, "CC_SHARED" }, \
+ { __DMA_ATTR_ALLOC_CC_SHARED, "ALLOC_CC_SHARED" })
DECLARE_EVENT_CLASS(dma_map,
TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
@@ -133,7 +134,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class,
TP_fast_assign(
__assign_str(device);
__entry->virt_addr = virt_addr;
- __entry->dma_addr = dma_addr;
+ __entry->dma_addr = virt_addr ? dma_addr : 0;
__entry->size = size;
__entry->flags = flags;
__entry->dir = dir;
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 270c1a2c24c4..d53be932df01 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -191,7 +191,8 @@ TRACE_DEFINE_ENUM(CP_PHASE_FINISH_CHECKPOINT);
{ LOCK_NAME_NODE_WRITE, "node_write" }, \
{ LOCK_NAME_GC_LOCK, "gc_lock" }, \
{ LOCK_NAME_CP_GLOBAL, "cp_global" }, \
- { LOCK_NAME_IO_RWSEM, "io_rwsem" })
+ { LOCK_NAME_IO_RWSEM, "io_rwsem" }, \
+ { LOCK_NAME_NAT_TREE_LOCK, "nat_tree_lock" })
struct f2fs_sb_info;
struct f2fs_io_info;
@@ -2114,6 +2115,14 @@ DEFINE_EVENT(f2fs_zip_end, f2fs_decompress_pages_end,
);
#ifdef CONFIG_F2FS_IOSTAT
+/*
+ * Number of read folio order buckets emitted by the f2fs_iostat tracepoint.
+ * TP_printk() cannot loop, so the field count is fixed here and must be >=
+ * the largest possible NR_PAGE_ORDERS (14 on arm64 with 64K pages). The
+ * BUILD_BUG_ON() in f2fs_update_read_folio_count() enforces this.
+ */
+#define F2FS_IOSTAT_RD_FOLIO_ORDERS 16
+
TRACE_EVENT(f2fs_iostat,
TP_PROTO(struct f2fs_sb_info *sbi, unsigned long long *iostat,
@@ -2151,7 +2160,7 @@ TRACE_EVENT(f2fs_iostat,
__field(unsigned long long, fs_mrio)
__field(unsigned long long, fs_discard)
__field(unsigned long long, fs_reset_zone)
- __array(unsigned long long, read_folio_count, 11)
+ __array(unsigned long long, read_folio_count, F2FS_IOSTAT_RD_FOLIO_ORDERS)
),
TP_fast_assign(
@@ -2186,7 +2195,8 @@ TRACE_EVENT(f2fs_iostat,
__entry->fs_reset_zone = iostat[FS_ZONE_RESET_IO];
memset(__entry->read_folio_count, 0, sizeof(__entry->read_folio_count));
memcpy(__entry->read_folio_count, read_folio_count,
- sizeof(unsigned long long) * min_t(int, NR_PAGE_ORDERS, 11));
+ sizeof(unsigned long long) *
+ min_t(int, NR_PAGE_ORDERS, F2FS_IOSTAT_RD_FOLIO_ORDERS));
),
TP_printk("dev = (%d,%d), "
@@ -2201,7 +2211,8 @@ TRACE_EVENT(f2fs_iostat,
"fs [data=%llu, (gc_data=%llu, cdata=%llu), "
"node=%llu, meta=%llu], "
"read_folio_count [0=%llu, 1=%llu, 2=%llu, 3=%llu, 4=%llu, "
- "5=%llu, 6=%llu, 7=%llu, 8=%llu, 9=%llu, 10=%llu]",
+ "5=%llu, 6=%llu, 7=%llu, 8=%llu, 9=%llu, 10=%llu, 11=%llu, "
+ "12=%llu, 13=%llu, 14=%llu, 15=%llu]",
show_dev(__entry->dev), __entry->app_wio, __entry->app_dio,
__entry->app_bio, __entry->app_mio, __entry->app_bcdio,
__entry->app_mcdio, __entry->fs_dio, __entry->fs_cdio,
@@ -2218,7 +2229,9 @@ TRACE_EVENT(f2fs_iostat,
__entry->read_folio_count[4], __entry->read_folio_count[5],
__entry->read_folio_count[6], __entry->read_folio_count[7],
__entry->read_folio_count[8], __entry->read_folio_count[9],
- __entry->read_folio_count[10])
+ __entry->read_folio_count[10], __entry->read_folio_count[11],
+ __entry->read_folio_count[12], __entry->read_folio_count[13],
+ __entry->read_folio_count[14], __entry->read_folio_count[15])
);
#ifndef __F2FS_IOSTAT_LATENCY_TYPE
diff --git a/include/trace/events/huge_memory.h b/include/trace/events/huge_memory.h
index 291fae364c62..5a48c5406cce 100644
--- a/include/trace/events/huge_memory.h
+++ b/include/trace/events/huge_memory.h
@@ -16,7 +16,7 @@
EM( SCAN_EXCEED_SWAP_PTE, "exceed_swap_pte") \
EM( SCAN_EXCEED_SHARED_PTE, "exceed_shared_pte") \
EM( SCAN_PTE_NON_PRESENT, "pte_non_present") \
- EM( SCAN_PTE_UFFD_WP, "pte_uffd_wp") \
+ EM( SCAN_PTE_UFFD, "pte_uffd_wp") \
EM( SCAN_PTE_MAPPED_HUGEPAGE, "pte_mapped_hugepage") \
EM( SCAN_LACK_REFERENCED_PAGE, "lack_referenced_page") \
EM( SCAN_PAGE_NULL, "page_null") \
diff --git a/include/trace/events/icmp.h b/include/trace/events/icmp.h
index 31559796949a..6937b778ae54 100644
--- a/include/trace/events/icmp.h
+++ b/include/trace/events/icmp.h
@@ -27,24 +27,27 @@ TRACE_EVENT(icmp_send,
TP_fast_assign(
struct iphdr *iph = ip_hdr(skb);
- struct udphdr *uh = udp_hdr(skb);
- int proto_4 = iph->protocol;
+ struct udphdr _uh, *uh = NULL;
__be32 *p32;
__entry->skbaddr = skb;
__entry->type = type;
__entry->code = code;
- if (proto_4 != IPPROTO_UDP || (u8 *)uh < skb->head ||
- (u8 *)uh + sizeof(struct udphdr)
- > skb_tail_pointer(skb)) {
+ if (iph->protocol == IPPROTO_UDP)
+ uh = skb_header_pointer(skb,
+ skb_network_offset(skb) +
+ (iph->ihl << 2),
+ sizeof(_uh), &_uh);
+
+ if (!uh) {
__entry->sport = 0;
__entry->dport = 0;
__entry->ulen = 0;
} else {
__entry->sport = ntohs(uh->source);
__entry->dport = ntohs(uh->dest);
- __entry->ulen = ntohs(uh->len);
+ __entry->ulen = udp_get_len_short(uh);
}
p32 = (__be32 *) __entry->saddr;
diff --git a/include/trace/events/landlock.h b/include/trace/events/landlock.h
new file mode 100644
index 000000000000..3a43638c9bc2
--- /dev/null
+++ b/include/trace/events/landlock.h
@@ -0,0 +1,1060 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright © 2025 Microsoft Corporation
+ * Copyright © 2026 Cloudflare, Inc.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM landlock
+
+#if !defined(_TRACE_LANDLOCK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_LANDLOCK_H
+
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/landlock.h>
+#include <linux/socket.h>
+#include <linux/string.h>
+#include <linux/string_helpers.h>
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+#include <net/af_unix.h>
+
+enum landlock_request_type;
+struct dentry;
+struct landlock_blockers;
+struct landlock_domain;
+struct landlock_hierarchy;
+struct landlock_rule;
+struct landlock_ruleset;
+struct path;
+struct sock;
+struct task_struct;
+
+static_assert(sizeof(access_mask_t) <= sizeof(u64));
+
+TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_FS_CHANGE_TOPOLOGY);
+TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_FS_ACCESS);
+TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_NET_ACCESS);
+
+#ifdef CREATE_TRACE_POINTS
+
+/* About 6 KiB, leaving about 2 KiB for sibling helpers and fixed fields. */
+#define TRACE_UNTRUSTED_STR_OUTPUT_SIZE \
+ (TRACE_SEQ_BUFFER_SIZE - TRACE_SEQ_BUFFER_SIZE / 4)
+
+/*
+ * A raw UTF-8 ellipsis (…) marks truncation and cannot collide with escaped
+ * input: ESCAPE_NAP renders every non-ASCII input byte in octal.
+ */
+#define TRACE_TRUNCATION_MARKER "\xe2\x80\xa6"
+
+/*
+ * Escapes @len bytes of an untrusted string into the trace sequence @p so it
+ * cannot inject field separators or control characters into the ftrace text
+ * output, and can be unambiguously recovered. Called from the TP_printk() of
+ * the tracepoints that expose paths and process names. @len is passed by the
+ * caller (rather than derived with strlen()) so a name that is not
+ * NUL-terminated or carries embedded NUL bytes (an abstract socket name) is
+ * escaped in full instead of being truncated at the first NUL.
+ *
+ * Strings that exceed the output limit retain the largest complete escaped
+ * prefix followed by the truncation marker.
+ *
+ * Return: a pointer into @p's buffer, or NULL if @src is NULL or the fixed
+ * output reservation is unavailable.
+ */
+static inline const char *
+__trace_print_untrusted_str(struct trace_seq *p, const char *src, size_t len)
+{
+ const unsigned int escape_flags = ESCAPE_SPACE | ESCAPE_SPECIAL |
+ ESCAPE_NAP | ESCAPE_APPEND |
+ ESCAPE_OCTAL;
+ const size_t marker_len = sizeof(TRACE_TRUNCATION_MARKER) - 1;
+ size_t buf_size, prefix_len, prefix_size;
+ int escaped_size;
+ char *buf;
+ const char *ret;
+
+ buf_size = seq_buf_get_buf(&p->seq, &buf);
+ if (!src || buf_size < TRACE_UNTRUSTED_STR_OUTPUT_SIZE)
+ return NULL;
+
+ ret = trace_seq_buffer_ptr(p);
+ escaped_size = string_escape_mem(src, len, buf,
+ TRACE_UNTRUSTED_STR_OUTPUT_SIZE,
+ escape_flags, " ='\"\\");
+ if (likely(escaped_size < TRACE_UNTRUSTED_STR_OUTPUT_SIZE)) {
+ seq_buf_commit(&p->seq, escaped_size);
+ trace_seq_putc(p, 0);
+ return ret;
+ }
+
+ prefix_len = 0;
+ prefix_size = 0;
+ while (prefix_len < len) {
+ const char *const src_char = src + prefix_len;
+ int char_size;
+
+ char_size = string_escape_mem(src_char, 1, NULL, 0,
+ escape_flags, " ='\"\\");
+ if (char_size > TRACE_UNTRUSTED_STR_OUTPUT_SIZE - marker_len -
+ 1 - prefix_size)
+ break;
+ prefix_size += char_size;
+ prefix_len++;
+ }
+
+ escaped_size = string_escape_mem(src, prefix_len, buf, prefix_size,
+ escape_flags, " ='\"\\");
+ if (WARN_ON_ONCE(escaped_size != prefix_size))
+ return NULL;
+ memcpy(buf + prefix_size, TRACE_TRUNCATION_MARKER, marker_len);
+ seq_buf_commit(&p->seq, prefix_size + marker_len);
+ trace_seq_putc(p, 0);
+ return ret;
+}
+
+/*
+ * Fills the dense per-domain-layer array layers (one access mask per layer,
+ * indexed by level - 1) from rule's sparse layer stack, keeping only the
+ * requested rights (access_request). Layers with no matching rule entry get
+ * a zero mask. Shared by the check_rule_inode and check_rule_net_port events.
+ *
+ * rule->layers is sorted by ascending level, with levels in the domain's
+ * [1, num_layers] range (see landlock_merge_ruleset()), so every entry maps
+ * to a slot. A leftover entry would be a malformed rule; the zero-filled
+ * slots keep the output and the array bounds safe regardless.
+ */
+static inline void
+__trace_landlock_fill_layers(access_mask_t *const layers,
+ const size_t num_layers,
+ const struct landlock_rule *const rule,
+ const access_mask_t access_request)
+{
+ size_t i = 0;
+
+ for (size_t level = 1; level <= num_layers; level++) {
+ access_mask_t grants = 0;
+
+ if (i < rule->num_layers && level == rule->layers[i].level) {
+ grants = rule->layers[i].access & access_request;
+ i++;
+ }
+ layers[level - 1] = grants;
+ }
+
+ /* A leftover entry means an out-of-range or unsorted rule level. */
+ WARN_ON_ONCE(i < rule->num_layers);
+}
+
+/*
+ * Renders the dense per-domain-layer access array as symbolic flag names for
+ * the grants field: layers wrapped in "{}", flags within a layer joined by
+ * "|", layers separated by ",", an empty layer rendered as nothing.
+ * Open-codes the flag walk because trace_print_flags_seq() NUL-terminates per
+ * call and so cannot be chained into a single field. The shared names table
+ * covers every access right, so masked bits are always named. Returns the
+ * trace_seq position like __print_flags().
+ */
+static inline const char *__trace_landlock_print_layers(
+ struct trace_seq *p, const access_mask_t *const layers,
+ const size_t num_layers, const struct trace_print_flags *const names,
+ const size_t names_size)
+{
+ const char *const ret = trace_seq_buffer_ptr(p);
+
+ trace_seq_putc(p, '{');
+ for (size_t i = 0; i < num_layers; i++) {
+ access_mask_t mask = layers[i];
+ bool first = true;
+
+ if (i)
+ trace_seq_putc(p, ',');
+ for (size_t j = 0; mask && j < names_size; j++) {
+ if ((mask & names[j].mask) != names[j].mask)
+ continue;
+ if (!first)
+ trace_seq_putc(p, '|');
+ trace_seq_puts(p, names[j].name);
+ mask &= ~names[j].mask;
+ first = false;
+ }
+ }
+ trace_seq_putc(p, '}');
+ trace_seq_putc(p, 0);
+ return ret;
+}
+
+#endif /* CREATE_TRACE_POINTS */
+
+/* clang-format off */
+
+/* Maps a shared _LANDLOCK_*_NAMES entry to a __print_flags() pair. */
+#define _LANDLOCK_NAME_ENTRY(mask, name) { mask, name }
+
+#define _LANDLOCK_FS_BLOCKER_TYPE_NAMES \
+ { LANDLOCK_REQUEST_FS_CHANGE_TOPOLOGY, "change_topology" }
+
+/**
+ * DOC: Landlock trace events
+ *
+ * These guarantees and constraints hold for every Landlock tracepoint.
+ * A new tracepoint must uphold them, and an eBPF consumer can rely on
+ * them.
+ *
+ * Decision context
+ * ~~~~~~~~~~~~~~~~
+ *
+ * A denial event identifies the domain whose policy denied the request, the
+ * Landlock operation and policy object that were checked, and the blocker or
+ * domain relationship responsible for the denial. When tracing starts with
+ * sandbox construction, ruleset and domain events provide the policy history
+ * needed to interpret these identifiers. The denying domain is the subject
+ * that enforced the policy, not necessarily current. Generic tracepoints can
+ * provide additional operational context.
+ *
+ * Lifecycle consistency
+ * ~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Lifecycle emission is balanced: a creation event always has a matching
+ * deallocation event and vice versa. A consumer that observes an object's
+ * complete lifetime can model it from this pair; one that attaches late or
+ * loses exported records must reconcile incomplete state. A creation event
+ * fires while the object is still private to the calling thread
+ * (landlock_create_ruleset fires before the ruleset's file descriptor is
+ * installed, so it cannot race a concurrent :manpage:`close(2)`); if fd
+ * installation later fails and the ruleset is freed, free_ruleset still
+ * fires, keeping the pair balanced. The domain pair (create_domain and
+ * free_domain) is balanced the same way: create_domain fires when the
+ * domain is created (under the ruleset lock, before thread-sync), and
+ * free_domain fires when it is freed. A rare thread-sync failure aborts
+ * the just-created domain, which then emits both events (its creation, then
+ * an immediate free). Denial events fire only for denials that actually
+ * happen.
+ *
+ * Pointer access
+ * ~~~~~~~~~~~~~~
+ *
+ * All pointer arguments in TP_PROTO are guaranteed non-NULL by the
+ * caller, but pointers reached through them may still be NULL (e.g.,
+ * hierarchy->parent at a root domain) and must be checked. eBPF programs
+ * read these pointers via BTF for richer introspection than the
+ * TP_STRUCT__entry fields, which serve TP_printk display only.
+ *
+ * Mutable object pointers are passed while the caller holds the object's
+ * lock, so TP_fast_assign and a BTF reader see the exact object the event
+ * reports, a snapshot no concurrent writer can change: add_rule holds the
+ * modified ruleset's lock, and create_domain holds the ruleset lock across
+ * the emission (before the thread-sync wait) so the inspected ruleset is
+ * the one merged into the domain. Objects immutable at the emission site
+ * (a domain after creation, a hierarchy at its last reference) need no
+ * lock. A few values that no held lock protects are a best-effort
+ * lockless snapshot instead: a task's comm, and the deny_access_net struct
+ * sock (whose network hook holds no socket lock), matching how the sched
+ * and signal trace events sample comm.
+ *
+ * Field encoding
+ * ~~~~~~~~~~~~~~
+ *
+ * Fields that mirror the Landlock UAPI preserve their widths and endianness
+ * (e.g. network ports are u64 in host endianness, like
+ * landlock_net_port_attr.port). Per-event details, such as where a value
+ * is byte-swapped, live in the field's own kdoc.
+ *
+ * Rule-check fields
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * The check_rule events fire during an access check, once per matching
+ * rule, before the final allow-or-deny verdict. They share domain (the
+ * enforcing domain being evaluated), access_request (the access mask being
+ * checked), and rule (the matching rule, with per-layer access masks).
+ *
+ * Denial fields
+ * ~~~~~~~~~~~~~
+ *
+ * Every denial event shares three fields. domain is the ID of the
+ * innermost domain that blocked the access. same_exec tells whether the
+ * current task is the same executable that entered that domain. logged is
+ * the domain's audit-logging decision for this denial (its log_status is
+ * enabled and the per-execution flag selected by same_exec is set); a
+ * stateless ftrace filter can select the denials the domain submits to
+ * audit with logged==1, without reconstructing it from the per-execution
+ * log flags. Denial events order their fields as domain, same_exec,
+ * logged, then blockers (deny_access events only), then the type-specific
+ * object fields, then any variable-length field.
+ *
+ * Relational referents
+ * ~~~~~~~~~~~~~~~~~~~~~
+ *
+ * A scope or ptrace verdict compares two domains, so the other party's
+ * domain is part of the decision context. It is exposed as a scalar
+ * domain ID (0 when that party is unsandboxed): target_domain (signal),
+ * peer_domain (abstract unix socket), tracee_domain (ptrace). With both
+ * IDs in the stream, a consumer that tracked domain creation can relate
+ * the two parties without kernel-internal state. The ID is a scalar
+ * snapshot, not a live domain pointer that could dangle: an optional
+ * relational referent is a scalar (0 sentinel), not a nullable pointer.
+ * Nonzero IDs are unique within one boot. For ptrace, same_exec instead
+ * describes the tracer, even for
+ * PTRACE_TRACEME, and may differ from the current task.
+ *
+ * Blocker fields
+ * ~~~~~~~~~~~~~~
+ *
+ * The filesystem and network blocker arguments identify the request type
+ * and carry its final missing access subset when applicable. The type
+ * determines how to interpret the access value.
+ */
+
+/*
+ * Prints a per-layer access mask array (the dynamic array @array) as symbolic
+ * flag names using the shared @flag_names list (a _LANDLOCK_*_NAMES macro).
+ * Stays outside CREATE_TRACE_POINTS: TP_printk is expanded in the print-output
+ * pass where that macro is undefined.
+ */
+#define __print_landlock_layers(array, flag_names...) \
+ ({ \
+ static const struct trace_print_flags __layer_names[] = { \
+ flag_names \
+ }; \
+ __trace_landlock_print_layers( \
+ p, __get_dynamic_array(array), \
+ __get_dynamic_array_len(array) / \
+ sizeof(access_mask_t), \
+ __layer_names, ARRAY_SIZE(__layer_names)); \
+ })
+
+/**
+ * landlock_create_ruleset - New ruleset created
+ *
+ * @ruleset: Newly created ruleset (never NULL); not yet shared via an fd,
+ * so no lock is needed.
+ *
+ * Emitted by sys_landlock_create_ruleset() while the new ruleset is still
+ * private to the calling thread, before its file descriptor is installed,
+ * so it cannot race a concurrent :manpage:`close(2)`. Balanced by a
+ * matching landlock_free_ruleset event.
+ */
+TRACE_EVENT(landlock_create_ruleset,
+
+ TP_PROTO(const struct landlock_ruleset *ruleset),
+
+ TP_ARGS(ruleset),
+
+ TP_STRUCT__entry(
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ __field( access_mask_t, handled_fs )
+ __field( access_mask_t, handled_net )
+ __field( access_mask_t, scoped )
+ ),
+
+ TP_fast_assign(
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ __entry->handled_fs = ruleset->handled_masks.fs;
+ __entry->handled_net = ruleset->handled_masks.net;
+ __entry->scoped = ruleset->handled_masks.scope;
+ ),
+
+ TP_printk("ruleset=%llx.%llu handled_fs=%s handled_net=%s scoped=%s",
+ __entry->ruleset_id, __entry->ruleset_version,
+ __print_flags(__entry->handled_fs, "|", _LANDLOCK_ACCESS_FS_NAMES),
+ __print_flags(__entry->handled_net, "|", _LANDLOCK_ACCESS_NET_NAMES),
+ __print_flags(__entry->scoped, "|", _LANDLOCK_SCOPE_NAMES))
+);
+
+/**
+ * landlock_free_ruleset - Ruleset freed
+ *
+ * @ruleset: Ruleset being freed (never NULL); at its last reference, so no
+ * lock is needed.
+ *
+ * Emitted when a ruleset's last reference is dropped (typically when
+ * the creating process closes the ruleset file descriptor). Fires even
+ * when file-descriptor installation failed after creation, keeping the
+ * create/free pair balanced.
+ */
+TRACE_EVENT(landlock_free_ruleset,
+
+ TP_PROTO(const struct landlock_ruleset *ruleset),
+
+ TP_ARGS(ruleset),
+
+ TP_STRUCT__entry(
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ ),
+
+ TP_fast_assign(
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ ),
+
+ TP_printk("ruleset=%llx.%llu",
+ __entry->ruleset_id, __entry->ruleset_version)
+);
+
+/**
+ * landlock_add_rule_path_beneath - Path-beneath rule added to a ruleset
+ *
+ * @ruleset: Source ruleset (never NULL).
+ * @flags: Complete validated landlock_add_rule_flags value supplied by this
+ * successful call, not the rule's accumulated quiet state.
+ * @access_rights: Canonical per-call access mask passed to
+ * landlock_insert_rule() after normalization, not the raw
+ * sys_landlock_add_rule() argument or accumulated rule.
+ * @path: Filesystem path for the rule (never NULL).
+ * @pathname: Resolved absolute path string (never NULL; error placeholder
+ * on resolution failure).
+ *
+ * Emitted by sys_landlock_add_rule() under the modified ruleset's lock, so
+ * the reported ruleset is a stable snapshot that no concurrent writer can
+ * change.
+ */
+TRACE_EVENT(landlock_add_rule_path_beneath,
+
+ TP_PROTO(const struct landlock_ruleset *ruleset, u32 flags,
+ u64 access_rights, const struct path *path,
+ const char *pathname),
+
+ TP_ARGS(ruleset, flags, access_rights, path, pathname),
+
+ TP_STRUCT__entry(
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ __field( access_mask_t, access_rights )
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __string( pathname, pathname )
+ ),
+
+ TP_fast_assign(
+ lockdep_assert_held(&ruleset->lock);
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ __entry->access_rights = access_rights;
+ __entry->dev = path->dentry->d_sb->s_dev;
+ /*
+ * The inode number may not be the user-visible one,
+ * but it will be the same used by audit.
+ */
+ __entry->ino = d_backing_inode(path->dentry)->i_ino;
+ __assign_str(pathname);
+ ),
+
+ TP_printk("ruleset=%llx.%llu access_rights=%s dev=%u:%u ino=%lu path=%s",
+ __entry->ruleset_id, __entry->ruleset_version,
+ __print_flags(__entry->access_rights, "|", _LANDLOCK_ACCESS_FS_NAMES),
+ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino,
+ __trace_print_untrusted_str(p, __get_str(pathname),
+ __get_dynamic_array_len(pathname) - 1))
+);
+
+/**
+ * landlock_add_rule_net_port - Network-port rule added to a ruleset
+ *
+ * @ruleset: Source ruleset (never NULL).
+ * @flags: Complete validated landlock_add_rule_flags value supplied by this
+ * successful call, not the rule's accumulated quiet state.
+ * @access_rights: Canonical per-call access mask passed to
+ * landlock_insert_rule() after normalization, not the raw
+ * sys_landlock_add_rule() argument or accumulated rule.
+ * @port: Network port in host endianness, forwarded directly from
+ * &landlock_net_port_attr.port.
+ *
+ * Emitted by sys_landlock_add_rule() under the modified ruleset's lock, so
+ * the reported ruleset is a stable snapshot that no concurrent writer can
+ * change.
+ */
+TRACE_EVENT(landlock_add_rule_net_port,
+
+ TP_PROTO(const struct landlock_ruleset *ruleset, u32 flags,
+ u64 access_rights, u64 port),
+
+ TP_ARGS(ruleset, flags, access_rights, port),
+
+ TP_STRUCT__entry(
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ __field( access_mask_t, access_rights )
+ __field( u64, port )
+ ),
+
+ TP_fast_assign(
+ lockdep_assert_held(&ruleset->lock);
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ __entry->access_rights = access_rights;
+ __entry->port = port;
+ ),
+
+ TP_printk("ruleset=%llx.%llu access_rights=%s port=%llu",
+ __entry->ruleset_id, __entry->ruleset_version,
+ __print_flags(__entry->access_rights, "|", _LANDLOCK_ACCESS_NET_NAMES),
+ __entry->port)
+);
+
+/**
+ * landlock_create_domain - New domain created
+ *
+ * @domain: Newly created domain (never NULL, immutable after creation).
+ * @domain->hierarchy->id is its unique ID, shared with the
+ * landlock_enforce_domain and landlock_free_domain events;
+ * @domain->hierarchy->details holds the requesting process.
+ * @ruleset: Source ruleset frozen into the domain (never NULL). The
+ * ruleset lock is held across the emission, so a BPF program
+ * reading it via BTF sees the exact merged ruleset;
+ * @ruleset->id / @ruleset->version identify it.
+ *
+ * Emitted by sys_landlock_restrict_self() once, in the requesting
+ * thread's context, right after the merge and before thread-sync. The
+ * flags-only path (ruleset_fd == -1) creates no domain and does not
+ * emit this event. Paired with the per-thread landlock_enforce_domain
+ * (join on @domain->hierarchy->id) and balanced by a matching
+ * landlock_free_domain event.
+ */
+TRACE_EVENT(landlock_create_domain,
+
+ TP_PROTO(const struct landlock_domain *domain,
+ const struct landlock_ruleset *ruleset),
+
+ TP_ARGS(domain, ruleset),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( u64, parent_id )
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ ),
+
+ TP_fast_assign(
+ lockdep_assert_held(&ruleset->lock);
+ __entry->domain_id = domain->hierarchy->id;
+ __entry->parent_id = domain->hierarchy->parent ?
+ domain->hierarchy->parent->id : 0;
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ ),
+
+ TP_printk("domain=%llx parent=%llx ruleset=%llx.%llu",
+ __entry->domain_id, __entry->parent_id,
+ __entry->ruleset_id, __entry->ruleset_version)
+);
+
+/**
+ * landlock_enforce_domain - Domain enforced on a thread
+ *
+ * @domain: Domain now enforced on the current thread (never NULL,
+ * immutable; read locklessly). Correlate to
+ * landlock_create_domain via @domain->hierarchy->id for the
+ * source ruleset and requesting thread, or read
+ * @domain->hierarchy->details for the requesting process.
+ * @complete: Set on the single event that concludes the operation, after
+ * all its other enforcements; filter on it for one event per
+ * operation.
+ * @process_wide: The enforcement covers every eligible (non-exiting)
+ * thread of the process: set when the caller used
+ * %LANDLOCK_RESTRICT_SELF_TSYNC or the process is
+ * single-threaded. A lone thread whose group still
+ * holds a zombie leader is not counted single-threaded,
+ * so process_wide == 0 never proves the opposite.
+ * @no_new_privs: The enforcing thread's no_new_privs state at
+ * enforcement time: 1 if set (by a prior
+ * :manpage:`prctl(2)` %PR_SET_NO_NEW_PRIVS or by
+ * %LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS), 0 if the domain
+ * was enforced with %CAP_SYS_ADMIN instead.
+ *
+ * Emitted for each thread sys_landlock_restrict_self() enforces the
+ * domain on, in that thread's own context, right after its
+ * commit_creds(), so it fires only once the thread is irreversibly
+ * enforcing the domain (aborted operations emit none). Not
+ * balanced; every enforcement falls between the domain's
+ * landlock_create_domain and landlock_free_domain events.
+ *
+ * @complete == 1 && @process_wide == 1 means the whole process is
+ * sandboxed by @domain, durably (Landlock domains are monotonic and
+ * inherited on :manpage:`clone(2)`).
+ */
+TRACE_EVENT(landlock_enforce_domain,
+
+ TP_PROTO(const struct landlock_domain *domain, bool complete,
+ bool process_wide, bool no_new_privs),
+
+ TP_ARGS(domain, complete, process_wide, no_new_privs),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, complete )
+ __field( bool, process_wide )
+ __field( bool, no_new_privs )
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = domain->hierarchy->id;
+ __entry->complete = complete;
+ __entry->process_wide = process_wide;
+ __entry->no_new_privs = no_new_privs;
+ ),
+
+ TP_printk("domain=%llx complete=%d process_wide=%d no_new_privs=%d",
+ __entry->domain_id, __entry->complete, __entry->process_wide,
+ __entry->no_new_privs)
+);
+
+/**
+ * landlock_free_domain - Domain freed
+ *
+ * @hierarchy: Hierarchy node being freed (never NULL).
+ *
+ * Emitted when the hierarchy node's last reference is dropped: its
+ * refcount reaches zero after all child domains have released their
+ * parent reference. A committed domain is
+ * freed from a kworker via landlock_put_domain_deferred() (the credential
+ * free path runs in RCU context, where sleeping is forbidden), so the
+ * current task is not the sandboxed task that triggered the free. Balanced
+ * by a matching landlock_create_domain event.
+ */
+TRACE_EVENT(landlock_free_domain,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy),
+
+ TP_ARGS(hierarchy),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( u64, denials )
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = hierarchy->id;
+ __entry->denials = atomic64_read(&hierarchy->num_denials);
+ ),
+
+ TP_printk("domain=%llx denials=%llu",
+ __entry->domain_id, __entry->denials)
+);
+
+/**
+ * landlock_check_rule_inode - Inode rule evaluated during access check
+ *
+ * @domain: Enforcing domain (never NULL).
+ * @rule: Matching rule with per-layer access masks (never NULL).
+ * @access_request: Access mask evaluated against the rule (the domain's
+ * handled mask during rename/link double-checks).
+ * @dentry: Filesystem dentry being checked (never NULL).
+ *
+ * Emitted for each rule that matches during a filesystem access check.
+ * The grants array shows the requested rights the rule grants at each
+ * domain layer. See Documentation/trace/events-landlock.rst for how to
+ * interpret it.
+ */
+TRACE_EVENT(landlock_check_rule_inode,
+
+ TP_PROTO(const struct landlock_domain *domain,
+ const struct landlock_rule *rule,
+ u64 access_request, const struct dentry *dentry),
+
+ TP_ARGS(domain, rule, access_request, dentry),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( access_mask_t, access_request )
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __dynamic_array(access_mask_t, grants,
+ domain->num_layers)
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = domain->hierarchy->id;
+ __entry->access_request = access_request;
+ __entry->dev = dentry->d_sb->s_dev;
+ __entry->ino = d_backing_inode(dentry)->i_ino;
+
+ __trace_landlock_fill_layers(__get_dynamic_array(grants),
+ __get_dynamic_array_len(grants) /
+ sizeof(access_mask_t),
+ rule,
+ (access_mask_t)access_request);
+ ),
+
+ TP_printk("domain=%llx access_request=%s dev=%u:%u ino=%lu grants=%s",
+ __entry->domain_id,
+ __print_flags(__entry->access_request, "|", _LANDLOCK_ACCESS_FS_NAMES),
+ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino,
+ __print_landlock_layers(grants, _LANDLOCK_ACCESS_FS_NAMES))
+);
+
+/**
+ * landlock_check_rule_net_port - Network port rule evaluated
+ *
+ * @domain: Enforcing domain (never NULL).
+ * @rule: Matching rule with per-layer access masks (never NULL).
+ * @access_request: Access mask being requested.
+ * @port: Network port being checked (host endianness).
+ *
+ * Emitted for each rule that matches during a network access check. The
+ * grants array shows the requested rights the rule grants at each domain
+ * layer. See Documentation/trace/events-landlock.rst for how to
+ * interpret it.
+ */
+TRACE_EVENT(landlock_check_rule_net_port,
+
+ TP_PROTO(const struct landlock_domain *domain,
+ const struct landlock_rule *rule,
+ u64 access_request, u64 port),
+
+ TP_ARGS(domain, rule, access_request, port),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( access_mask_t, access_request )
+ __field( u64, port )
+ __dynamic_array(access_mask_t, grants,
+ domain->num_layers)
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = domain->hierarchy->id;
+ __entry->access_request = access_request;
+ __entry->port = port;
+
+ __trace_landlock_fill_layers(__get_dynamic_array(grants),
+ __get_dynamic_array_len(grants) /
+ sizeof(access_mask_t),
+ rule,
+ (access_mask_t)access_request);
+ ),
+
+ TP_printk("domain=%llx access_request=%s port=%llu grants=%s",
+ __entry->domain_id,
+ __print_flags(__entry->access_request, "|", _LANDLOCK_ACCESS_NET_NAMES),
+ __entry->port,
+ __print_landlock_layers(grants, _LANDLOCK_ACCESS_NET_NAMES))
+);
+
+/**
+ * landlock_deny_access_fs - Filesystem access denied
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the current task entered the denying domain itself.
+ * @logged: The domain's audit-logging decision for this denial.
+ * @blockers: Request type and final missing access subset (never NULL).
+ * @path: Filesystem path that was denied (never NULL).
+ * @pathname: Resolved path string (never NULL; an error placeholder on
+ * resolution failure).
+ *
+ * Emitted when a Landlock domain denies a filesystem access.
+ */
+TRACE_EVENT(landlock_deny_access_fs,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, const struct landlock_blockers *blockers,
+ const struct path *path, const char *pathname),
+
+ TP_ARGS(hierarchy, same_exec, logged, blockers, path, pathname),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( enum landlock_request_type, blockers_type )
+ __field( access_mask_t, blockers_access )
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __string( pathname, pathname )
+ ),
+
+ TP_fast_assign(
+ const struct inode *inode = d_backing_inode(path->dentry);
+
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->blockers_type = blockers->type;
+ __entry->blockers_access = blockers->access;
+ __entry->dev = path->dentry->d_sb->s_dev;
+ /*
+ * A negative dentry has no backing inode, so mirror the
+ * guard in dump_common_audit_data() and report inode 0.
+ */
+ __entry->ino = inode ? inode->i_ino : 0;
+ __assign_str(pathname);
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d blockers=%s dev=%u:%u ino=%lu path=%s",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->blockers_type == LANDLOCK_REQUEST_FS_ACCESS ?
+ __print_flags(__entry->blockers_access, "|", _LANDLOCK_ACCESS_FS_NAMES) :
+ __print_symbolic(__entry->blockers_type,
+ _LANDLOCK_FS_BLOCKER_TYPE_NAMES),
+ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino,
+ __trace_print_untrusted_str(p, __get_str(pathname),
+ __get_dynamic_array_len(pathname) - 1))
+);
+
+static_assert(offsetof(struct sockaddr_in, sin_port) ==
+ offsetof(struct sockaddr_in6, sin6_port));
+static_assert(sizeof_field(struct sockaddr_in, sin_port) ==
+ sizeof_field(struct sockaddr_in6, sin6_port));
+
+/**
+ * landlock_deny_access_net - Network access denied
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the current task entered the denying domain itself.
+ * @logged: The domain's audit-logging decision for this denial.
+ * @blockers: Request type and final missing access subset (never NULL).
+ * @sk: Socket object (never NULL), read without a socket lock, so its fields
+ * are a best-effort snapshot.
+ * @socket_family: Socket-family snapshot used by the verdict.
+ * @address: Authoritative address checked by the verdict (never NULL).
+ * The producer copies @addrlen bytes from the checked address and
+ * zeroes the remaining storage before emission. The
+ * &sockaddr_in.sin_port or &sockaddr_in6.sin6_port member, when
+ * present, remains in network endianness.
+ * @addrlen: Validated signed length of @address.
+ *
+ * Emitted when a Landlock domain denies a network operation. The blocker
+ * identifies whether the address is a bind or connect/send policy object.
+ * The flattened port field is converted from the checked address to host
+ * endianness, or is -1 when no port was checked. Zero is a valid checked
+ * port.
+ */
+TRACE_EVENT(landlock_deny_access_net,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, const struct landlock_blockers *blockers,
+ const struct sock *sk, u16 socket_family,
+ const struct sockaddr_storage *address, int addrlen),
+
+ TP_ARGS(hierarchy, same_exec, logged, blockers, sk, socket_family,
+ address, addrlen),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( enum landlock_request_type, blockers_type )
+ __field( access_mask_t, blockers_access )
+ __field( s64, port )
+ ),
+
+ TP_fast_assign(
+ const struct sockaddr *const addr =
+ (const struct sockaddr *)address;
+ const bool has_port =
+ addrlen >= (int)offsetofend(struct sockaddr_in, sin_port) &&
+ (addr->sa_family == AF_INET ||
+ addr->sa_family == AF_INET6 ||
+ (addr->sa_family == AF_UNSPEC &&
+ socket_family == AF_INET));
+
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->blockers_type = blockers->type;
+ __entry->blockers_access = blockers->access;
+ __entry->port =
+ has_port ?
+ ntohs(((const struct sockaddr_in *)addr)->sin_port) :
+ -1;
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d blockers=%s port=%lld",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->blockers_type == LANDLOCK_REQUEST_NET_ACCESS ?
+ __print_flags(__entry->blockers_access, "|", _LANDLOCK_ACCESS_NET_NAMES) :
+ "unknown",
+ __entry->port)
+);
+
+/**
+ * landlock_deny_ptrace - Ptrace access denied by a Landlock domain
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the tracer entered the denying domain itself.
+ * @logged: The domain's audit-logging decision for this denial.
+ * @tracee_domain_id: The tracee's Landlock domain ID, or 0 if the tracee
+ * is unsandboxed.
+ * @tracee: The target task ptrace acted on (never NULL). tracee_pid is
+ * the init-namespace TGID (like audit's opid).
+ * @tracer: The tracer or proposed tracer (never NULL); for PTRACE_TRACEME
+ * this is the parent, not the syscall caller.
+ *
+ * Emitted when a Landlock domain denies a ptrace operation.
+ */
+TRACE_EVENT(landlock_deny_ptrace,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, u64 tracee_domain_id,
+ const struct task_struct *tracee,
+ const struct task_struct *tracer),
+
+ TP_ARGS(hierarchy, same_exec, logged, tracee_domain_id, tracee, tracer),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( u64, tracee_domain_id)
+ __field( pid_t, tracee_pid )
+ __string( tracee_comm, tracee->comm )
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->tracee_domain_id = tracee_domain_id;
+ __entry->tracee_pid = task_tgid_nr((struct task_struct *)tracee);
+ __assign_str(tracee_comm);
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d tracee_domain=%llx tracee_pid=%d tracee_comm=%s",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->tracee_domain_id, __entry->tracee_pid,
+ __trace_print_untrusted_str(p, __get_str(tracee_comm),
+ __get_dynamic_array_len(tracee_comm) - 1))
+);
+
+/**
+ * landlock_deny_scope_signal - Signal delivery denied by
+ * LANDLOCK_SCOPE_SIGNAL
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the policy subject entered the denying domain itself.
+ * @logged: The domain's audit-logging decision for this denial.
+ * @target_domain_id: The target's Landlock domain ID, or 0 if the target
+ * is unsandboxed.
+ * @target: The task the signal was aimed at (never NULL). target_pid is
+ * the init-namespace TGID (like audit's opid).
+ * @signal: The signal selected by the denied check. Zero is a permission
+ * probe, not an absent value.
+ *
+ * Emitted when a Landlock domain denies signal delivery to a scoped-out
+ * target.
+ */
+TRACE_EVENT(landlock_deny_scope_signal,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, u64 target_domain_id,
+ const struct task_struct *target, int signal),
+
+ TP_ARGS(hierarchy, same_exec, logged, target_domain_id, target, signal),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( u64, target_domain_id)
+ __field( pid_t, target_pid )
+ __string( target_comm, target->comm )
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->target_domain_id = target_domain_id;
+ __entry->target_pid = task_tgid_nr((struct task_struct *)target);
+ __assign_str(target_comm);
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d target_domain=%llx target_pid=%d target_comm=%s",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->target_domain_id, __entry->target_pid,
+ __trace_print_untrusted_str(p, __get_str(target_comm),
+ __get_dynamic_array_len(target_comm) - 1))
+);
+
+/**
+ * landlock_deny_scope_abstract_unix_socket - Abstract unix socket access
+ * denied by LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the current task entered the denying domain itself.
+ * @logged: The domain's audit-logging decision for this denial.
+ * @peer_domain_id: The peer's Landlock domain ID, or 0 if the peer is
+ * unsandboxed.
+ * @peer: Peer socket (never NULL). peer_pid is best-effort: it is 0 for
+ * a datagram peer (no SO_PEERCRED), so sun_path is the reliable
+ * peer identifier.
+ *
+ * Emitted when a Landlock domain denies access to a scoped-out abstract
+ * unix socket.
+ */
+TRACE_EVENT(landlock_deny_scope_abstract_unix_socket,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, u64 peer_domain_id, const struct sock *peer),
+
+ TP_ARGS(hierarchy, same_exec, logged, peer_domain_id, peer),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( u64, peer_domain_id )
+ __field( pid_t, peer_pid )
+ /*
+ * Abstract socket names are untrusted binary data from
+ * user space. Use __string_len because abstract names
+ * are not NUL-terminated; their length is determined by
+ * addr->len. unix_sk(peer)->addr is stable here because
+ * the caller (hook_unix_stream_connect or
+ * hook_unix_may_send) holds unix_state_lock(peer).
+ */
+ __string_len( sun_path,
+ unix_sk(peer)->addr ?
+ unix_sk(peer)->addr->name->sun_path + 1 :
+ "",
+ unix_sk(peer)->addr ?
+ unix_sk(peer)->addr->len -
+ offsetof(struct sockaddr_un,
+ sun_path) - 1 :
+ 0)
+ ),
+
+ TP_fast_assign(
+ struct pid *peer_pid;
+
+ lockdep_assert_held(&unix_sk(peer)->lock);
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->peer_domain_id = peer_domain_id;
+ /*
+ * Best-effort (0 for a datagram peer). The caller holds the
+ * peer's AF_UNIX state lock, serializing published peercred
+ * updates. The peer socket keeps a reference to sk_peer_pid
+ * through pid_nr(); sun_path is the reliable identifier.
+ */
+ peer_pid = READ_ONCE(peer->sk_peer_pid);
+ __entry->peer_pid = peer_pid ? pid_nr(peer_pid) : 0;
+ __assign_str(sun_path);
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d peer_domain=%llx peer_pid=%d sun_path=%s",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->peer_domain_id, __entry->peer_pid,
+ __trace_print_untrusted_str(p, __get_str(sun_path),
+ __get_dynamic_array_len(sun_path) - 1))
+);
+
+#undef _LANDLOCK_FS_BLOCKER_TYPE_NAMES
+#undef _LANDLOCK_NAME_ENTRY
+
+#endif /* _TRACE_LANDLOCK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
+
+/* clang-format on */
diff --git a/include/trace/events/lock.h b/include/trace/events/lock.h
index 1ded869cd619..b1d5b18c4514 100644
--- a/include/trace/events/lock.h
+++ b/include/trace/events/lock.h
@@ -137,7 +137,11 @@ TRACE_EVENT(contention_end,
TP_printk("%p (ret=%d)", __entry->lock_addr, __entry->ret)
);
-TRACE_EVENT(contended_release,
+/* kernel/locking/mutex.c */
+int arch_contended_release_trace_reg(void);
+void arch_contended_release_trace_unreg(void);
+
+TRACE_EVENT_FN(contended_release,
TP_PROTO(void *lock),
@@ -151,7 +155,9 @@ TRACE_EVENT(contended_release,
__entry->lock_addr = lock;
),
- TP_printk("%p", __entry->lock_addr)
+ TP_printk("%p", __entry->lock_addr),
+
+ arch_contended_release_trace_reg, arch_contended_release_trace_unreg
);
#endif /* _TRACE_LOCK_H */
diff --git a/include/trace/events/memory-failure.h b/include/trace/events/memory-failure.h
index aa57cc8f896b..7a8ee5d1a44e 100644
--- a/include/trace/events/memory-failure.h
+++ b/include/trace/events/memory-failure.h
@@ -1,6 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
-#define TRACE_SYSTEM memory_failure
+/*
+ * For historical versions, memory_failure_event is in ras subsystem,
+ * some user programs depend on it.
+ */
+#define TRACE_SYSTEM ras
#define TRACE_INCLUDE_FILE memory-failure
#if !defined(_TRACE_MEMORY_FAILURE_H) || defined(TRACE_HEADER_MULTI_READ)
diff --git a/include/trace/events/migrate.h b/include/trace/events/migrate.h
index cd01dd7b3640..15ee2ef201b5 100644
--- a/include/trace/events/migrate.h
+++ b/include/trace/events/migrate.h
@@ -23,7 +23,8 @@
EM( MR_CONTIG_RANGE, "contig_range") \
EM( MR_LONGTERM_PIN, "longterm_pin") \
EM( MR_DEMOTION, "demotion") \
- EMe(MR_DAMON, "damon")
+ EM( MR_DAMON, "damon") \
+ EMe(MR_NEVER, "never_migrated")
/*
* First define the enums in the above macros to be exported to userspace
@@ -51,7 +52,7 @@ TRACE_EVENT(mm_migrate_pages,
TP_PROTO(unsigned long succeeded, unsigned long failed,
unsigned long thp_succeeded, unsigned long thp_failed,
unsigned long thp_split, unsigned long large_folio_split,
- enum migrate_mode mode, int reason),
+ enum migrate_mode mode, enum migrate_reason reason),
TP_ARGS(succeeded, failed, thp_succeeded, thp_failed,
thp_split, large_folio_split, mode, reason),
@@ -64,7 +65,7 @@ TRACE_EVENT(mm_migrate_pages,
__field( unsigned long, thp_split)
__field( unsigned long, large_folio_split)
__field( enum migrate_mode, mode)
- __field( int, reason)
+ __field( enum migrate_reason, reason)
),
TP_fast_assign(
@@ -91,13 +92,13 @@ TRACE_EVENT(mm_migrate_pages,
TRACE_EVENT(mm_migrate_pages_start,
- TP_PROTO(enum migrate_mode mode, int reason),
+ TP_PROTO(enum migrate_mode mode, enum migrate_reason reason),
TP_ARGS(mode, reason),
TP_STRUCT__entry(
__field(enum migrate_mode, mode)
- __field(int, reason)
+ __field(enum migrate_reason, reason)
),
TP_fast_assign(
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index a6e5a44c9b42..935893e5ea53 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -54,18 +54,10 @@
# define TRACE_GFP_FLAGS_LOCKDEP
#endif
-#ifdef CONFIG_SLAB_OBJ_EXT
-# define TRACE_GFP_FLAGS_SLAB \
- TRACE_GFP_EM(NO_OBJ_EXT)
-#else
-# define TRACE_GFP_FLAGS_SLAB
-#endif
-
#define TRACE_GFP_FLAGS \
TRACE_GFP_FLAGS_GENERAL \
TRACE_GFP_FLAGS_KASAN \
- TRACE_GFP_FLAGS_LOCKDEP \
- TRACE_GFP_FLAGS_SLAB
+ TRACE_GFP_FLAGS_LOCKDEP
#undef TRACE_GFP_EM
#define TRACE_GFP_EM(a) TRACE_DEFINE_ENUM(___GFP_##a##_BIT);
@@ -194,6 +186,12 @@ IF_HAVE_PG_ARCH_3(arch_3)
# define IF_HAVE_UFFD_MINOR(flag, name)
#endif
+#ifdef CONFIG_USERFAULTFD_RWP
+# define IF_HAVE_UFFD_RWP(flag, name) {flag, name},
+#else
+# define IF_HAVE_UFFD_RWP(flag, name)
+#endif
+
#if defined(CONFIG_64BIT) || defined(CONFIG_PPC32)
# define IF_HAVE_VM_DROPPABLE(flag, name) {flag, name},
#else
@@ -215,6 +213,7 @@ IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR, "uffd_minor" ) \
{VM_PFNMAP, "pfnmap" }, \
{VM_MAYBE_GUARD, "maybe_guard" }, \
{VM_UFFD_WP, "uffd_wp" }, \
+IF_HAVE_UFFD_RWP(VM_UFFD_RWP, "uffd_rwp" ) \
{VM_LOCKED, "locked" }, \
{VM_IO, "io" }, \
{VM_SEQ_READ, "seqread" }, \
diff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h
index 04521acba483..22882bd03459 100644
--- a/include/trace/events/mptcp.h
+++ b/include/trace/events/mptcp.h
@@ -75,7 +75,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
TP_ARGS(mpext),
TP_STRUCT__entry(
- __field(u64, data_ack)
__field(u64, data_seq)
__field(u32, subflow_seq)
__field(u16, data_len)
@@ -94,7 +93,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
),
TP_fast_assign(
- __entry->data_ack = mpext->ack64 ? mpext->data_ack : mpext->data_ack32;
__entry->data_seq = mpext->data_seq;
__entry->subflow_seq = mpext->subflow_seq;
__entry->data_len = mpext->data_len;
@@ -112,8 +110,8 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
__entry->infinite_map = mpext->infinite_map;
),
- TP_printk("data_ack=%llu data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
- __entry->data_ack, __entry->data_seq,
+ TP_printk("data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
+ __entry->data_seq,
__entry->subflow_seq, __entry->data_len,
__entry->csum, __entry->use_map,
__entry->dsn64, __entry->data_fin,
diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h
index 082cb03c6131..3fec3e8f91c8 100644
--- a/include/trace/events/netfs.h
+++ b/include/trace/events/netfs.h
@@ -59,6 +59,7 @@
EM(netfs_rreq_trace_free, "FREE ") \
EM(netfs_rreq_trace_intr, "INTR ") \
EM(netfs_rreq_trace_ki_complete, "KI-CMPL") \
+ EM(netfs_rreq_trace_ra_put_ref, "RA-PUT ") \
EM(netfs_rreq_trace_recollect, "RECLLCT") \
EM(netfs_rreq_trace_redirty, "REDIRTY") \
EM(netfs_rreq_trace_resubmit, "RESUBMT") \
@@ -70,9 +71,11 @@
EM(netfs_rreq_trace_unpause, "UNPAUSE") \
EM(netfs_rreq_trace_wait_ip, "WAIT-IP") \
EM(netfs_rreq_trace_wait_pause, "--PAUSED--") \
+ EM(netfs_rreq_trace_wait_put_ra_refs, "WAIT-P-RA") \
EM(netfs_rreq_trace_wait_quiesce, "WAIT-QUIESCE") \
EM(netfs_rreq_trace_waited_ip, "DONE-IP") \
EM(netfs_rreq_trace_waited_pause, "--UNPAUSED--") \
+ EM(netfs_rreq_trace_waited_put_ra_refs, "DONE-P-RA") \
EM(netfs_rreq_trace_waited_quiesce, "DONE-QUIESCE") \
EM(netfs_rreq_trace_wake_ip, "WAKE-IP") \
EM(netfs_rreq_trace_wake_queue, "WAKE-Q ") \
@@ -195,7 +198,6 @@
EM(netfs_folio_trace_clear_cc, "clear-cc") \
EM(netfs_folio_trace_clear_g, "clear-g") \
EM(netfs_folio_trace_clear_s, "clear-s") \
- EM(netfs_folio_trace_copy_to_cache, "mark-copy") \
EM(netfs_folio_trace_end_copy, "end-copy") \
EM(netfs_folio_trace_filled_gaps, "filled-gaps") \
EM(netfs_folio_trace_invalidate_all, "inval-all") \
@@ -206,16 +208,19 @@
EM(netfs_folio_trace_kill_cc, "kill-cc") \
EM(netfs_folio_trace_kill_g, "kill-g") \
EM(netfs_folio_trace_kill_s, "kill-s") \
+ EM(netfs_folio_trace_mark_copy, "mark-copy") \
EM(netfs_folio_trace_mkwrite, "mkwrite") \
EM(netfs_folio_trace_mkwrite_plus, "mkwrite+") \
- EM(netfs_folio_trace_not_under_wback, "!wback") \
EM(netfs_folio_trace_not_locked, "!locked") \
+ EM(netfs_folio_trace_not_under_wback, "!wback") \
+ EM(netfs_folio_trace_pgpriv2_copy, "pgpriv2-copy") \
EM(netfs_folio_trace_put, "put") \
EM(netfs_folio_trace_read, "read") \
EM(netfs_folio_trace_read_done, "read-done") \
EM(netfs_folio_trace_read_gaps, "read-gaps") \
EM(netfs_folio_trace_read_unlock, "read-unlock") \
EM(netfs_folio_trace_redirtied, "redirtied") \
+ EM(netfs_folio_trace_sched_copy, "sched-copy") \
EM(netfs_folio_trace_store, "store") \
EM(netfs_folio_trace_store_copy, "store-copy") \
EM(netfs_folio_trace_store_plus, "store+") \
@@ -786,6 +791,27 @@ TRACE_EVENT(netfs_folioq,
__print_symbolic(__entry->trace, netfs_folioq_traces))
);
+TRACE_EVENT(netfs_read_progress_at,
+ TP_PROTO(const struct netfs_io_request *rreq),
+
+ TP_ARGS(rreq),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, rreq)
+ __field(size_t, progress_at)
+ __field(size_t, cleaned_to)
+ ),
+
+ TP_fast_assign(
+ __entry->rreq = rreq->debug_id;
+ __entry->cleaned_to = rreq->cleaned_to - rreq->start;
+ __entry->progress_at = rreq->progress_at;
+ ),
+
+ TP_printk("R=%08x cln=%zx prg=%zx",
+ __entry->rreq, __entry->cleaned_to, __entry->progress_at)
+ );
+
#undef EM
#undef E_
#endif /* _TRACE_NETFS_H */
diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h
index 171524d3526d..36c3a90f0acc 100644
--- a/include/trace/events/pagemap.h
+++ b/include/trace/events/pagemap.h
@@ -77,6 +77,14 @@ TRACE_EVENT(mm_lru_activate,
TP_printk("folio=%p pfn=0x%lx", __entry->folio, __entry->pfn)
);
+DECLARE_TRACE(mm_lru_add_drain,
+ TP_PROTO(int cpu, unsigned int nr_folios),
+ TP_ARGS(cpu, nr_folios));
+
+DECLARE_TRACE(mm_lru_add_drain_all,
+ TP_PROTO(bool force_all_cpus),
+ TP_ARGS(force_all_cpus));
+
#endif /* _TRACE_PAGEMAP_H */
/* This part must be outside protection */
diff --git a/include/trace/events/qcom_geni_i2c.h b/include/trace/events/qcom_geni_i2c.h
new file mode 100644
index 000000000000..c7e7984f3620
--- /dev/null
+++ b/include/trace/events/qcom_geni_i2c.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_geni_i2c
+
+#if !defined(_TRACE_QCOM_GENI_I2C_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_QCOM_GENI_I2C_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(geni_i2c_bus_setup,
+ TP_PROTO(struct device *dev, u32 clk_freq, u8 clk_div,
+ u8 t_high_cnt, u8 t_low_cnt, u8 t_cycle_cnt),
+ TP_ARGS(dev, clk_freq, clk_div, t_high_cnt, t_low_cnt, t_cycle_cnt),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(u32, clk_freq)
+ __field(u8, clk_div)
+ __field(u8, t_high_cnt)
+ __field(u8, t_low_cnt)
+ __field(u8, t_cycle_cnt)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->clk_freq = clk_freq;
+ __entry->clk_div = clk_div;
+ __entry->t_high_cnt = t_high_cnt;
+ __entry->t_low_cnt = t_low_cnt;
+ __entry->t_cycle_cnt = t_cycle_cnt;
+ ),
+
+ TP_printk("%s: clk_freq=%u clk_div=%u t_high=%u t_low=%u t_cycle=%u",
+ __get_str(name), __entry->clk_freq, __entry->clk_div,
+ __entry->t_high_cnt, __entry->t_low_cnt,
+ __entry->t_cycle_cnt)
+);
+
+TRACE_EVENT(geni_i2c_irq,
+ TP_PROTO(struct device *dev, u32 m_stat, u32 rx_st,
+ u32 dm_tx_st, u32 dm_rx_st),
+ TP_ARGS(dev, m_stat, rx_st, dm_tx_st, dm_rx_st),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(u32, m_stat)
+ __field(u32, rx_st)
+ __field(u32, dm_tx_st)
+ __field(u32, dm_rx_st)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->m_stat = m_stat;
+ __entry->rx_st = rx_st;
+ __entry->dm_tx_st = dm_tx_st;
+ __entry->dm_rx_st = dm_rx_st;
+ ),
+
+ TP_printk("%s: m_stat=0x%08x rx_st=0x%08x dm_tx=0x%08x dm_rx=0x%08x",
+ __get_str(name), __entry->m_stat, __entry->rx_st,
+ __entry->dm_tx_st, __entry->dm_rx_st)
+);
+
+TRACE_EVENT(geni_i2c_err,
+ TP_PROTO(struct device *dev, int err, const char *msg),
+ TP_ARGS(dev, err, msg),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(int, err)
+ __string(msg, msg)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->err = err;
+ __assign_str(msg);
+ ),
+
+ TP_printk("%s: err=%d msg=%s",
+ __get_str(name), __entry->err, __get_str(msg))
+);
+
+#endif /* _TRACE_QCOM_GENI_I2C_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/qcom_geni_se.h b/include/trace/events/qcom_geni_se.h
new file mode 100644
index 000000000000..4a6e1ba2d147
--- /dev/null
+++ b/include/trace/events/qcom_geni_se.h
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_geni_se
+
+#if !defined(_TRACE_QCOM_GENI_SE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_QCOM_GENI_SE_H
+
+#include <linux/io.h>
+#include <linux/tracepoint.h>
+#include <linux/soc/qcom/geni-se.h>
+
+TRACE_EVENT(geni_se_regs,
+ TP_PROTO(struct geni_se *se),
+
+ TP_ARGS(se),
+
+ TP_STRUCT__entry(__string(geni_se_name, dev_name(se->dev))
+ __field(u32, geni_se_m_cmd0)
+ __field(u32, geni_se_m_irq_status)
+ __field(u32, geni_se_s_cmd0)
+ __field(u32, geni_se_s_irq_status)
+ __field(u32, geni_se_status)
+ __field(u32, geni_se_ios)
+ __field(u32, geni_se_m_cmd_ctrl)
+ __field(u32, geni_se_m_cmd_err)
+ __field(u32, geni_se_m_fw_err)
+ __field(u32, geni_se_tx_fifo_status)
+ __field(u32, geni_se_rx_fifo_status)
+ __field(u32, geni_se_tx_watermark)
+ __field(u32, geni_se_rx_watermark)
+ __field(u32, geni_se_rx_watermark_rfr)
+ __field(u32, geni_se_m_gp_length)
+ __field(u32, geni_se_s_gp_length)
+ __field(u32, geni_se_dma_tx_irq)
+ __field(u32, geni_se_dma_rx_irq)
+ __field(u32, geni_se_dma_tx_irq_en)
+ __field(u32, geni_se_dma_rx_irq_en)
+ __field(u32, geni_se_dma_rx_len)
+ __field(u32, geni_se_dma_rx_len_in)
+ __field(u32, geni_se_dma_tx_len)
+ __field(u32, geni_se_dma_tx_len_in)
+ __field(u32, geni_se_dma_tx_ptr_l)
+ __field(u32, geni_se_dma_tx_ptr_h)
+ __field(u32, geni_se_dma_rx_ptr_l)
+ __field(u32, geni_se_dma_rx_ptr_h)
+ __field(u32, geni_se_dma_tx_attr)
+ __field(u32, geni_se_dma_tx_max_burst)
+ __field(u32, geni_se_dma_rx_attr)
+ __field(u32, geni_se_dma_rx_max_burst)
+ __field(u32, geni_se_dma_if_en)
+ __field(u32, geni_se_dma_if_en_ro)
+ __field(u32, geni_se_dma_general_cfg)
+ __field(u32, geni_se_dma_qsb_trans_cfg)
+ __field(u32, geni_se_dma_dbg)
+ __field(u32, geni_se_m_irq_en)
+ __field(u32, geni_se_s_irq_en)
+ __field(u32, geni_se_gsi_event_en)
+ __field(u32, geni_se_irq_en)
+ __field(u32, geni_se_ser_m_clk_cfg)
+ __field(u32, geni_se_ser_s_clk_cfg)
+ __field(u32, geni_se_general_cfg)
+ __field(u32, geni_se_output_ctrl)
+ __field(u32, geni_se_clk_ctrl_ro)
+ __field(u32, geni_se_fifo_if_disable)
+ __field(u32, geni_se_fw_multilock_msa)
+ __field(u32, geni_se_clk_sel)
+ ),
+
+ TP_fast_assign(__assign_str(geni_se_name);
+ __entry->geni_se_m_cmd0 = readl(se->base + SE_GENI_M_CMD0);
+ __entry->geni_se_m_irq_status = readl(se->base + SE_GENI_M_IRQ_STATUS);
+ __entry->geni_se_s_cmd0 = readl(se->base + SE_GENI_S_CMD0);
+ __entry->geni_se_s_irq_status = readl(se->base + SE_GENI_S_IRQ_STATUS);
+ __entry->geni_se_status = readl(se->base + SE_GENI_STATUS);
+ __entry->geni_se_ios = readl(se->base + SE_GENI_IOS);
+ __entry->geni_se_m_cmd_ctrl = readl(se->base + SE_GENI_M_CMD_CTRL_REG);
+ __entry->geni_se_m_cmd_err = readl(se->base + M_CMD_ERR_STATUS);
+ __entry->geni_se_m_fw_err = readl(se->base + M_FW_ERR_STATUS);
+ __entry->geni_se_tx_fifo_status = readl(se->base + SE_GENI_TX_FIFO_STATUS);
+ __entry->geni_se_rx_fifo_status = readl(se->base + SE_GENI_RX_FIFO_STATUS);
+ __entry->geni_se_tx_watermark = readl(se->base + SE_GENI_TX_WATERMARK_REG);
+ __entry->geni_se_rx_watermark = readl(se->base + SE_GENI_RX_WATERMARK_REG);
+ __entry->geni_se_rx_watermark_rfr = readl(se->base + SE_GENI_RX_RFR_WATERMARK_REG);
+ __entry->geni_se_m_gp_length = readl(se->base + SE_GENI_M_GP_LENGTH);
+ __entry->geni_se_s_gp_length = readl(se->base + SE_GENI_S_GP_LENGTH);
+ __entry->geni_se_dma_tx_irq = readl(se->base + SE_DMA_TX_IRQ_STAT);
+ __entry->geni_se_dma_rx_irq = readl(se->base + SE_DMA_RX_IRQ_STAT);
+ __entry->geni_se_dma_tx_irq_en = readl(se->base + SE_DMA_TX_IRQ_EN);
+ __entry->geni_se_dma_rx_irq_en = readl(se->base + SE_DMA_RX_IRQ_EN);
+ __entry->geni_se_dma_rx_len = readl(se->base + SE_DMA_RX_LEN);
+ __entry->geni_se_dma_rx_len_in = readl(se->base + SE_DMA_RX_LEN_IN);
+ __entry->geni_se_dma_tx_len = readl(se->base + SE_DMA_TX_LEN);
+ __entry->geni_se_dma_tx_len_in = readl(se->base + SE_DMA_TX_LEN_IN);
+ __entry->geni_se_dma_tx_ptr_l = readl(se->base + SE_DMA_TX_PTR_L);
+ __entry->geni_se_dma_tx_ptr_h = readl(se->base + SE_DMA_TX_PTR_H);
+ __entry->geni_se_dma_rx_ptr_l = readl(se->base + SE_DMA_RX_PTR_L);
+ __entry->geni_se_dma_rx_ptr_h = readl(se->base + SE_DMA_RX_PTR_H);
+ __entry->geni_se_dma_tx_attr = readl(se->base + SE_DMA_TX_ATTR);
+ __entry->geni_se_dma_tx_max_burst = readl(se->base + SE_DMA_TX_MAX_BURST);
+ __entry->geni_se_dma_rx_attr = readl(se->base + SE_DMA_RX_ATTR);
+ __entry->geni_se_dma_rx_max_burst = readl(se->base + SE_DMA_RX_MAX_BURST);
+ __entry->geni_se_dma_if_en = readl(se->base + SE_DMA_IF_EN);
+ __entry->geni_se_dma_if_en_ro = readl(se->base + DMA_IF_EN_RO);
+ __entry->geni_se_dma_general_cfg = readl(se->base + DMA_GENERAL_CFG);
+ __entry->geni_se_dma_qsb_trans_cfg = readl(se->base + SE_DMA_QSB_TRANS_CFG);
+ __entry->geni_se_dma_dbg = readl(se->base + SE_DMA_DEBUG_REG0);
+ __entry->geni_se_m_irq_en = readl(se->base + SE_GENI_M_IRQ_EN);
+ __entry->geni_se_s_irq_en = readl(se->base + SE_GENI_S_IRQ_EN);
+ __entry->geni_se_gsi_event_en = readl(se->base + SE_GSI_EVENT_EN);
+ __entry->geni_se_irq_en = readl(se->base + SE_IRQ_EN);
+ __entry->geni_se_ser_m_clk_cfg = readl(se->base + GENI_SER_M_CLK_CFG);
+ __entry->geni_se_ser_s_clk_cfg = readl(se->base + GENI_SER_S_CLK_CFG);
+ __entry->geni_se_general_cfg = readl(se->base + GENI_GENERAL_CFG);
+ __entry->geni_se_output_ctrl = readl(se->base + GENI_OUTPUT_CTRL);
+ __entry->geni_se_clk_ctrl_ro = readl(se->base + GENI_CLK_CTRL_RO);
+ __entry->geni_se_fifo_if_disable = readl(se->base + GENI_IF_DISABLE_RO);
+ __entry->geni_se_fw_multilock_msa = readl(se->base + GENI_FW_MULTILOCK_MSA_RO);
+ __entry->geni_se_clk_sel = readl(se->base + SE_GENI_CLK_SEL);
+ ),
+
+ TP_printk("%s: m_cmd0=0x%08x m_irq_status=0x%08x s_cmd0=0x%08x s_irq_status=0x%08x geni_status=0x%08x geni_ios=0x%08x m_cmd_ctrl=0x%08x m_cmd_err=0x%08x m_fw_err=0x%08x tx_fifo_sts=0x%08x rx_fifo_sts=0x%08x tx_watermark=0x%08x rx_watermark=0x%08x rx_watermark_rfr=0x%08x m_gp_length=0x%08x s_gp_length=0x%08x dma_tx_irq=0x%08x dma_rx_irq=0x%08x dma_tx_irq_en=0x%08x dma_rx_irq_en=0x%08x dma_rx_len=0x%08x dma_rx_len_in=0x%08x dma_tx_len=0x%08x dma_tx_len_in=0x%08x dma_tx_ptr_l=0x%08x dma_tx_ptr_h=0x%08x dma_rx_ptr_l=0x%08x dma_rx_ptr_h=0x%08x dma_tx_attr=0x%08x dma_tx_max_burst=0x%08x dma_rx_attr=0x%08x dma_rx_max_burst=0x%08x dma_if_en=0x%08x dma_if_en_ro=0x%08x dma_general_cfg=0x%08x dma_qsb_trans_cfg=0x%08x dma_dbg=0x%08x m_irq_en=0x%08x s_irq_en=0x%08x gsi_event_en=0x%08x se_irq_en=0x%08x ser_m_clk_cfg=0x%08x ser_s_clk_cfg=0x%08x general_cfg=0x%08x output_ctrl=0x%08x clk_ctrl_ro=0x%08x fifo_if_dis=0x%08x fw_multilock_msa=0x%08x clk_sel=0x%08x",
+ __get_str(geni_se_name),
+ __entry->geni_se_m_cmd0, __entry->geni_se_m_irq_status,
+ __entry->geni_se_s_cmd0, __entry->geni_se_s_irq_status,
+ __entry->geni_se_status, __entry->geni_se_ios,
+ __entry->geni_se_m_cmd_ctrl,
+ __entry->geni_se_m_cmd_err, __entry->geni_se_m_fw_err,
+ __entry->geni_se_tx_fifo_status, __entry->geni_se_rx_fifo_status,
+ __entry->geni_se_tx_watermark, __entry->geni_se_rx_watermark,
+ __entry->geni_se_rx_watermark_rfr,
+ __entry->geni_se_m_gp_length, __entry->geni_se_s_gp_length,
+ __entry->geni_se_dma_tx_irq, __entry->geni_se_dma_rx_irq,
+ __entry->geni_se_dma_tx_irq_en, __entry->geni_se_dma_rx_irq_en,
+ __entry->geni_se_dma_rx_len, __entry->geni_se_dma_rx_len_in,
+ __entry->geni_se_dma_tx_len, __entry->geni_se_dma_tx_len_in,
+ __entry->geni_se_dma_tx_ptr_l, __entry->geni_se_dma_tx_ptr_h,
+ __entry->geni_se_dma_rx_ptr_l, __entry->geni_se_dma_rx_ptr_h,
+ __entry->geni_se_dma_tx_attr, __entry->geni_se_dma_tx_max_burst,
+ __entry->geni_se_dma_rx_attr, __entry->geni_se_dma_rx_max_burst,
+ __entry->geni_se_dma_if_en, __entry->geni_se_dma_if_en_ro,
+ __entry->geni_se_dma_general_cfg, __entry->geni_se_dma_qsb_trans_cfg,
+ __entry->geni_se_dma_dbg,
+ __entry->geni_se_m_irq_en, __entry->geni_se_s_irq_en,
+ __entry->geni_se_gsi_event_en, __entry->geni_se_irq_en,
+ __entry->geni_se_ser_m_clk_cfg, __entry->geni_se_ser_s_clk_cfg,
+ __entry->geni_se_general_cfg, __entry->geni_se_output_ctrl,
+ __entry->geni_se_clk_ctrl_ro, __entry->geni_se_fifo_if_disable,
+ __entry->geni_se_fw_multilock_msa, __entry->geni_se_clk_sel)
+);
+
+#endif /* _TRACE_QCOM_GENI_SE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/qcom_geni_serial.h b/include/trace/events/qcom_geni_serial.h
index 417ec01f9fc8..e1aa551d525e 100644
--- a/include/trace/events/qcom_geni_serial.h
+++ b/include/trace/events/qcom_geni_serial.h
@@ -97,18 +97,17 @@ DECLARE_EVENT_CLASS(geni_serial_data,
TP_ARGS(dev, buf, len),
TP_STRUCT__entry(__string(name, dev_name(dev))
- __field(unsigned int, len)
__dynamic_array(u8, data, len)
),
TP_fast_assign(__assign_str(name);
- __entry->len = len;
memcpy(__get_dynamic_array(data), buf, len);
),
TP_printk("%s: len=%u data=%s",
- __get_str(name), __entry->len,
- __print_hex(__get_dynamic_array(data), __entry->len))
+ __get_str(name), __get_dynamic_array_len(data),
+ __print_hex(__get_dynamic_array(data),
+ __get_dynamic_array_len(data)))
);
DEFINE_EVENT(geni_serial_data, geni_serial_tx_data,
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index 5fbdabe3faea..991fd6f41e4b 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -547,10 +547,11 @@ TRACE_EVENT_RCU(rcu_segcb_stats,
),
TP_fast_assign(
+ int i;
__entry->ctx = ctx;
memcpy(__entry->seglen, rs->seglen, RCU_CBLIST_NSEGS * sizeof(long));
- memcpy(__entry->gp_seq, rs->gp_seq, RCU_CBLIST_NSEGS * sizeof(unsigned long));
-
+ for (i = 0; i < RCU_CBLIST_NSEGS; i++)
+ __entry->gp_seq[i] = rs->gp_seq[i].norm;
),
TP_printk("%s seglen: (DONE=%ld, WAIT=%ld, NEXT_READY=%ld, NEXT=%ld) "
@@ -625,7 +626,7 @@ TRACE_EVENT_RCU(rcu_invoke_callback,
*/
TRACE_EVENT_RCU(rcu_invoke_kvfree_callback,
- TP_PROTO(const char *rcuname, struct rcu_head *rhp, unsigned long offset),
+ TP_PROTO(const char *rcuname, struct kvfree_rcu_head *rhp, unsigned long offset),
TP_ARGS(rcuname, rhp, offset),
diff --git a/include/trace/events/sched_ext.h b/include/trace/events/sched_ext.h
index d1bf5acd59c5..1e54f9564ef3 100644
--- a/include/trace/events/sched_ext.h
+++ b/include/trace/events/sched_ext.h
@@ -84,6 +84,34 @@ TRACE_EVENT(sched_ext_bypass_lb,
)
);
+TRACE_EVENT(sched_ext_exit,
+
+ TP_PROTO(struct scx_sched *sch, __u32 kind),
+
+ TP_ARGS(sch, kind),
+
+ TP_STRUCT__entry(
+ __string( name, sch->ops.name )
+ __field( __s32, level )
+ __field( __u64, sub_cgroup_id )
+ __string( cgrp_path, sch_cgrp_path(sch) )
+ __field( __u32, kind )
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->level = sch->level;
+ __entry->sub_cgroup_id = sch->ops.sub_cgroup_id;
+ __assign_str(cgrp_path);
+ __entry->kind = kind;
+ ),
+
+ TP_printk("sched %s level %d sub_cgroup_id %llu cgrp_path %s kind %u",
+ __get_str(name), __entry->level, __entry->sub_cgroup_id,
+ __get_str(cgrp_path), __entry->kind
+ )
+);
+
#endif /* _TRACE_SCHED_EXT_H */
/* This part must be outside protection */
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index ca82fd62dc30..3aa0608c6361 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -302,7 +302,7 @@ DECLARE_EVENT_CLASS(hrtimer_class,
* hrtimer_start_expired - Invoked when a expired timer was started
* @hrtimer: pointer to struct hrtimer
*
- * Preceeded by a hrtimer_start tracepoint.
+ * Preceded by a hrtimer_start tracepoint.
*/
DEFINE_EVENT(hrtimer_class, hrtimer_start_expired,
diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
index fbc07d353be6..93011f800d0f 100644
--- a/include/trace/trace_events.h
+++ b/include/trace/trace_events.h
@@ -19,6 +19,7 @@
*/
#include <linux/trace_events.h>
+#include <linux/btf_ids.h>
#ifndef TRACE_SYSTEM_VAR
#define TRACE_SYSTEM_VAR TRACE_SYSTEM
@@ -397,6 +398,26 @@ static inline notrace int trace_event_get_offsets_##call( \
#define _TRACE_PERF_INIT(call)
#endif /* CONFIG_PERF_EVENTS */
+#if defined(CONFIG_BPF_EVENTS) && defined(CONFIG_DEBUG_INFO_BTF)
+/*
+ * Per-template BTF id list, populated at link time by resolve_btfids:
+ * [0] FUNC __bpf_trace_<call> (the BPF dispatcher)
+ * [1] STRUCT trace_event_raw_<call> (the ring-buffer record)
+ * Exposed via the events/<sys>/<name>/btf_ids tracefs file.
+ */
+#define _TRACE_BTF_IDS_DECLARE(call) \
+ BTF_ID_LIST(__bpf_trace_btf_ids_##call) \
+ BTF_ID(func, __bpf_trace_##call) \
+ BTF_ID(struct, trace_event_raw_##call)
+
+#define _TRACE_BTF_IDS_INIT(call) \
+ .btf_ids = __bpf_trace_btf_ids_##call,
+
+#else
+#define _TRACE_BTF_IDS_DECLARE(call)
+#define _TRACE_BTF_IDS_INIT(call)
+#endif /* CONFIG_BPF_EVENTS && CONFIG_DEBUG_INFO_BTF */
+
#include "stages/stage6_event_callback.h"
@@ -474,6 +495,7 @@ static inline void ftrace_test_probe_##call(void) \
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
_TRACE_PERF_PROTO(call, PARAMS(proto)); \
+_TRACE_BTF_IDS_DECLARE(call) \
static char print_fmt_##call[] = print; \
static struct trace_event_class __used __refdata event_class_##call = { \
.system = TRACE_SYSTEM_STRING, \
@@ -483,6 +505,7 @@ static struct trace_event_class __used __refdata event_class_##call = { \
.probe = trace_event_raw_event_##call, \
.reg = trace_event_reg, \
_TRACE_PERF_INIT(call) \
+ _TRACE_BTF_IDS_INIT(call) \
};
#undef DECLARE_EVENT_SYSCALL_CLASS