The helper function produces the value that is returned in *oldlenp.

If you happen to use CTL_DESCRIBE (e.g. running sysctl -d), it's
not your helper function being called but the sysctl_describe helper
that returns a value of 1024.

Maybe you can show your helper routine and how you call sysctl ?

sure, I call sysctl this way: sysctl debug.tslog

here's the helper function code:

static int
sysctl_debug_tslog(SYSCTLFN_ARGS)
{
        char buf[LINE_MAX] = "";
        char *where = oldp;
        size_t slen, i, limit;
        int error = 0;
        static size_t needed = 0;

        /* Come back with the right size */
        /* here at second call, *oldlenp == 1024 */
        if (*oldlenp < needed) {
                *oldlenp = needed;
                return 0; /* will be back with correct size */
        }
        /* Add data logged within the kernel. */
        limit = MIN(nrecs, nitems(timestamps));
        for (i = 0; i < limit; i++) {
                snprintf(buf, LINE_MAX, "0x%x %llu",
                        timestamps[i].lid,
                        (unsigned long long)timestamps[i].tsc);
                switch (timestamps[i].type) {
                case TS_ENTER:
                        strcat(buf, " ENTER");
                        break;
                case TS_EXIT:
                        strcat(buf, " EXIT");
                        break;
                case TS_THREAD:
                        strcat(buf, " THREAD");
                        break;
                case TS_EVENT:
                        strcat(buf, " EVENT");
                        break;
                }
                snprintf(buf, LINE_MAX, "%s %s", buf,
                        timestamps[i].f ? timestamps[i].f : "(null)");
                if (timestamps[i].s)
                        snprintf(buf, LINE_MAX, "%s %s\n", buf,
                                timestamps[i].s);
                else
                        strcat(buf, "\n");

                slen = strlen(buf) + 1;

                if (where == NULL) /* 1st pass, calculate needed */
                        needed += slen;
                else {
                        if (i > 0)
                                where--; /* overwrite last \0 */
                        if ((error = copyout(buf, where, slen)))
                                break;
                        where += slen;
                }
        }
        /* Come back with an address */
        if (oldp == NULL)
                *oldlenp = needed;

        return error;
}

Here's the setup:

SYSCTL_SETUP(sysctl_tslog_setup, "tslog sysctl")
{
        sysctl_createv(NULL, 0, NULL, NULL,
                CTLFLAG_PERMANENT|CTLFLAG_READONLY,
                CTLTYPE_STRING, "tslog",
                SYSCTL_DESCR("Dump recorded event timestamps"),
                sysctl_debug_tslog, 0, NULL, 0,
                CTL_DEBUG, CTL_CREATE, CTL_EOL);
}

--
------------------------------------------------------------------------
Emile `iMil' Heitor <imil@{home.imil.net,NetBSD.org}> | https://imil.net

Reply via email to