Page MenuHomeFreeBSD

Make root_mount_hold() work after boot.
ClosedPublic

Authored by trasz on Jan 30 2017, 6:33 PM.

Details

Summary

Make root_mount_hold() work after boot. This is important for two
reasons. First is rerooting into USB-mounted device that happens
to be not yet enumerated. The second is when mounting with (non-root)
filesystem on USB device on a hub that's enumerated later than the root
mount: the rc scripts explicitly mount for the root mount holds to be
released, but each USB bus takes the hold asynchronously, and if that
happens after root mount, it would just get ignored.

Diff Detail

Repository
rS FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

trasz updated this revision to Diff 24572.Jan 30 2017, 6:33 PM
trasz retitled this revision from to Make root_mount_hold() work after boot..
trasz updated this object.
trasz edited the test plan for this revision. (Show Details)
trasz added a reviewer: kib.Jan 30 2017, 6:34 PM

Marcel, "svn ann" suggests it was there when you wrote it. What do you think about the change? Thanks!

marcel edited edge metadata.Jan 31 2017, 6:56 PM

First of all: You may want to change root_mount_rel() as well: h cannot be NULL anymore. A KASSERT would be appropriate...

The purpose of root_mount_hold() is to delay mounting the root file system because device enumeration isn't complete. It's a harmless and needless operation when the root file system is mounted already, but to your point, can still help for the root re-mount cases. I just don't know how such would actually work, because rc.d scripts run only after we have mounted the root disk and I'm not aware of a way to re-invoke the root mount logic again. It's the root mount logic that waits for any holds -- I don't think there's any other place that does that.

Can you elaborate on the scenario a bit more so that I can understand exactly what is happening in your case?

trasz added a comment.Feb 1 2017, 11:38 PM

Good point with root_mount_rel(), I'll fix that.

Now, regarding the point of this: the r290196 changed the mechanism so that if you're eg waiting for "usbus0 usbus1 usbus2", but your root path is ufs:/dev/ada0p2, the root mount won't wait for the holds to be released - because the device already exists. However, the list of the holds is still exported to the userland via vfs.root_mount_holds sysctl, so that, should the mountcritlocal fail, it (the rc script) can wait for the root mount holds to be released and then retry the mount. This is for eg an USB disk mounted on /var. To see how it works grep for "root_hold_wait" in /etc/rc.d/*.

Now, currently, it looks like things can fail like this: USB holds usbus0, root mount succeeds, because it's not on an USB device, USB discovers a new hub, obtains hold on usbus1, and releases the hold on usbus0. The rc scripts should work for usbus1 - but they don't, because root_mount_hold() didn't do anything. The patch intends to fix the last part.

Got it! Thanks for the explanation.

trasz updated this revision to Diff 24762.Feb 5 2017, 12:09 PM
trasz edited edge metadata.

Don't allow NULL pointer in root_mount_rel().

trasz added a comment.Feb 5 2017, 9:03 PM

Note to self: tinderboxed.

marcel accepted this revision.Feb 5 2017, 9:32 PM
marcel edited edge metadata.
This revision is now accepted and ready to land.Feb 5 2017, 9:32 PM
This revision was automatically updated to reflect the committed changes.