Solved What does canmount=off and canmount=noauto mean?

Hello everyone,

How to interpret the meaning of canmount=off and canmount=noauto?

The value of the canmount attribute of the data set zroot/usr is off.
The value of the canmount attribute of zroot/ROOT/default is noauto.

Why are they actually mounted?
 
Learn to use man pages.

Code:
     canmount=on | off | noauto
         If this property is set to off, the file system cannot be mounted,
         and is ignored by "zfs mount -a".  Setting this property to off is
         similar to setting the mountpoint property to none, except that the
         dataset still has a normal mountpoint property, which can be
         inherited. Setting this property to off allows datasets to be used
         solely as a mechanism to inherit properties. One example of setting
         canmount=off is to have two datasets with the same mountpoint, so
         that the children of both datasets appear in the same directory, but
         might have different inherited characteristics.

         When the noauto value is set, a dataset can only be mounted and
         unmounted explicitly. The dataset is not mounted automatically when
         the dataset is created or imported, nor is it mounted by the "zfs
         mount -a" command or unmounted by the "zfs umount -a" command.

         This property is not inherited.

See zfs(8).
 
To add a bit of info here based on my own conjecture, in the instances they are set to "off" it's because of how ZFS works, how FreeBSD boots, and how the heirarchy is designed. ZFS doesn't allow you to just create a new ZFS file system, for example, on /usr/ports unless both /usr and / are each their own ZFS file system (created via zfs create). FreeBSD wisely sets (by default if using ZFS) /usr/ports (and a couple other directories in /usr) to be their own ZFS file system, which of course means /usr has to be its own as well. However, when booting, only / is initially mounted, and the rest is mounted later on.

A problem occurs when, during the boot process and only / is mounted, it wants to access something on /usr (and not one of the other sub-/usr directories where a different ZFS file system exists, like /usr/ports) but /usr isn't mounted yet. The workaround to this problem (and what is done by default) is to simply set canmount=off on /usr, which puts all the things that would be in that ZFS filesystem (e.g. /usr) instead on the parent ZFS filesystem (e.g. /), but still allows you to create and use ZFS file systems further down the heirarchy like /usr/ports.

Having said that, I've created several systems in the past, before the automated root-on-ZFS installation scripts were created, that do have /usr as a mountable, separate ZFS file system that's not available during certain stages of the boot process. They continue to boot just fine to 11.2-RELEASE. However, I'm concerned that if something in the future should require a file that's there, and it hasn't been mounted yet, it could leave the system unbootable, so I'd definitely avoid doing this on any new system you're setting up.

Edit: You mentioned that zroot/usr is mounted despite canmount=off. I don't think this is possible, so how are you concluding that it's mounted? If it shows up on zfs list but not when you run mount (without arguments) that means it is not mounted.
 
Edit: You mentioned that zroot/usr is mounted despite canmount=off. I don't think this is possible, so how are you concluding that it's mounted? If it shows up on zfs list but not when you run mount (without arguments) that means it is not mounted.

I found it with zfs get all zroot/usr and zfs get all zroot/ROOT/default.
 
zroot/usr isn't mounted as a real filesystem. The /usr directory is actually part of the / filesystem which is probably part of something like zroot/ROOT/default. ZFS requires that any datasets that are created are created inside a parent dataset so the datasets like zroot/usr/src have this zroot/usr as their parent just to satisfy that requirement.
 
  • Thanks
Reactions: sdf
ZFS requires that any datasets that are created are created inside a parent dataset so the datasets like zroot/usr/src have this zroot/usr as their parent just to satisfy that requirement.
That set up actually makes zroot/usr a dataset with a filesystem on it and it needs to be mounted.

Code:
dice@maelcum:~ % zfs list
NAME              USED  AVAIL  REFER  MOUNTPOINT
zroot            5.60G  40.7G   357M  /
zroot/usr        4.30G  40.7G  3.26G  /usr
zroot/usr/home   2.78M  40.7G  2.66M  /usr/home
zroot/usr/local   682M  40.7G   402M  /usr/local
zroot/var         816M  40.7G  59.6M  /var
zroot/var/db      344M  40.7G   258M  /var/db
zroot/var/empty    31K  40.7G    22K  /var/empty
zroot/var/log    1.83M  40.7G  1.30M  /var/log
zroot/var/tmp      32K  40.7G    23K  /var/tmp
Code:
dice@maelcum:~ % zfs get mountpoint zroot/usr
NAME       PROPERTY    VALUE       SOURCE
zroot/usr  mountpoint  /usr        inherited from zroot
dice@maelcum:~ % zfs get canmount zroot/usr
NAME       PROPERTY  VALUE     SOURCE
zroot/usr  canmount  on        default
 
