[DTrace-devel] [PATCH] Add support for getmajor() and getminor() subroutines
eugene.loh at oracle.com
eugene.loh at oracle.com
Tue Feb 15 20:00:18 UTC 2022
From: Eugene Loh <eugene.loh at oracle.com>
The expected behavior is unclear. E.g., with D script
y = 0x1234567890abcdef;
printf("%x\n", getmajor(y));
printf("%x\n", getminor(y));
Solaris gives
12345678
90abcdef
while legacy DTrace (on Linux) gives
90a
bcdef
Further, there were no tests.
Implement the behavior that is in /usr/include/linux/kdev_t.h:
#define MAJOR(dev) ((dev)>>8)
#define MINOR(dev) ((dev) & 0xff)
and add tests.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_cg.c | 27 +++++++++++-
test/unittest/funcs/tst.getmajor.sh | 65 +++++++++++++++++++++++++++++
test/unittest/funcs/tst.getminor.sh | 59 ++++++++++++++++++++++++++
3 files changed, 149 insertions(+), 2 deletions(-)
create mode 100755 test/unittest/funcs/tst.getmajor.sh
create mode 100755 test/unittest/funcs/tst.getminor.sh
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index b6b39617..bd05bd32 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3374,6 +3374,29 @@ dt_cg_subr_dirname(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_cg_subr_path_helper(dnp, dlp, drp, "dt_dirname");
}
+/*
+ * For getmajor and getminor, see /usr/include/linux/kdev_t.h.
+ */
+static void
+dt_cg_subr_getmajor(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+ dt_node_t *arg = dnp->dn_args;
+
+ dt_cg_node(arg, dlp, drp);
+ dnp->dn_reg = arg->dn_reg;
+ emit(dlp, BPF_ALU64_IMM(BPF_RSH, dnp->dn_reg, 8));
+}
+
+static void
+dt_cg_subr_getminor(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+ dt_node_t *arg = dnp->dn_args;
+
+ dt_cg_node(arg, dlp, drp);
+ dnp->dn_reg = arg->dn_reg;
+ emit(dlp, BPF_ALU64_IMM(BPF_AND, dnp->dn_reg, 0xff));
+}
+
/*
* Get and return a new speculation ID. These are unallocated entries in the
* specs map, obtained by calling dt_speculation(). Return zero if none is
@@ -4120,8 +4143,8 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_COPYINTO] = NULL,
[DIF_SUBR_MSGDSIZE] = NULL,
[DIF_SUBR_MSGSIZE] = NULL,
- [DIF_SUBR_GETMAJOR] = NULL,
- [DIF_SUBR_GETMINOR] = NULL,
+ [DIF_SUBR_GETMAJOR] = &dt_cg_subr_getmajor,
+ [DIF_SUBR_GETMINOR] = &dt_cg_subr_getminor,
[DIF_SUBR_DDI_PATHNAME] = NULL,
[DIF_SUBR_STRJOIN] = dt_cg_subr_strjoin,
[DIF_SUBR_LLTOSTR] = &dt_cg_subr_lltostr,
diff --git a/test/unittest/funcs/tst.getmajor.sh b/test/unittest/funcs/tst.getmajor.sh
new file mode 100755
index 00000000..65fb5036
--- /dev/null
+++ b/test/unittest/funcs/tst.getmajor.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at
+# http://oss.oracle.com/licenses/upl.
+#
+
+dtrace=$1
+
+DIRNAME="$tmpdir/getmajor.$$.$RANDOM"
+mkdir -p $DIRNAME
+cd $DIRNAME
+
+cat << EOF > test.c
+#include <stdio.h>
+#include <sys/types.h> /* for dev_t, or use <sys/stat.h> */
+#include <linux/kdev_t.h> /* for MAJOR */
+
+int main(int c, char **v) {
+ long long y = 0x1234567890abcdefll;
+ dev_t x = y;
+
+ /*
+ * sizeof(dev_t) is:
+ * 8 bytes in user header /usr/include/sys/types.h
+ * 4 bytes in kernel header include/linux/types.h
+ * DTrace uses the kernel dev_t. So truncate the result.
+ */
+ printf("%x\n\n", (unsigned int) MAJOR(x));
+ return 0;
+}
+EOF
+
+gcc test.c
+if [ $? -ne 0 ]; then
+ echo ERROR: test.c did not compile
+ exit 1
+fi
+
+./a.out > test.out
+
+$dtrace -qn '
+BEGIN
+{
+ printf("%x\n", getmajor(0x1234567890abcdef));
+ exit(0)
+}' > dtrace.out
+if [ $? -ne 0 ]; then
+ echo ERROR: dtrace error
+ exit 1
+fi
+
+diff test.out dtrace.out
+if [ $? -ne 0 ]; then
+ echo ERROR: unexpected output
+ echo expect:
+ cat test.out
+ echo actual:
+ cat dtrace.out
+ exit 1
+fi
+
+echo success
+exit 0
diff --git a/test/unittest/funcs/tst.getminor.sh b/test/unittest/funcs/tst.getminor.sh
new file mode 100755
index 00000000..34b77e23
--- /dev/null
+++ b/test/unittest/funcs/tst.getminor.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at
+# http://oss.oracle.com/licenses/upl.
+#
+
+dtrace=$1
+
+DIRNAME="$tmpdir/getminor.$$.$RANDOM"
+mkdir -p $DIRNAME
+cd $DIRNAME
+
+cat << EOF > test.c
+#include <stdio.h>
+#include <sys/types.h> /* for dev_t, or use <sys/stat.h> */
+#include <linux/kdev_t.h> /* for MINOR */
+
+int main(int c, char **v) {
+ long long y = 0x1234567890abcdefll;
+ dev_t x = y;
+
+ printf("%x\n\n", (unsigned int) MINOR(x));
+ return 0;
+}
+EOF
+
+gcc test.c
+if [ $? -ne 0 ]; then
+ echo ERROR: test.c did not compile
+ exit 1
+fi
+
+./a.out > test.out
+
+$dtrace -qn '
+BEGIN
+{
+ printf("%x\n", getminor(0x1234567890abcdef));
+ exit(0)
+}' > dtrace.out
+if [ $? -ne 0 ]; then
+ echo ERROR: dtrace error
+ exit 1
+fi
+
+diff test.out dtrace.out
+if [ $? -ne 0 ]; then
+ echo ERROR: unexpected output
+ echo expect:
+ cat test.out
+ echo actual:
+ cat dtrace.out
+ exit 1
+fi
+
+echo success
+exit 0
--
2.18.4
More information about the DTrace-devel
mailing list