afs: Add static attribute to internal functions When building against a Linux 6.8 kernel, functions that are missing prototypes or declarations are flagged. We can add the static attribute to functions that are not referenced outside of the file that implements them to avoid having these functions flagged by the compiler. These functions are flagged due to missing prototypes when building against a Linux 6.8 kernel (which sets the -Wmissing-declarations and -Wmissing-prototypes compiler flags as default). Linux 6.8 commit: 'Makefile.extrawarn: turn on missing-prototypes globally' (0fcb70851f). When building against a kernel with CONFIG_WERROR=y, the build fails. There are no functional changes in this commit. Change-Id: I24c78a3167f6a81da4f62267cf901024468ae6b3 Reviewed-on: https://gerrit.openafs.org/15625 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
LINUX: Make 'fs flush*' invalidate dentry Our 'fs flush' and related commands (flushall, flushvolume) clear the relevant entries in the OpenAFS stat cache and data cache, which can fix problems if the cache ever becomes incorrect for any reason. (This can happen after bugs, repairing corrupted volumes, disaster recovery scenarios, and similar edge cases.) However, on Linux, these commands don't affect the VFS dentry cache. If someone needs to use an 'fs flush' command to fix a problem, this will fix the OpenAFS cache, but the Linux dcache can still be wrong. The only way to manually flush dcache entries is to use the global 'drop_caches' mechanism, which is a very heavweight operation, only accessible to root. For example: $ ls -l ls: cannot access foo.1: No such file or directory total 2 drwxrwxr-x. 2 bin adeason 2048 Apr 6 14:20 dir -?????????? ? ? ? ? ? foo.1 $ fs flush . $ ls -l ls: cannot access foo.1: No such file or directory total 2 drwxrwxr-x. 2 bin adeason 2048 Apr 6 14:20 dir -?????????? ? ? ? ? ? foo.1 $ sudo sysctl -q -w vm.drop_caches=3 $ ls -l total 3 drwxrwxr-x. 2 bin adeason 2048 Apr 6 14:20 dir -rw-rw-r--. 1 bin adeason 29 Sep 22 2022 foo.1 To make the 'fs flush' commands be effective in more situations, change afs_ResetVCache() to also invalidate the dcache entries associated with each vcache we reset. To make things simpler and reduce locking complexity, do this by setting d_time to 0, and don't directly run dcache-managing functions like d_invalidate or d_drop, etc. The above example now becomes: $ ls -l ls: cannot access foo.1: No such file or directory total 2 drwxrwxr-x. 2 bin adeason 2048 Apr 6 14:20 dir -?????????? ? ? ? ? ? foo.1 $ fs flush . $ ls -l total 3 drwxrwxr-x. 2 bin adeason 2048 Apr 6 14:20 dir -rw-rw-r--. 1 bin adeason 29 Sep 22 2022 foo.1 Change-Id: Ic95ef6137f5b671baf68a4890ef1562f029af794 Reviewed-on: https://gerrit.openafs.org/15391 Reviewed-by: Cheyenne Wills <cwills@sinenomine.net> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: BuildBot <buildbot@rampaginggeek.com>
clang-16: Fix simple unused-but-set variables Clang-16 is flagging variables as unused-but-set-variables resulting in build errors when --enable-warning is used. db_verify.c:996:9: error: variable 'builtinUsers' set but not used [-Werror,-Wunused-but-set-variable] int builtinUsers = 0; ^ Remove the variables that are set but never actually used. This commit fixes the simpler cases where variables are only set but not used elsewhere. Change-Id: I45674871cfc70a7e57c7c3e2d74ec81a4433a7c4 Reviewed-on: https://gerrit.openafs.org/15178 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Andrew Deason <adeason@sinenomine.net> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Avoid always-false NULL test on AFSTOV(avc) GCC-12 is flagging a comparison with the following diagnostic: src/afs/afs_vcache.c:3161:25: error: the comparison will always evaluate as ‘false’ for the address of ‘v’ will never be NULL [-Werror=address] 3161 | AFSTOV(avc) == NULL || vType(avc) == VDIR || | ^~ When the vcache structure does not have the vnode embedded the expansion of the AFSTOV macro results in: ((avc)->v) which tests contents of a 'v'. When the vcache structure does have the vnode embedded, the expansion of the macro results in: (&(avc)->v) which tests the address of 'v', which will never be NULL in this case. Update afs.h to add a new define 'AFS_VCACHE_EMBEDDED_VNODE' when the vcache structure contains an embedded vnode structure. Restructure the preprocessor statements for the AFSTOV definition Avoid testing AFSTOV(x) against NULL when AFS_VCACHE_EMBEDDED_VNODE is defined. The diagnostic is changed from a warning to an error when configured with --enable-checking. Change-Id: Ib72647fa23e5a7ecd96772b04c6ef76540f44535 Reviewed-on: https://gerrit.openafs.org/14956 Reviewed-by: Michael Meffie <mmeffie@sinenomine.net> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Andrew Deason <adeason@sinenomine.net> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
FBSD: Check VOP_ISLOCKED for LK_EXCLUSIVE A couple of places in the code check if a vnode is locked by the current thread by simply checking 'if (VOP_ISLOCKED(vp))'. But VOP_ISLOCKED() doesn't just return a simple 1 or 0, it returns LK_* constants (or 0). LK_EXCLUSIVE indicates that the calling thread holds an exclusive lock on the vnode, but LK_SHARED means someone holds a shared lock (possibly not the current thread), and LK_EXCLOTHER indicates that a different thread holds an exclusive lock. Because of this, it's possible for us to skip grabbing the vnode lock for certain operations, if someone else holds the lock at the same time. For example, this can happen when we call vinvalbuf() inside afs_GetVCache(), and FreeBSD will warn us that we didn't lock the vnode: #0 0xffffffff80bf6557 at kdb_backtrace+0x67 #1 0xffffffff80c7a337 at assert_vop_locked+0x77 #2 0xffffffff80c7a273 at vinvalbuf+0x23 #3 0xffffffff8285aa2d at afs_GetVCache+0x25d #4 0xffffffff828d3325 at afs_root+0x145 #5 0xffffffff80c70296 at lookup+0x8c6 #6 0xffffffff80c6f599 at namei+0x4a9 #7 0xffffffff80c872e4 at sys_lpathconf+0x54 #8 0xffffffff81074581 at amd64_syscall+0x291 #9 0xffffffff8104cde0 at fast_syscall_common+0x101 vnode 0xfffff8012a62bc58: tag afs, type VDIR usecount 2, writecount 0, refcount 2 mountedhere 0 flags (VV_ROOT|VI_ACTIVE) lock type afs: UNLOCKED #0 0xffffffff80b81fc2 at lockmgr_lock_fast_path+0x1e2 #1 0xffffffff811fa9f6 at VOP_LOCK1_APV+0x96 #2 0xffffffff80c8c705 at _vn_lock+0x65 #3 0xffffffff80c7c066 at vget+0xa6 #4 0xffffffff828d3437 at afs_root+0x257 #5 0xffffffff80c70296 at lookup+0x8c6 #6 0xffffffff80c6f599 at namei+0x4a9 #7 0xffffffff80c872e4 at sys_lpathconf+0x54 #8 0xffffffff81074581 at amd64_syscall+0x291 #9 0xffffffff8104cde0 at fast_syscall_common+0x101 vc 0xfffffe002be00000 vp 0xfffff8012a62bc58 tag afs, fid: 1.536870924.1.1, opens 0, writers 0 To fix this, change our "islocked"-style checks to check if VOP_ISLOCKED() returns LK_EXCLUSIVE specifically. Change-Id: If322f62dc443ee9acc2349a23c6c618afd3e29d4 Reviewed-on: https://gerrit.openafs.org/14204 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: BuildBot <buildbot@rampaginggeek.com>
IRIX: Remove pre-65 code Commit d1923139 (irix kill efs and start pruning pre-65) removed all files that defined AFS_SGI64_ENV and earlier, but didn't remove that code that depended on those defines. In addition, there has been code in the tree that checks for AFS_SGI53_ENV since OpenAFS 1.0, but nothing has ever defined Irix 5.3 support in OpenAFS. Remove all of this obsolete code. Change all references to AFS_SGIXX_ENV to AFS_SGI_ENV, and assume AFS_SGI_ENV is defined in all IRIX dirs. Consolidate some of the resulting ifdef logic appropriately. Change-Id: I9dd426296e04801980b805a5e195063762b23189 Reviewed-on: https://gerrit.openafs.org/14230 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Remove 'retry' arg from afs_FindVCache Since OpenAFS 1.0, afs_FindVCache has had an optional 'retry' output arg. The relevant functionality appears to have been specific to Irix versions before 5.3, but even OpenAFS 1.0 only had param.h files and general build logic for Irix 6.2 and later. With commit 13e44b2b (afs: Refactor osi_vnhold/AFS_FAST_HOLD), the unused 'retry' argument has now been removed from the lower-level osi_vnhold function, so now remove it from afs_FindVCache and related comments, and remove the associated logic to handle a non-zero 'retry'. Change-Id: I4464347bf6e0a57f8babbcdcdf5283e52532f687 Reviewed-on: https://gerrit.openafs.org/14231 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Avoid touching CBRs after free Currently, we free our CBR structures in shutdown_vcache, but later on in shutdown_server, we call afs_FreeCBR on each one that's attached to a struct server. afs_FreeCBR doesn't actually free the memory; it just modifies some pointers to put the CBR on the free list. Since we do this after the underlying memory has been freed, it can cause a panic during shutdown since the structures are no longer valid. To avoid this, make the afs_FreeCBR calls inside shutdown_vcache, right before the memory is freed. Change-Id: I142126d6aa811762b6c234d05abdac3764dad887 Reviewed-on: https://gerrit.openafs.org/14165 Reviewed-by: Michael Meffie <mmeffie@sinenomine.net> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: BuildBot <buildbot@rampaginggeek.com>
LINUX: defer afs_remunlink when current->fs==NULL afs_remunlink is called to delete a file on the fileserver after it has been silly-renamed (due to being unlinked while the file is open). Sometimes current->fs is NULL when this happens, typically when the process is shutting down, after current->fs has been freed and file handles are getting released. During afs_remunlink, we need to interact with our cache files, and so we call dentry_open, which calls security_file_open, which calls into the configured LSM for security checks. Certain LSMs (e.g. Crowdstrike Falcon) will panic the kernel in this situation if current->fs is NULL. There's no way to skip the LSM hooks, or to flag to the LSM that we're making an in-kernel VFS call, so the only way to avoid these panics is to do our I/O in another thread. Fortunately, we already have a way to defer afs_remunlink calls to a background daemon (CUnlinkedDel), since we already do this in some cases (when someone else is holding afs_xvcache or afs_xdcache). So, to avoid the panic in the above scenario, defer calls to afs_remunlink to a background daemon using CUnlinkedDel when current->fs is NULL, and we're using a disk cache. More details on this issue is discussed at following thread: https://lists.openafs.org/pipermail/openafs-info/2021-March/043073.html Change-Id: I1ee83d088a9b661d2974ce24b36bfd9f6ea4e7e9 Reviewed-on: https://gerrit.openafs.org/14691 Tested-by: BuildBot <buildbot@rampaginggeek.com> Tested-by: Jonathan Billings <jsbillings@jsbillings.org> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Change AFS*_LINUXnn_ENV to AFS*_LINUX_ENV The minimum Linux kernel that is now supported is linux-2.6.18. The Linux versioned preprocessor macros AFS_*LINUXnn_ENV are no longer needed to distinguish the different levels of Linux and can be merged into just a single set of macros. Perform a global change of _LINUX\d+_ENV to _LINUX_ENV. e.g. AFS_LINUX24_ENV -> AFS_LINUX_ENV AFS_USR_LINUX24_ENV -> AFS_USR_LINUX_ENV AFS_AMD64_LINUX20_ENV -> AFS_AMD64_LINUX_ENV Replace the multiple definitions for the versioned 'AFS*_LINUXnn_ENV' with just single non-version definitions 'AFS*_LINUX_ENV'. Apart from replacing the now-redundant #define directives and tidying up a few comments at the close of a preprocessor block to match their current form, this commit was done using a mechanical change of the variable names and did not reduce preprocessor statements that could now be combined or eliminated. Nor does this commit remove dead code. A follow-up commit (Cleanup AFS_*LINUX_ENV usage) will handle these changes. The updates should have no functional changes. Change-Id: I71e32ca9818d28f82b4f23679868d1b9a62c44bd Reviewed-on: https://gerrit.openafs.org/14387 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
afs: write-lock vcache->lock in afs_InactiveVCache Since the original IBM code import, the comments for afs_InvalidateAllSegments indicate that vcache->lock W should be held at entry. However, even back then, only LINUX and IRIX honored this requirement when the 'inactive' vnode operation reached afs_InvalidateAllSegments. Over the years, a number of commits have changed the operation and locking for the LINUX inactive vnode op: 5293aa35617a6ad35980ce16fdf492ea960cc18a linux-iput-and-glock-changes-20010130 e8591334602e5e8dad78dc6426d3c44d564572c1 linux-osi-clear-inode-locking-fix-20010816 652f3bd9cb7a5d7833a760ba50ef7c2c67214bba linux-dynamic-inodes-20050710 e0d9e434bb778a2507c1cd6d96c1faa2071f2b2c put-inode-speedup-20050815 b21c13dc3ab751118220dc31276995050841a1ae linux-dentry-iput-20060813 Eventually, ac52e2f3c0bec9298d020de963036409165f380e linux-dont-lock-around-inactivevcache-20061010 removed the vcache->lock from afs_dentry_iput (the current OpenAFS handler for inactive vcaches). The commit message states: "iafs_InactiveVCache() [sic] calls afs_InvalidateAllSegments() which says it should be called with the vnode locked. so the lock should probably be moved to afs_InactiveVCache() so it can be droppped before calling afs_remunlink()." Unfortunately, the vcache->lock was never moved to afs_InactiveVCache. Finally, 3be5880d1d2a0aef6600047ed43d602949cd5f4d 'afs: Avoid panics in afs_InvalidateAllSegments' introduced a background operation BInvalidateSegments that contains an assert for vcache->lock. This assert has exposed the existing lack of proper locking for some paths to afs_InvalidateAllSegments by causing a kernel panic: d_iput -> afs_dentry_iput -> afs_InactiveVCache -> afs_InvalidateAllSegments -> afs_BQueue(BOP_INVALIDATE_SEGMENTS..) -> BInvalidateSegments -> osi_Assert(WriteLocked(&vcache->lock)) Prevent the panic by modifying afs_InactiveVCache to obtain vcache->lock W before calling afs_InvalidateAllSegments, and dropping it before calling afs_remunlink. Thanks to Chaskiel Grundman for reporting and diagnosing the problem. Change-Id: Ic309e4006bf47bcb38fa2b53bf103e0c645a856d Reviewed-on: https://gerrit.openafs.org/14584 Reviewed-by: Andrew Deason <adeason@sinenomine.net> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Handle osi_NewVnode failures Currently, code inside afs_vcache.c assumes that osi_NewVnode always returns non-NULL, which means that osi_NewVnode must panic if it cannot create a new vnode. All of the callers of afs_GetVCache, afs_NewVCache, etc, already handle getting a NULL return, though (after all, the given fid may not exist or be inaccessible due to network errors, etc). So, just propagate NULL returns from osi_NewVnode up to our callers, to avoid panics in these situations. Modify osi_NewVnode on many arches to return an error on allocation failure, instead of panic'ing. Change-Id: Ib578b1747590bdf65327d4674e0849811ed999eb Reviewed-on: https://gerrit.openafs.org/13701 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Reviewed-by: Yadavendra Yadav <yadayada@in.ibm.com> Tested-by: BuildBot <buildbot@rampaginggeek.com>
afs: Let afs_ShakeLooseVCaches run longer Currently, when afs_ShakeLooseVCaches runs osi_TryEvictVCache, we check if osi_TryEvictVCache slept (i.e. dropped afs_xvcache/GLOCK). If we sleep over 100 times, then we stop trying to evict vcaches and return. If we have recently accessed a lot of AFS files, this limitation can severely reduce our ability to keep our number of vcaches limited to a reasonable size. For example: Say a Linux client runs a process that quickly accesses 1 million files (a simple 'find' command) and then does nothing else. A few minutes later, afs_ShakeLooseVCaches is run, but since all of the newly accessed vcaches have dentries attached to them, we will sleep on each one in order to try to prune the attached dentries. This means that afs_ShakeLooseVCaches will evict 100 vcaches, and then return, leaving us with still almost 1 million vcaches. This will happen repeatedly until afs_ShakeLooseVCaches finally works its way through all of the vcaches (which takes quite a while, if we only clear 100 at once), or the dentries get pruned by other means (such as, if Linux evicts them due to memory pressure). The limit of 100 sleeps was originally added in commit 29277d96 (newvcache-dont-spin-20060128), but the current effect of it was largely introduced in commit 9be76c0d (Refactor afs_NewVCache). It exists to ensure that afs_ShakeLooseVCaches doesn't take forever to run, but the limit of 100 sleeps may seem quite low, especially if those 100 sleeps run very quickly. To avoid the situation described above, instead of limiting afs_ShakeLooseVCaches based on a fixed number of sleeps, limit it based on how long we've been running, and set an arbitrary limit of roughly 3 seconds. Only check how long we've been running after 100 sleeps like before, so we're not constantly checking the time while running. Log a new warning if we exit afs_ShakeLooseVCaches prematurely if we've been running for too long, to help indicate what is going on. Change-Id: I65729ace748e8507cc0d5c26dec39e74d7bff5d2 Reviewed-on: https://gerrit.openafs.org/14254 Reviewed-by: Cheyenne Wills <cwills@sinenomine.net> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Log warning when we detect too many vcaches Currently, afs_ShakeLooseVCaches has a kind of warning that is logged when we fail to free up any vcaches. This information can be useful to know, since it may be a sign that users are trying to access way more files than our configured vcache limit, hindering performance as we constantly try to evict and re-create vcaches for files. However, the current warning is not clear at all to non-expert users, and it can only occur for non-dynamic vcaches (which is uncommon these days). To improve this, try to make a general determination if it looks like the stat cache is "stressed", and log a message if so after afs_ShakeLooseVCaches runs (for all platforms, regardless of dynamic vcaches). Also try to make the message a little more user-friendly, and only log it (at most) once per 4 hours. Determining whether the stat cache looks stressed or not is difficult and arguably subjective (especially for dynamic vcaches). This commit draws a few arbitrary lines in the sand to make the decision, so at least something will be logged in the cases where users are constantly accessing way more files than our configured vcache limit. Change-Id: I022478dc8abb7fdef24ccc06d477b349cca759ac Reviewed-on: https://gerrit.openafs.org/13255 Reviewed-by: Cheyenne Wills <cwills@sinenomine.net> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Refactor osi_vnhold/AFS_FAST_HOLD Make a few changes to osi_vnhold and AFS_FAST_HOLD: - Currently, the second argument of osi_vnhold ("retry") is never used by any implementation. Get rid of it. - AFS_FAST_HOLD() is the same as osi_vnhold(). Get rid of AFS_FAST_HOLD, and just have all callers use osi_vnhold instead. - Allow osi_vnhold to return an error, and adjust callers to handle it. - Change osi_vnhold to be a real function, instead of a macro, to make nontrivial implementations less cumbersome. Most platforms never return an error from osi_vnhold(), so the added code paths to check the return value of osi_vnhold() will not trigger. However, this lets us add future commits that do make osi_vnhold() return an error. Change-Id: Id2f3717be6c305d06305685247ac789815e1ebf7 Reviewed-on: https://gerrit.openafs.org/13971 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
FBSD: Avoid holding AFS_GLOCK during vinvalbuf Currently we call vinvalbuf(9) in a few places while holding AFS_GLOCK, but AFS_GLOCK is a non-sleepable lock (struct mtx), and vinvalbuf can sleep. This can trigger a panic in some rare conditions, with the message: Sleeping thread (tid 100179, pid 95481) owns a non-sleepable lock To avoid this, drop AFS_GLOCK around a few places that call vinvalbuf(). Change-Id: I58acb144b6ffa007675402e7639b63ff3745dec5 Reviewed-on: https://gerrit.openafs.org/13970 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: BuildBot <buildbot@rampaginggeek.com>
afs: Fix ifdef indenting in afs_vcache.c Change-Id: Ib566156184cb3f64a0983babd5d9f7883c84cc85 Reviewed-on: https://gerrit.openafs.org/13877 Reviewed-by: Michael Meffie <mmeffie@sinenomine.net> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: Benjamin Kaduk <kaduk@mit.edu>
FBSD: Remove pre-8 code Commit 123f0fb1 (config: remove support for old FreeBSD releases) removed our support for FreeBSD releases before FreeBSD 8. However, various areas of code still reference the symbols from those old versions (e.g. AFS_FBSD53_ENV). Remove our ifdef logic for these old symbols, according to the following rules: - In FBSD-specific dirs, assume AFS_FBSD80_ENV is always true (as well as the symbols for earlier versions) - In non-FBSD dirs, convert AFS_FBSD80_ENV to AFS_FBSD_ENV (and do the same for all earlier versions) This allows us to remove code that was specific to older FreeBSD versions, and simplify some ifdef conditionals. Also remove the definitions for AFS_FBSD80_ENV and earlier versions in our existing param.h files. With this commit, the functions afs_start, afs_vop_lock, afs_vop_unlock, and afs_vop_islocked are now always unreferenced, so remove them. Change-Id: Ia5a5ba5ee5b71a86cb4514305e20f1bb34487100 Reviewed-on: https://gerrit.openafs.org/13812 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Tim Creech <tcreech@tcreech.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Remove dead code There is a perhaps-surprisingly large amount of code disabled behind directives like '#if 0', '#ifdef notdef', and '#ifdef notyet'. At best, this code is clutter, and at worst some of it is confusing/outdated, and/or confusingly nested inside other preprocessor conditionals. Sometimes this disabled code shows up when grepping the tree, and causes a nuisance when refactoring related areas of code. Get rid of all of it. If anyone ever wants this code back, it can always be restored by reverting portions of this commit. Also delete some comments that clearly refer to the disabled code, and in some cases, adjust the adjacent comments to make sense accordingly. This commit doesn't touch any files in src/external/. Change-Id: If260a41257e8d107930bd3c177eddb8ab336f0d1 Reviewed-on: https://gerrit.openafs.org/13683 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: Benjamin Kaduk <kaduk@mit.edu>
afs: Remove reference to nonexistent function The real lie here is that TellALittleWhiteLie exists in afs_vcache.c. That has never been true, ever since OpenAFS 1.0. Change-Id: I5ba121db5b4f0bbe7a37054a3d2d8c46f6c49c0a Reviewed-on: https://gerrit.openafs.org/13697 Reviewed-by: Benjamin Kaduk <kaduk@mit.edu> Tested-by: BuildBot <buildbot@rampaginggeek.com>