summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/lttng/lttng-modules/0005-fix-block-add-a-disk_uevent-helper-v5.12.patch
blob: 3a2280ccdc1360c5ce2df2258ed46b3064885948 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
From 17cd2dc91cb82ed342b0da699f2b1a70c1bf6a03 Mon Sep 17 00:00:00 2001
From: Michael Jeanson <mjeanson@efficios.com>
Date: Mon, 15 Mar 2021 14:54:02 -0400
Subject: [PATCH 2/4] fix: block: add a disk_uevent helper (v5.12)

See upstream commit:

  commit bc359d03c7ec1bf3b86d03bafaf6bbb21e6414fd
  Author: Christoph Hellwig <hch@lst.de>
  Date:   Sun Jan 24 11:02:39 2021 +0100

    block: add a disk_uevent helper

    Add a helper to call kobject_uevent for the disk and all partitions, and
    unexport the disk_part_iter_* helpers that are now only used in the core
    block code.

Upstream-status: Backport [2.12.6]

Change-Id: If6e8797049642ab382d5699660ee1dd734e92c90
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
---
 Makefile               |   1 +
 lttng-statedump-impl.c |  34 +++++++++----
 src/wrapper/genhd.c    | 111 +++++++++++++++++++++++++++++++++++++++++
 wrapper/genhd.h        |  62 +++++++++++++++++++++++
 4 files changed, 198 insertions(+), 10 deletions(-)
 create mode 100644 src/wrapper/genhd.c

diff --git a/Makefile b/Makefile
index a9aff3f1..34043cfb 100644
--- a/Makefile
+++ b/Makefile
@@ -80,6 +80,7 @@ ifneq ($(KERNELRELEASE),)
                         wrapper/kallsyms.o \
                         wrapper/irqdesc.o \
                         wrapper/fdtable.o \
+                        wrapper/genhd.o \
                         lttng-wrapper-impl.o
 
   ifneq ($(CONFIG_HAVE_SYSCALL_TRACEPOINTS),)
diff --git a/lttng-statedump-impl.c b/lttng-statedump-impl.c
index 60b937c9..5511c7e8 100644
--- a/lttng-statedump-impl.c
+++ b/lttng-statedump-impl.c
@@ -250,13 +250,17 @@ int lttng_enumerate_block_devices(struct lttng_session *session)
 	struct device_type *ptr_disk_type;
 	struct class_dev_iter iter;
 	struct device *dev;
+	int ret = 0;
 
 	ptr_block_class = wrapper_get_block_class();
-	if (!ptr_block_class)
-		return -ENOSYS;
+	if (!ptr_block_class) {
+		ret = -ENOSYS;
+		goto end;
+	}
 	ptr_disk_type = wrapper_get_disk_type();
 	if (!ptr_disk_type) {
-		return -ENOSYS;
+		ret = -ENOSYS;
+		goto end;
 	}
 	class_dev_iter_init(&iter, ptr_block_class, NULL, ptr_disk_type);
 	while ((dev = class_dev_iter_next(&iter))) {
@@ -272,22 +276,32 @@ int lttng_enumerate_block_devices(struct lttng_session *session)
 		    (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
 			continue;
 
-		disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
-		while ((part = disk_part_iter_next(&piter))) {
+		/*
+		 * The original 'disk_part_iter_init' returns void, but our
+		 * wrapper can fail to lookup the original symbol.
+		 */
+		if (wrapper_disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0) < 0) {
+			ret = -ENOSYS;
+			goto iter_exit;
+		}
+
+		while ((part = wrapper_disk_part_iter_next(&piter))) {
 			char name_buf[BDEVNAME_SIZE];
 
 			if (lttng_get_part_name(disk, part, name_buf) == -ENOSYS) {
-				disk_part_iter_exit(&piter);
-				class_dev_iter_exit(&iter);
-				return -ENOSYS;
+				wrapper_disk_part_iter_exit(&piter);
+				ret = -ENOSYS;
+				goto iter_exit;
 			}
 			trace_lttng_statedump_block_device(session,
 					lttng_get_part_devt(part), name_buf);
 		}
-		disk_part_iter_exit(&piter);
+		wrapper_disk_part_iter_exit(&piter);
 	}
+iter_exit:
 	class_dev_iter_exit(&iter);
-	return 0;
+end:
+	return ret;
 }
 
 #ifdef CONFIG_INET
