Subject: How to make a sysctl return a short structure?
To: None <tech-kern@netbsd.org>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-kern
Date: 11/09/2005 10:42:43
I've just upgraded the kernel on my laptop, and installed a slighly
older userland snapshot from ftp.netbsd.org.  When I try to run top(1)
I see:

	euclid 20> top
	top: sysctl vm.uvmexp2 failed: Cannot allocate memory

The ENOMEN is coming from the bottom of sys___sysctl() here:

        /*
         * if the only problem is that we weren't given enough space,
         * that's an ENOMEM error
         */
        if (error == 0 && SCARG(uap, old) != NULL && savelen < oldlen)
                error = ENOMEM;

Part of the problem is that I'd added a new member to the end of struct
uvmexp_sysctl that I'd forgotten about, but until now my userland had
been built against my kernel sources.  Now, I effectively have an "old"
userland a newer kernel that has a larger struct uvmexp_sysctl.

Prior to our new dynamic sysctl infrastructure, the handler for
vm.uvmexp2 used to call a function called sysctl_rdminstruct() to return
the data to userland, and this function explicity didn't error of the
current kernel struct was bigger than what was asked for - it just
trimmed off the end and returned however much userland asked for.  This
way, future kernel's struct uvmexp_sysctl could grow, but an older top
wouldn't care and would still work ok.

Is there a way for a sysctl helper function (sysctl_vm_uvmexp2() in
sys/uvm/uvm_meter.c in this case) to return some sort of flag saying
that a short struct isn't an error?  Not breaking older versions of ps,
top, w, et al on newer kernels was the original goal of converting these
programs to use sysctl, and I'd like to fix the current situation before
struct uvmexp_sysctl changes.

Simon.
--
Simon Burge                                   <simonb@wasabisystems.com>
NetBSD Development, Support and Service:   http://www.wasabisystems.com/