This must have changed fairly recently, as this is a bog standard install too (but was installed with 11.1-RELEASE):
Code:
dice@jenkins:~ % zfs list
NAME                     USED  AVAIL  REFER  MOUNTPOINT
zroot                   2.60G  14.7G   176K  /zroot
zroot/ROOT              2.14G  14.7G   176K  none
zroot/ROOT/default      2.14G  14.7G  2.14G  /
zroot/tmp               58.5M  14.7G  58.5M  /tmp
zroot/usr                370M  14.7G   176K  /usr
zroot/usr/home           370M  14.7G   272K  /usr/home
zroot/usr/home/jenkins   370M  14.7G   370M  /usr/home/jenkins
zroot/usr/ports          176K  14.7G   176K  /usr/ports
zroot/usr/src            176K  14.7G   176K  /usr/src
zroot/var               14.4M  14.7G   176K  /var
zroot/var/audit          176K  14.7G   176K  /var/audit
zroot/var/crash          176K  14.7G   176K  /var/crash
zroot/var/log           13.3M  14.7G  13.3M  /var/log
zroot/var/mail           400K  14.7G   400K  /var/mail
zroot/var/tmp            176K  14.7G   176K  /var/tmp
Same here:
Code:
dice@gitlab:~ % zfs list
NAME                 USED  AVAIL  REFER  MOUNTPOINT
zroot               5.21G  9.81G    88K  /zroot
zroot/ROOT          4.88G  9.81G    88K  none
zroot/ROOT/default  4.88G  9.81G  4.88G  /
zroot/tmp           14.2M  9.81G  14.2M  /tmp
zroot/usr            304M  9.81G    88K  /usr
zroot/usr/home       304M  9.81G   304M  /usr/home
zroot/usr/ports       88K  9.81G    88K  /usr/ports
zroot/usr/src         88K  9.81G    88K  /usr/src
zroot/var           9.87M  9.81G    88K  /var
zroot/var/audit       88K  9.81G    88K  /var/audit
zroot/var/crash       88K  9.81G    88K  /var/crash
zroot/var/log       9.34M  9.81G  9.34M  /var/log
zroot/var/mail       172K  9.81G   172K  /var/mail
zroot/var/tmp        104K  9.81G   104K  /var/tmp
As do all my other installs. But as I said, they were initially installed with 11.1-RELEASE.
 
Hmm.. Spoke a bit too soon. Looks like this was done much earlier:
Code:
dice@jenkins:~ % mount
zroot/ROOT/default on / (zfs, local, noatime, nfsv4acls)
devfs on /dev (devfs, local, multilabel)
zroot/tmp on /tmp (zfs, local, noatime, nosuid, nfsv4acls)
zroot/usr/home on /usr/home (zfs, local, noatime, nfsv4acls)
zroot/usr/home/jenkins on /usr/home/jenkins (zfs, local, noatime, nfsv4acls)
zroot/usr/ports on /usr/ports (zfs, local, noatime, nosuid, nfsv4acls)
zroot/usr/src on /usr/src (zfs, local, noatime, nfsv4acls)
zroot/var/audit on /var/audit (zfs, local, noatime, noexec, nosuid, nfsv4acls)
zroot/var/crash on /var/crash (zfs, local, noatime, noexec, nosuid, nfsv4acls)
zroot/var/log on /var/log (zfs, local, noatime, noexec, nosuid, nfsv4acls)
zroot/var/mail on /var/mail (zfs, local, nfsv4acls)
zroot/var/tmp on /var/tmp (zfs, local, noatime, nosuid, nfsv4acls)
zroot on /zroot (zfs, local, noatime, nfsv4acls)

That first system that did have /usr mounted is a really old system that has been upgraded/updated many times. I'm not even sure what version I used to set it up initially. It's even possible I built that one by hand from scratch. Looking at the power_on_hours metric of the SSD (41000+ hours) it happened 4-5 years ago.
 
This page talks about the reason for it. And has 10.1 mentioned. https://mwl.io/archives/2363

"This list is deceptive. The dataset zroot/usr exists, but it isn’t mounted. Go ahead, run mount(8) or zfs mount and check. I’ll wait. The dataset must exist for you to have child datasets like /usr/ports, but it doesn’t actually contain any data. The files in /usr that aren’t in specific child datasets like /usr/ports or /usr/src are all in the root dataset."

Boot environments are awesome by the way. I've used them whenever I do any kind of upgrade. So nice to know that if anything goes wrong you can just boot the old one straight away!
 
This page talks about the reason for it.
I've always found it odd to have /usr/ separated but not /usr/local/, even on the 'old' traditional BSD labeled slices. Because of the split between OS and ports/packages having /usr/local separate made more sense to me.

I suspect I built that machine with the old partitioning stuck in the back of my mind.
 
The <zpool>/usr dataset exists only as a parent dataset for the <zpool>/usr/home dataset that is mounted at /usr/home. It could be called <zpool>/dummy and it wouldn't make a difference.
 
Looks like this is to support boot environment selection. So when it snapshots / this also includes /usr?
I forgot about boot environments; that makes more sense as to why it's done that way. But yes, there is no separate /usr FS as it's not mounted.

Anyway if you ever do manual ZFS partitioning and want to compare it to what the automatic script does, you can always look at /usr/src/usr.sbin/bsdinstall/scripts/zfsboot. Unfortunately the automated partitioning in bsdinstall for ZFS root doesn't let you use less than the entire disk, so I end up doing this a lot more than I want to.
 
zroot/usr isn't mounted as a real filesystem. The /usr directory is actually part of the / filesystem which is probably part of something like zroot/ROOT/default. ZFS requires that any datasets that are created are created inside a parent dataset so the datasets like zroot/usr/src have this zroot/usr as their parent just to satisfy that requirement.
Thank you very much.
 
Back
Top