diff --git a/src/wrapper/genhd.c b/src/wrapper/genhd.c
new file mode 100644
index 00000000..a5a6c410
--- /dev/null
+++ b/src/wrapper/genhd.c
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only)
+ *
+ * wrapper/genhd.c
+ *
+ * Wrapper around disk_part_iter_(init|next|exit). Using KALLSYMS to get the
+ * addresses when available, else we need to have a kernel that exports this
+ * function to GPL modules. This export was removed in 5.12.
+ *
+ * Copyright (C) 2021 Michael Jeanson <mjeanson@efficios.com>
+ */
+
+#include <lttng/kernel-version.h>
+#include <linux/module.h>
+#include <wrapper/genhd.h>
+
+#if (defined(CONFIG_KALLSYMS) && \
+	(LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,12,0)))
+
+#include <wrapper/kallsyms.h>
+
+static
+void (*disk_part_iter_init_sym)(struct disk_part_iter *piter, struct gendisk *disk,
+			unsigned int flags);
+
+static
+LTTNG_DISK_PART_TYPE *(*disk_part_iter_next_sym)(struct disk_part_iter *piter);
+
+static
+void (*disk_part_iter_exit_sym)(struct disk_part_iter *piter);
+
+/*
+ * This wrapper has an 'int' return type instead of the original 'void', to be
+ * able to report the symbol lookup failure to the caller.
+ *
+ * Return 0 on success, -1 on error.
+ */
+int wrapper_disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk,
+                          unsigned int flags)
+{
+	if (!disk_part_iter_init_sym)
+		disk_part_iter_init_sym = (void *) kallsyms_lookup_funcptr("disk_part_iter_init");
+
+	if (disk_part_iter_init_sym) {
+		disk_part_iter_init_sym(piter, disk, flags);
+	} else {
+		printk_once(KERN_WARNING "LTTng: disk_part_iter_init symbol lookup failed.\n");
+		return -1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wrapper_disk_part_iter_init);
+
+LTTNG_DISK_PART_TYPE *wrapper_disk_part_iter_next(struct disk_part_iter *piter)
+{
+	if (!disk_part_iter_next_sym)
+		disk_part_iter_next_sym = (void *) kallsyms_lookup_funcptr("disk_part_iter_next");
+
+	if (disk_part_iter_next_sym) {
+		return disk_part_iter_next_sym(piter);
+	} else {
+		printk_once(KERN_WARNING "LTTng: disk_part_iter_next symbol lookup failed.\n");
+		return NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(wrapper_disk_part_iter_next);
+
+/*
+ * We don't return an error on symbol lookup failure here because there is
+ * nothing the caller can do to cleanup the iterator.
+ */
+void wrapper_disk_part_iter_exit(struct disk_part_iter *piter)
+{
+	if (!disk_part_iter_exit_sym)
+		disk_part_iter_exit_sym = (void *) kallsyms_lookup_funcptr("disk_part_iter_exit");
+
+	if (disk_part_iter_exit_sym) {
+		disk_part_iter_exit_sym(piter);
+	} else {
+		printk_once(KERN_WARNING "LTTng: disk_part_iter_exit symbol lookup failed.\n");
+	}
+}
+EXPORT_SYMBOL_GPL(wrapper_disk_part_iter_exit);
+
+#else
+
+/*
+ * This wrapper has an 'int' return type instead of the original 'void', so the
+ * kallsyms variant can report the symbol lookup failure to the caller.
+ *
+ * This variant always succeeds and returns 0.
+ */
+int wrapper_disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk,
+                          unsigned int flags)
+{
+	disk_part_iter_init(piter, disk, flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wrapper_disk_part_iter_init);
+
+LTTNG_DISK_PART_TYPE *wrapper_disk_part_iter_next(struct disk_part_iter *piter)
+{
+	return disk_part_iter_next(piter);
+}
+EXPORT_SYMBOL_GPL(wrapper_disk_part_iter_next);
+
+void wrapper_disk_part_iter_exit(struct disk_part_iter *piter)
+{
+	disk_part_iter_exit(piter);
+}
+EXPORT_SYMBOL_GPL(wrapper_disk_part_iter_exit);
+#endif
diff --git a/wrapper/genhd.h b/wrapper/genhd.h
index 98feb57b..6bae239d 100644
--- a/wrapper/genhd.h
+++ b/wrapper/genhd.h
@@ -13,6 +13,13 @@
 #define _LTTNG_WRAPPER_GENHD_H
 
 #include <linux/genhd.h>
+#include <lttng/kernel-version.h>
+
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,11,0))
+#define LTTNG_DISK_PART_TYPE struct block_device
+#else
+#define LTTNG_DISK_PART_TYPE struct hd_struct
+#endif
 
 #ifdef CONFIG_KALLSYMS_ALL
 
@@ -94,4 +101,59 @@ struct device_type *wrapper_get_disk_type(void)
 
 #endif
 
+/*
+ * This wrapper has an 'int' return type instead of the original 'void', to be
+ * able to report the symbol lookup failure to the caller.
+ *
+ * Return 0 on success, -1 on error.
+ */
+int wrapper_disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk,
+                          unsigned int flags);
+LTTNG_DISK_PART_TYPE *wrapper_disk_part_iter_next(struct disk_part_iter *piter);
+void wrapper_disk_part_iter_exit(struct disk_part_iter *piter);
+
+/*
+ * Canary function to check for 'disk_part_iter_init()' at compile time.
+ *
+ * From 'include/linux/genhd.h':
+ *
+ *   extern void disk_part_iter_init(struct disk_part_iter *piter,
+ *                                   struct gendisk *disk, unsigned int flags);
+ *
+ */
+static inline
+void __canary__disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk,
+		unsigned int flags)
+{
+	disk_part_iter_init(piter, disk, flags);
+}
+
+/*
+ * Canary function to check for 'disk_part_iter_next()' at compile time.
+ *
+ * From 'include/linux/genhd.h':
+ *
+ *   struct block_device *disk_part_iter_next(struct disk_part_iter *piter);
+ *
+ */
+static inline
+LTTNG_DISK_PART_TYPE *__canary__disk_part_iter_next(struct disk_part_iter *piter)
+{
+	return disk_part_iter_next(piter);
+}
+
+/*
+ * Canary function to check for 'disk_part_iter_exit()' at compile time.
+ *
+ * From 'include/linux/genhd.h':
+ *
+ *   extern void disk_part_iter_exit(struct disk_part_iter *piter);
+ *
+ */
+static inline
+void __canary__disk_part_iter_exit(struct disk_part_iter *piter)
+{
+	return disk_part_iter_exit(piter);
+}
+
 #endif /* _LTTNG_WRAPPER_GENHD_H */
-- 
2.25.1