mount(2) claims that it should fail with ENAMETOOLONG if the path is <= 255 or 1023 characters: [ENAMETOOLONG] A component of a pathname exceeded 255 characters, or the entire length of a path name exceeded 1023 charac- ters. In practice, that isn't true: # mount -t nullfs -o noatime /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/ports/distfiles /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles mount_nullfs: File name too long # echo mount -t nullfs -o noatime /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/ports/distfiles/ /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles | awk '{ print length($(NF - 1)), length($NF) }' 83 90 # It's failing a bounds check in nmount and its callees. I've seen this issue with both nullfs and UFS, so it's most likely a problem in vfs_mount.c, etc. I've seen this issue on 8.2-RELEASE (FreeNAS), as well as 9-CURRENT and 10-CURRENT. How-To-Repeat: #!/bin/sh set -e mkdir -p /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles/ md=$(mdconfig -a -t swap -s 512m) newfs /dev/$md mount /dev/$md /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles/
I looked into this more closely after I submitted the bug and the problem is the arbitrarily short value attached to MNAMELEN: 122537 mckusick #define MNAMELEN 88 /* size of on/from name bufs */ The value has changed over the years (all the way back to the mid-90s) from 90 to 70 to 80 to 88, but each time the author doesn't clearly state why the change was required. Testing out a kernel with the newly imposed limits to determine if the new limit is functional and/or there's a major performance regression with the new limit. Thanks, -Garrett
On Tue, 11 Oct 2011, Garrett Cooper wrote: >> Description: > mount(2) claims that it should fail with ENAMETOOLONG if the path is <= 255 or 1023 characters: > > [ENAMETOOLONG] A component of a pathname exceeded 255 characters, or > the entire length of a path name exceeded 1023 charac- > ters. > > In practice, that isn't true: > > # mount -t nullfs -o noatime /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/ports/distfiles /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles > mount_nullfs: File name too long There are limit of MNAMELEN = 88 and OMNAMELEN (a bit smaller) for mount(). This seems to be a new bug. In FreeBSD[1-4], mount() used normal pathname stuff and there were no references to MNAMELEN in vfs, and file systems like ffs silently ignored the ENAMETOOLONG error for copyinstr() of the user pathname to mp->mnt_stat.f_mntonname[] (which has size MNAMELEN). (This copyinstr() isn't quite normal pathname stuff either. copyinstr() to the namei buffer and using that for everything in the kernel would be normal. ffs_mount() also handles namei initialization and I think it uses a separate copyinstr() for f_mntonname[] in at least some cases because namei initialization occurs later.) This seems to have been broken somewhere in FreeBSD-5, probably collaterally with nmount(). FreeBSD-5.2 has up-front checks that the pathname fits in a buffer of size MNAMELEN, in both nmount(9) and mount(9). For nmount(), the pathname is far from normal, since it is passed as an option string. For mount(), the pathname starts as normal, but it is copyinstr()'ed into a malloc buffer of size MNAMELEN to join up with nmount(). ffs no longer (still in 5.2) copyinstr()'s the user path to mp->mnt_stat.f_mntonname[], but it still does an NDINIT() on args.fspec with arg UIO_USERSPACE; that now seems to work only accidentally, since the path is actually in UIO_SYSSPACE. Now in -current, even more of the initialization has been moved up to vfs; ffs still does the NDINIT() but it uses arg UIO_SYSSPACE. ISTR old PRs about almost the opposite problem, that you could mount things with paths so long that you couldn't easily unmount them, because the pathname in mp->mnt_stat.f_mntonname[] is truncated. Bruce
In our NanoBSD builds we use nullfs to provide a dir with packages to install. I changed the MAKEOBJDIR to include the full path to working directory to provide a means to separate multiple images and versions of images. nullfs couldn't handle the length of that path. I am -very- surprised that nullfs is not able to handle MAX_PATH length paths. Our workaround is the use the MD5 of the full path instead of the path itself: # XXX Take the MD5 of the path as mount_nullfs (for packages) does not handle long paths. See # FreeBSD PR kern/161481. p="$(echo "$PWD" | sed -Ee 's#^/((usr)?/home|Users)/##' | md5)" NANO_OBJ=${NANO_OBJ:-"/usr/obj/nanobsd/$p"} I do understand that this is actually a rather complex little bug, as it goes across a number of APIs.
I'm hitting this issue as well. On my boxes running an rsync-based backup of !FreeBSD systems to ZFS on FreeBSD, paths will routinely pass the 88 char limit in MNAMELEN. I expect that the issue also affects a large number of people running virtual systems and/or build hosts on ZFS, but also that they make workarounds without complaining. It looks like a discussion is also ongoing on the hackers list: http://marc.info/?l=freebsd-hackers&m=141485641407039&w=2
See the ino64 64-bit inode status update and call for testing: https://lists.freebsd.org/pipermail/freebsd-current/2017-April/065687.html
For bugs matching the following conditions: - Status == In Progress - Assignee == "bugs@FreeBSD.org" - Last Modified Year <= 2017 Do - Set Status to "Open"
Should be fixed now.