Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Jun 2025 16:25:02 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 287741] ctld deletes ports if they already exist
Message-ID:  <bug-287741-227-IQLFYncUq9@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-287741-227@https.bugs.freebsd.org/bugzilla/>

index | next in thread | previous in thread | raw e-mail

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=287741

--- Comment #3 from Alan Somers <asomers@FreeBSD.org> ---
The scenario that 5f89aea7b74aa4605b25af62e31303097a4a48cc helps with is when
two separate processes both do "service ctld restart" or "service ctld reload"
at the same time.  It also helps if ctld receives a signal while it's still
starting up.  Both of those scenarios could cause kernel_port_add() to fail.

Some background info: there are really multiple separate lists of CTL ports. 
One is the kernel's list.  That's the list that you can see with "ctladm
portlist".  ctld's kernel_port_add() function adds ports to that list.  Another
is the list of ports that existed in the kernel before this ctld instance
started.  That's stored in ctld's "kports" variable.  Finally, there's the list
of ports that are managed by this ctld instance and also exist in the kernel. 
That's stored in the newconf variable.  What 5f89aea7b74 does is it removes a
port from the newconf variable if the kernel rejected it, for any reason.  But
it doesn't attempt to remove ports from the kernel.  That would require
kernel_port_remove().  Note that ctld is careful not to call kernel_port_add()
for ports that already exist within the kernel.

The reason for this complicated dance is that ctld is technically optional. 
Almost everything it can do can also be done with ctladm.  And in theory it
should be possible to run multiple instances of ctld at the same time, each
managing different LUNs and targets (though I don't know of anybody who
actually does that).  So each ctld instance must take care not to interfere
with kernel ports created by another ctld instance, or by ctladm. 
Unfortunately, if ctld crashes or gets killed by a signal, then when the next
ctld process starts, it will see many kernel ports and think that they might be
managed by a different ctld instance.  So it won't try to manage it. 
5f89aea7b74 fixes a bug of that sort.

We can't simply remove the kernel_port_add() call, because that would break the
ability to use ctladm to add ports manually, and break the ability to run
multiple ctld instances.

If kernel_port_add() fails because the port already exists, that suggests to me
another race similar to what 5f89aea7b74 fixed.  Absent any race, port_find()
should've found an existing port, causing kernel_port_add() to be skipped.  So
you really need to determine why kernel_port_add() is failing.  The three
likeliest reasons I can think of are simultaneous "service ctld ..." calls,
direct use of ctladm, or ctld crashing or being killed by a signal.

We can certainly fix the log message, as you suggested in your email.

-- 
You are receiving this mail because:
You are the assignee for the bug.

home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-287741-227-IQLFYncUq9>