Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: sysctl_teardown() with dynamic nodes?



A little bit of progress in the on-going saga of sysctl_teardown() not
working as expected...

I still can't determine what the problem is, but I can reproduce it at
will.  I put in some extra debugging stuff (a few calls to
sysctl_log_print()) and here's what I see (manual line-breaks inserted
for readability)

* The sysv_ipc module gets autoloaded and sets up its sysctl stuff.

	sysv_ipc_modcmd: clog = 0xfffffe81f04dc318
	root 0xffffffff806c0420 left 62 size 128 content \
		version 715 type 2 len 3: 1 82 1369 \
		version 714 type 2 len 3: 1 82 1368 \
		version 713 type 2 len 3: 1 82 1367 \
		version 712 type 2 len 3: 1 82 9 \
		version 711 type 2 len 3: 1 82 8 \
		version 710 type 2 len 3: 1 82 7 \
		version 709 type 2 len 3: 1 82 6 \
		version 708 type 4 len 3: 1 82 5 \
		version 707 type 2 len 3: 1 82 1366 \
		version 706 type 2 len 3: 1 82 1365 \
		version 705 type 5 len 3: 1 82 1 end

* The module gets auto-unloaded, and syscall_teardown() returns
  successfully.

	sysv_ipc_modcmd: clog = 0xfffffe81f04dc318
	root 0xffffffff806c0420 left 62 size 128 content \
		<remainder of sysctl_log_print() elided>

* The module gets reloaded, and once again the sysctllog output
  looks correct.  Everything is the same except for the version and
  node numbers:

	sysv_ipc_modcmd: clog = 0xfffffe810f3b97d0
	root 0xffffffff806c0420 left 62 size 128 content \
		version 752 type 2 len 3: 1 83 1374 \
		version 751 type 2 len 3: 1 83 1373 \
		version 750 type 2 len 3: 1 83 1372 \
		version 749 type 2 len 3: 1 82 9 \
		version 748 type 2 len 3: 1 82 8 \
		version 747 type 2 len 3: 1 82 7 \
		version 746 type 2 len 3: 1 82 6 \
		version 745 type 4 len 3: 1 82 5 \
		version 744 type 2 len 3: 1 83 1371 \
		version 743 type 2 len 3: 1 83 1370 \
		version 742 type 5 len 3: 1 82 1 end

* Now, when auto-unload comes around, we get a failure for each of
  the dynamically-assigned nodes (1370 thru 1374).  Each of them
  fails with error == 20 (ENOTDIR).  Here's the debug output from
  the first failure (note that the first entry in the log has been
  consumed before the call to sysctl_log_print()).

	sysctl_teardown: log 0xfffffe810f3b97d0 error 20 \
		type 2 ver 752 name 1 83 1374
	root 0xffffffff806c0420 left 68 size 128 content \
		version 751 type 2 len 3: 1 83 1373 \
		version 750 type 2 len 3: 1 83 1372 \
		version 749 type 2 len 3: 1 82 9 \
		version 748 type 2 len 3: 1 82 8 \
		version 747 type 2 len 3: 1 82 7 \
		version 746 type 2 len 3: 1 82 6 \
		version 745 type 4 len 3: 1 82 5 \
		version 744 type 2 len 3: 1 83 1371 \
		version 743 type 2 len 3: 1 83 1370 \
		version 742 type 5 len 3: 1 82 1 end

* And according to sysctl, these entries still exist in the tree:

	# sysctl -M kern.ipc | sed -e "s/ flag/\\
		flag/"
	kern.ipc (1.82): CTLTYPE_NODE, children 8/16, size 96,
		flags 0x200<READONLY,PERMANENT>, ver=758
	kern.ipc.sysvmsg (1.82.2): CTLTYPE_INT, size 4,
		flags 0x200<READONLY,PERMANENT>, ver=104
	kern.ipc.sysvsem (1.82.3): CTLTYPE_INT, size 4,
		flags 0x200<READONLY,PERMANENT>, ver=105
	kern.ipc.sysvshm (1.82.4): CTLTYPE_INT, size 4,
		flags 0x200<READONLY,PERMANENT>, ver=106
	kern.ipc.msgmni (1.82.1370): CTLTYPE_INT, size 4,
		flags 0x70<READWRITE>, func=0xffffffff808fc1db, ver=743
	kern.ipc.msgseg (1.82.1371): CTLTYPE_INT, size 4,
		flags 0x70<READWRITE>, func=0xffffffff808fc0eb, ver=744
	kern.ipc.semmni (1.82.1372): CTLTYPE_INT, size 4,
		flags 0x70<READWRITE>, func=0xffffffff808fdd93, ver=750
	kern.ipc.semmns (1.82.1373): CTLTYPE_INT, size 4,
		flags 0x70<READWRITE>, func=0xffffffff808fdccc, ver=751
	kern.ipc.semmnu (1.82.1374): CTLTYPE_INT, size 4,
		flags 0x70<READWRITE>, func=0xffffffff808fdc05, ver=752

I haven't tried this time, but on previous iterations, any attempt to
actually read these lingering entries results in a crash, since the
func pointers are no longer valid (the module has been unloaded).

It doesn't make a lot of sense to me how this could happen.  The
failing entries are on either side of five entries that are torn-
down successfully.  The only code I can find that would return a
ENOTDIR for sysctl_teardown() is in routine sysctl_locate()

int
sysctl_locate(struct lwp *l, const int *name, u_int namelen,
	      const struct sysctlnode **rnode, int *nip)
{
	...
	for (ni = 0; ni < namelen; ni++) {
		/*
		 * walked off bottom of tree
		 */
		if (node == NULL) {
			if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE)
				error = ENOENT;
			else
				error = ENOTDIR;
			break;
		}
	...
        }

	*rnode = pnode;
	if (nip)
		*nip = ni;

	return (error);
}

I just don't see how this could return ENOTDIR for some entries and
succeed for others.


+------------------+--------------------------+-------------------------+
| Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:       |
| (Retired)        | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com    |
| Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org  |
+------------------+--------------------------+-------------------------+


Home | Main Index | Thread Index | Old Index