Description of problem: After exporting the root directory ('/'), it is impossible to unexport it using `exportfs -u ...` (unless you unexport all exports with `-a`). Version-Release number of selected component (if applicable): nfs-utils-2.5.3-0.fc33.x86_64 How reproducible: Always. Steps to Reproduce: 1. exportfs localhost:/ 2. exportfs -u localhost:/ Actual results: exportfs: Could not find 'localhost:/' to unexport. Expected results: The unexport command should work. Additional information: Note that this happens also on rawhide (nfs-utils-2.5.3-3.rc1.fc35.x86_64).
Checking the code quickly.... That "Could not find" error is from unexportfs_parsed. Looks like client_gettype("localhost") returns MCL_FQDN, so this means we've searched exportlist[MCL_FQDN] and found nothing matching with e_path "/" and hostname "localhost". (I wonder why it also checks m_type, shouldn't that be redundant? I haven't thought about this data structure in a while.) Might be interesting to see the output of "exportfs -v" before and after the initial "exportfs localhost:/".
I was always starting with an empty export table: ``` # exportfs -v # exportfs localhost:/ # exportfs -v / localhost(sync,wdelay,hide,no_subtree_check,sec=sys,ro,root_squash,no_all_squash) # exportfs -u localhost:/ exportfs: Could not find 'localhost:/' to unexport. # exportfs -v / localhost(sync,wdelay,hide,no_subtree_check,sec=sys,ro,root_squash,no_all_squash) ``` And FWIW, if I use an IP (127.0.0.1) instead of a hostname, the result is the same: ``` # exportfs -v # exportfs 127.0.0.1:/ # exportfs -v / 127.0.0.1(sync,wdelay,hide,no_subtree_check,sec=sys,ro,root_squash,no_all_squash) # exportfs -u 127.0.0.1:/ exportfs: Could not find '127.0.0.1:/' to unexport. # exportfs -v / 127.0.0.1(sync,wdelay,hide,no_subtree_check,sec=sys,ro,root_squash,no_all_squash) ```
Thanks. Nothing's jumping out at me here. The next step might be to watch that loop in unexportfs_parsed() under a debugger.
OK, so I looked at the source code and I immediately saw what seems to be the culprit: 366 static void 367 unexportfs_parsed(char *hname, char *path, int verbose) 368 { [...] 380 /* 381 * It's possible the specified path ends with a '/'. But 382 * the entry from exportlist won't has the trailing '/', 383 * so need to deal with it. 384 */ 385 size_t nlen = strlen(path); 386 while (path[nlen - 1] == '/') 387 nlen--; Should be a trivial patch to simply prepend `nlen > 1 && ` to the loop condition. It's now even accessing path[-1] when given any string of just slashes... Shall I submit a patch somewhere or will it be quicker if you guys fix it? :P
Oh, good spotting. Were you able to confirm that the unexport works after that? Best if you can would be to send a patch to steved, cc'd to linux-nfs.org (the public nfs mailing list).
OK, patch posted: https://lore.kernel.org/linux-nfs/20210322210238.96915-1-omosnace@redhat.com/T/
(And forgot to add: yes, I tested it and it fixes the issue :)
FEDORA-2021-f1f18d78a6 has been submitted as an update to Fedora 33. https://bodhi.fedoraproject.org/updates/FEDORA-2021-f1f18d78a6
FEDORA-2021-f1f18d78a6 has been pushed to the Fedora 33 testing repository. Soon you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2021-f1f18d78a6` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2021-f1f18d78a6 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2021-f1f18d78a6 has been pushed to the Fedora 33 stable repository. If problem still persists, please make note of it in this bug report.