[DTrace-devel] [PATCH] Add support for getmajor() and getminor() subroutines
Eugene Loh
eugene.loh at oracle.com
Tue Feb 15 20:10:06 UTC 2022
Actually, I probably did this wrong, but before I fix could someone
comment on this inconsistency?
In kernel header include/linux/kdev_t.h, we have:
#include <uapi/linux/kdev_t.h>
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
Then, in include/uapi/linux/kdev_t.h, we have:
#define MAJOR(dev) ((dev)>>8)
#define MINOR(dev) ((dev) & 0xff)
Should I simply ignore the uapi version? (Also, it has
sizeof(kdev_t)==8, while the kernel has 4.)
On 2/15/22 3:00 PM, eugene.loh at oracle.com wrote:
> 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
More information about the DTrace-devel
mailing list