commit b2519eeb09bcd93f2eda3eb34ea522489d83abf3 Author: Michael Meffie Date: Tue Nov 11 15:10:32 2025 -0500 Make OpenAFS 1.8.15pre1 Update version strings for the 1.8.15pre1 release. Change-Id: I83ca4b0c6a72affaf3529cb6503cff2e1d31454d Reviewed-on: https://gerrit.openafs.org/16617 Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason Reviewed-by: Cheyenne Wills Tested-by: BuildBot Reviewed-by: Benjamin Kaduk commit 0928123c3a83f3d6e36a1ac0d2466d851b1281a7 Author: Michael Meffie Date: Thu Nov 6 20:28:01 2025 -0500 Update NEWS for OpenAFS 1.8.15pre1 Change-Id: I7bbbc4cf98d60c4296c3719fb204d667235b64e5 Reviewed-on: https://gerrit.openafs.org/16613 Reviewed-by: Michael Meffie Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk commit 5bbc578f0852c6f953fbae679fa33671e15e16cb Author: Mark Vitale Date: Thu Dec 11 17:38:43 2025 -0500 DARWIN: Use AFS_LDRULE for privhelper The OpenAFS macOS (DARWIN) build process supports a builder-supplied ARCHFLAGS with multiple values. This allows building a single package that can install and run on any supported architecture (currently x86_64 and arm64). Executables created this way are known as "Universal" binaries. However, since its introduction (120871f03f38 "DARWIN: Add 'privhelper' tool for PrefPane"), the privhelper has only been built for the native platform. This is because its makefile ignores ARCHFLAGS. This results in the following symptoms: - If the package is built on x86 but installed on arm64: The org.openafs.privhelper will be x86-only and so requires and runs under Rosetta 2. If the OpenAFS cache manager is started using the prefpane (via the privhelper), this also results in the afsd threads running as x86 under Rosetta 2. However, both the prefpane and Cache Manager seems to work correctly under Rosetta 2. - If the package is built on arm64 but installed on x86: The org.openafs.privhelper will be arm-only and will fail to start. Therefore any prefpane operation requiring the privhelper will either fail or hang. However, the Cache Manager will work correctly. Modify the makefile to use AFS_LDRULE, so we respect ARCHFLAGS, CFLAGS, and any other related flags. For example, now ARCHFLAGS='-arch arm64 -arch x86_64' will build a universal package (including a universal privhelper) that will run natively regardless of the architecture of the build host or the install host. Reviewed-on: https://gerrit.openafs.org/16654 Reviewed-by: Benjamin Kaduk Reviewed-by: Michael Meffie Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason Reviewed-by: Marcio Brito Barbosa (cherry picked from commit 755cdbe546581746af1c819468d584c9cd414bf0) Change-Id: I9a750c36f7d06750eb15922f1e1baded9d9f8953 Reviewed-on: https://gerrit.openafs.org/16662 Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk commit a6a13a72042ccd7e966484bdf79068d1297e7e1f Author: Andrew Deason Date: Mon Nov 17 20:39:50 2025 -0600 afs: Save local copy of afs_fakestat_enable Since commit 629d080654 ("This is mostly a rewrite..."), afs_InitFakeStat() does nothing if afs_fakestat_enable is 0; it does not even set state->valid and leaves it uninitialized. When afs_PutFakeStat() is called later on (or one of the EvalFakeStat functions), as its caller must do, if afs_fakestat_enable is now non-zero, we will assert that state->valid is non-zero. But state->valid is uninitialized, and so may be zero; if it's zero, we'll panic the machine. Normally, the value of afs_fakestat_enable cannot change while we're running. But it does change at least once: during the startup sequence, afsd calls the AFSOP_SET_FAKESTAT syscall (if -fakestat or -fakestat-all are passed), which sets afs_fakestat_enable. Most code paths calling afs_InitFakeStat() / afs_PutFakeStat() are not possible until afsd has finished its startup sequence, since /afs is not mounted and files aren't accessible. But pioctls can be issued before /afs is mounted (with a NULL avc), and all pioctls call afs_InitFakeStat() and afs_PutFakeStat(). So, if someone runs a pioctl while 'afsd -fakestat' is running its startup sequence, it is possible for afs_fakestat_enable to be 0 while afs_InitFakeStat() is called, and nonzero when afs_PutFakeStat() is called, potentially causing a failed assert. This is possibly most likely with the PSetTokens/PSetTokens2 pioctls, since those operations involve taking other locks (such as afs_xuser), which may involve dropping AFS_GLOCK, allowing the value of afs_fakestat_enable to change in another afsd process. To fix this, change afs_InitFakeStat() to always initialize the 'state' struct, and remember the value of afs_fakestat_enable in a new struct afs_fakestat_state field called 'fakestat_enable'. Change other code paths using struct afs_fakestat_state to use state->fakestat_enable instead of the afs_fakestat_enable global; this helps ensure consistent behavior in the code that uses the struct afs_fakestat_state, even if the value of the afs_fakestat_enable global changes. While we're doing this, change all users of afs_fakestat_enable to try to avoid reading the value of afs_fakestat_enable multiple times in the same code path, and instead store a local copy of the value once. It should not be possible for the value of afs_fakestat_enable to actually change in these other code paths, but do this for consistency and extra safety. After this commit, there are still a few code paths remaining that read afs_fakestat_enable multiple times. Some callers do something like this: if (afs_fakestat_enable) { afs_InitFakeStat(&fakestate); afs_TryEvalFakeStat(...); afs_PutFakeStat(&fakestate); } And dentry_revalidate_common() calls afs_InitFakeStat(), and then later calls parent_vcache_dv(), which also itself calls afs_InitFakeStat(). Those code paths are also effectively re-reading afs_fakestat_enable (since afs_InitFakeStat() itself reads afs_fakestat_enable). But fixing those involves either rearranging the afs_InitFakeStat() calls or changing the afs_InitFakeStat() API. Fixing those cases is left for future commits; this commit just handles these easier cases. FIXES 135594 Reviewed-on: https://gerrit.openafs.org/16631 Reviewed-by: Cheyenne Wills Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Tested-by: BuildBot Reviewed-by: Benjamin Kaduk (cherry picked from commit d6f04a42dea931de50e027e66926889cb7e05072) Change-Id: I122fa459c1f9f30fa9613887eb9f08225a83f2a2 Reviewed-on: https://gerrit.openafs.org/16653 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie Reviewed-by: Cheyenne Wills Reviewed-by: Marcio Brito Barbosa Reviewed-by: Benjamin Kaduk commit a7170839e03b3da7673ec7536e627883d6f997d6 Author: Ben Huntsman Date: Fri Jan 31 20:22:39 2025 -0800 revert: Deorbit AIX-specific QuickStartGuide bits This reverts commit c16ec571273b03e9d4f4905efdeaa2182bbe0c6a, which removed the AIX-specific documentation from the Quick Start guide. With the AIX port working again, bring this documentation back into the Quick Start Guide. Reviewed-on: https://gerrit.openafs.org/16216 Tested-by: BuildBot Reviewed-by: Michael Meffie (cherry picked from commit c9eb881d7fd0ab2da2cc2f76d36de545f26719e3) Change-Id: I1a9854ce3ae09c299e8dd0b959ed3ded8fb862b3 Reviewed-on: https://gerrit.openafs.org/16635 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie Reviewed-by: Cheyenne Wills Reviewed-by: Marcio Brito Barbosa Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk commit 1a6417dd54adf686323ed214c0abbc702fbe32fa Author: Ben Huntsman Date: Tue Dec 10 19:05:20 2024 -0800 cf: Set default --with-aix-soname to 'svr4' OpenAFS builds both shared and static libraries by default. On most platforms, each library is built as a shared library libfoo.so.x.y.z, and as a static library libfoo.a. libtool refers to this as the 'svr4' style of libraries on AIX. On AIX, traditionally libraries are built with the shared library, static library, and various versions and 64-bit variants and such all contained in the same libfoo.a. libtool refers to this as the 'aix' style of libraries on AIX. libtool defaults to the 'aix' style on AIX, and so this is how libtool attempts to build our libraries on AIX. For many of our libraries, even though the build completes successfully, this results in broken binaries because our Makefile rules assume the shared and static library files have different names. For example, here is the install rule for librokenafs: install: $(SHARED_LIBS) librokenafs.a $(LT_INSTALL_DATA) librokenafs.la $(DESTDIR)$(libdir)/librokenafs.la $(RM) $(DESTDIR)$(libdir)/librokenafs.la $(INSTALL_DATA) librokenafs.a $(DESTDIR)$(libdir)/librokenafs.a On AIX, the LT_INSTALL_DATA step will install the shared library librokenafs.a into $(DESTDIR)$(libdir). Then the INSTALL_DATA step will install the static library librokenafs.a into the same location, deleting the shared library file. When the user tries to run an executable, they get an error, because the shared library librokenafs is not installed at all: $ /opt/openafs/bin/pts exec(): 0509-036 Cannot load program /opt/openafs/bin/pts because of the following errors: 0509-150 Dependent module /opt/openafs/lib/librokenafs.a(librokenafs.so.2) could not be loaded. 0509-152 Member librokenafs.so.2 is not found in archive To avoid this, the user can run configure with --with-aix-soname=svr4 to build all of our shared libraries in the 'svr4' style. In the above example, this causes LT_INSTALL_DATA to install the shared librokenafs as librokenafs.so.* into $(DESTDIR)$(libdir), and then the static library is installed as librokenafs.a like normal. The resulting binaries can then run without issue. To make it so users don't need to specify --with-aix-soname=svr4 to get a working build, change the default behavior to --with-aix-soname=svr4 by passing aix-soname=svr4 to LT_INIT. However, just specifying LT_INIT([aix-soname=svr4]) alone does not work, due to a bug in libtool: https://savannah.gnu.org/support/?111161 To workaround this bug, also explicitly turn on shared and static libraries by default in LT_INIT, even though they are already on by default. Using --disable-shared or --disable-static should still be honored as normal; the LT_INIT arguments just specify the default values. Ideally, we would install our shared libraries in the 'aix' style, so a single libfoo.a contains all of the necessary .o and .so files for that library. However, changing our build system to do this is difficult. And historically, OpenAFS has built shared libraries on AIX in the 'svr4' style; that is how we built shared libraries in OpenAFS 1.6 and earlier, before we converted to using libtool. Reviewed-on: https://gerrit.openafs.org/15983 Reviewed-by: Ben Huntsman Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason (cherry picked from commit b0e852bc1ab776cbfba770b23db7c07b662c958e) Change-Id: I831d71ace97f6b3a1eaa47df5e0fd1ed3ceb3850 Reviewed-on: https://gerrit.openafs.org/16634 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk commit 367adc7ef8433b7f73bff5834feac9b3d34c8f70 Author: Ben Huntsman Date: Sun Nov 24 11:10:14 2024 -0800 lwp: Ignore and clean the rw test utility The lwp test utility "rw" is not built by default. But if someone builds it explicitly, we should clean it during an clean pass. Also add it to a .gitignore file. Reviewed-on: https://gerrit.openafs.org/15972 Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason (cherry picked from commit 65a891b126ad3e7d6de463eae830035d3bbe6712) Change-Id: I53f5fb8eb65cfacf3d389c4ab13cbe2cb4ede5df Reviewed-on: https://gerrit.openafs.org/16633 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk commit 63e5034c311155361e19bb18666447a2bd9b7213 Author: Ben Huntsman Date: Fri Dec 27 12:11:47 2024 -0800 export: Call execerror as /usr/sbin/execerror On AIX, there are two kernel extensions, and each is loaded by a utility in src/export, cfgexport, and cfgafs. This utility calls the AIX "sysconfig" system call to load the extension into the kernel. Historically this usually works so error messages are not often seen, though the programs have facilities to display error messages. Error messages from the loading of kernel extensions are displayed using the execerror utility. Beginning with AIX 4.2, this utility was moved from /etc/execerror to /usr/sbin. The AFS cfg utlities were never updated. If an error occurs during loading of one of the extensions, the user receives the following misleading error: SYS_KLOAD: No such file or directory This error is not actually the result of the failed extension load, but actually the result of the next source code line: perror("SYS_KLOAD"); This error is actually a statement that the utility cannot find execerror. Update the utilities to call execerror from the correct location starting with AIX 4.2. Reviewed-on: https://gerrit.openafs.org/16006 Tested-by: BuildBot Reviewed-by: Ben Huntsman Reviewed-by: Cheyenne Wills Reviewed-by: Michael Meffie Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason (cherry picked from commit 3b605e621fee7403f20722d0c9b9f742ee998515) Change-Id: Ia7f66a606b4f898a821cf18da4bad66126671eb9 Reviewed-on: https://gerrit.openafs.org/16129 Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit e555c9cf3c2b6966559e34d646245cdc93c237ff Author: Andrew Deason Date: Thu May 18 17:18:53 2023 -0500 export: Modernize code Update the source code in src/export in various ways to use more modern conventions: - Get rid of K&R-style arguments. (An exception is error() and sys_error() in cfgexport.c, which use old-style arguments as a cheap imitation of varargs functions.) - Declare various local functions and globals as 'static' - Declare static functions before they are called (or move them, for small functions like usage()) - Declare functions as returning 'int' if they had no type - Declare all unspecified types as 'int' (function return types, arguments, and variables) - Include string.h for memset(), strcmp(), etc, and stdlib.h for exit() - Don't declare our own malloc() - Remove a few unused or #ifdef'd out functions Reviewed-on: https://gerrit.openafs.org/15449 Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Ben Huntsman Tested-by: BuildBot Reviewed-by: Michael Meffie (cherry picked from commit 3e360702426986424b9fdd69215c6fbb92f37e9a) Change-Id: Ie1c4a1082e68d7cad36f49b6493394ba0bbbce69 Reviewed-on: https://gerrit.openafs.org/16128 Reviewed-by: Ben Huntsman Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit 6fc9cf88a05b11183e737a3e8f0a64227c30cf97 Author: Andrew Deason Date: Tue Jan 7 16:25:35 2025 -0600 rx: Include rx_lwp.h et al in fallback rx_atomic.h In rx_atomic.h, our "fallback" implementation of atomics uses a global lock, using our afs_kmutex_t/MUTEX_ENTER() abstractions, but rx_atomic.h doesn't include any headers to define afs_kmutex_t et al. Most callers include rx_lwp.h or an equivalent before rx_atomic.h, but this is not guaranteed, and tests/rx/atomic-t.c (for example) does not do this. If someone tries to build OpenAFS on a platform that doesn't have a more specific rx atomic implementation, this means that building atomic-t fails: In file included from /.../tests/rx/atomic-t.c:34: /.../include/rx/rx_atomic.h: In function ‘rx_atomic_set’: /.../include/rx/rx_atomic.h:402:5: error: implicit declaration of function ‘MUTEX_ENTER’ [-Werror=implicit-function-declaration] MUTEX_ENTER(&rx_atomic_mutex); ^~~~~~~~~~~ /.../include/rx/rx_atomic.h:402:18: error: ‘rx_atomic_mutex’ undeclared (first use in this function); did you mean ‘rx_atomic_set’? MUTEX_ENTER(&rx_atomic_mutex); ^~~~~~~~~~~~~~~ rx_atomic_set To fix this, include rx_lwp.h in the "fallback" branch of rx_atomic.h (or rx_kmutex.h for the kernel, or rx_pthread.h for pthreads). This should ensure that our locking abstractions are defined appropriately so we can use the rx_atomic_mutex global lock. Reviewed-on: https://gerrit.openafs.org/16062 Tested-by: BuildBot Reviewed-by: Ben Huntsman Tested-by: Ben Huntsman Reviewed-by: Marcio Brito Barbosa Reviewed-by: Mark Vitale Reviewed-by: Cheyenne Wills Reviewed-by: Michael Meffie Reviewed-by: Andrew Deason (cherry picked from commit 18b4243772c361c460ee255f7ddabbecbee5071c) Change-Id: Ia8a3b69568d37d941f69d05a8fe9cc64d593676c Reviewed-on: https://gerrit.openafs.org/16127 Reviewed-by: Ben Huntsman Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit 53c4464883ec27f89bf34a50bb1b6c6f78f5da3c Author: Ben Huntsman Date: Mon Dec 2 16:43:57 2024 -0800 rx: Use sys/atomic_op.h on AIX 4.1+ Since commit 4505af8002 (aix: add atomic support), rx_atomic.h has used sys/atomic_op.h on AIX 6.1 and newer, but sys/atomic_op.h is available as far back as AIX 4.1. So, use sys/atomic_op.h on AIX 4.1+, so older versions of AIX can use proper atomics instead of the fallback implementation. Reviewed-on: https://gerrit.openafs.org/15975 Reviewed-by: Michael Meffie Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason (cherry picked from commit e79985dbf21acec5915e5ee75a42a34db0540848) Change-Id: I1e7ce32aa76b18bb084111141dbf214019b75db5 Reviewed-on: https://gerrit.openafs.org/16126 Reviewed-by: Ben Huntsman Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit 63163f26ef43920a93633c562a624257cb6684c2 Author: Andrew Deason Date: Fri Dec 30 19:17:10 2022 -0600 rx: Fix rx_atomic.h style nits Fix a few style nits in rx_atomic.h that have crept up over the years: - Make function definitions begin with a bare "{" line - Indent preprocessor directives - Add comments to the #endif of large #if blocks - Fix style of multi-line comments Reviewed-on: https://gerrit.openafs.org/15280 Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Marcio Brito Barbosa Reviewed-by: Benjamin Kaduk (cherry picked from commit 1f2a35871b5e9b93c766be04c196522112ff5009) Change-Id: Ieae8bee059c060a8f4044fa371058e79f2441efc Reviewed-on: https://gerrit.openafs.org/16125 Reviewed-by: Ben Huntsman Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Cheyenne Wills commit eb6753d93b930ad7d65772a9751117f6969a5e92 Author: Andrew Deason Date: Thu Oct 23 20:27:26 2025 -0500 LINUX: Zero code on EEXIST in afs_linux_read_cache In afs_linux_read_cache(), if we get a -EEXIST error from afs_add_to_page_cache_lru(), we'll effectively ignore the error, and go through the surrounding while() loop again to retry getting the relevant page. But when we do so, 'code' is still set to -EEXIST. So if find_get_page() now returns non-NULL, we'll break out of the while() loop, and continue through the rest of the function with 'code' still set. We won't update the given page, and we'll never set 'code' to anything else, eventually returning the confusing error -EEXIST. While triggering this may be a hard race to hit (it would require the backing page to suddenly exist between find_get_page() and afs_add_to_page_cache_lru()) and hasn't been known to actually happen, this seemingly could cause a afs_linux_readpage()/afs_linux_read_folio() to fail unexpectedly, possibly causing a spurious SIGBUS, which would be hard to identify. To avoid this, set 'code' to 0 after examining 'code' after the afs_add_to_page_cache_lru() call. Add some braces around the nearby 'if' to help make it clear this is outside of that block. This issue appears to have existed since this function was introduced in commit f75d84c404 (Add support for blocking readahead). Reviewed-on: https://gerrit.openafs.org/16590 Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Marcio Brito Barbosa Reviewed-by: Andrew Deason (cherry picked from commit aef55ce9e114fc1a8e16b82eadde5ead583d7b0d) Change-Id: I868d76873a8b12a98a036c69144674a4bde3f703 Reviewed-on: https://gerrit.openafs.org/16616 Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Cheyenne Wills Reviewed-by: Marcio Brito Barbosa Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie Reviewed-by: Benjamin Kaduk commit ec0be688f46ae7becf39bd1b24ea06f199212035 Author: Andrew Deason Date: Tue Jun 3 16:04:31 2025 -0500 afs: Pass relative cb time to CBHash in afs_create Currently, after calling an RPC that returns a CallBack promise, various vnode operations call something like this to queue the callback information locally: afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp); CBHash takes a relative time in seconds, and converts it to 128-second units, for use with our local 128-second buckets for tracking callback timeouts. Most callers just pass the CallBack.ExpirationTime returned from the relevant RPC. But in afs_create() since OpenAFS 1.0, we add the 'now' timestamp (the time when we started calling the RPC) to CallBack.ExpirationTime, making it an absolute timestamp, causing us to queue the callback in an arbitrary bucket. If we queue it in a bucket further in the future than it's supposed to be, we won't clear the CStatd flag on the vcache until much later than we're supposed to. For example: Say we create a file at time 1748960984, and we get an ExpirationTime of 14516 (about 4 hours). In afs_create(), tvc->cbExpires is correctly calculated to be 1748975500, but CBHash is given 1748975500, not 14516. So afs_QueueCallBack is given a hash index of 13663871, and so we queue the callback to bucket 127 (13663871 % CBHTSIZE == 127; assume 'base' is 0). If we gave the correct relative time 14516 to CBHash, we'd get a bucket of 113. We won't process the callback expiration (via afs_CheckCallbacks()) until we get to timeout bucket 127. We advance to the next timeout bucket about every 127 seconds (via afs_BumpBase()), so that means we won't process the callback for 16129 seconds. But the callback promise was only good for 14516 seconds; plus an extra 180 seconds or so for the viced ServerBias, so about 14696 seconds. That means there is a window of over 1000 seconds where the fileserver thinks the callback promise has expired, but the client thinks the callback is still valid. If someone else modifies the file during that window, the client won't see a callback break, and so will serve stale data to users. This situation is perhaps unlikely, since it requires the newly-created file to be untouched for between about 4 and 4.5 hours (the fileserver uses different callback times for different file usage, but a newly-created file can't have any other users, so should always get a callback of 4 hours). Also, the queued callback gets put in effectively a random timeout bucket, and we must put it in a timeout bucket further away than the correct bucket (if we put it in a closer bucket, we'll just check the expiration time too early, and then move it to the correct bucket). The correct bucket will be about 113 away, and there are only 128 buckets. So we have a 113/128 == 88% chance of not triggering the problem; only a 12% chance that the issue is possible at the current time. However, if the fileserver ever returns a shorter callback expiration time for a newly-created file, this issue could be much more likely to occur. To fix this, pass a relative time to the CBHash call for afs_QueueCallback (the untouched CallBack.ExpirationTime) in afs_create(), like we do for all other CBHash callers. Also initialize 'now' to the current time before our do/while retry loop, to make sure 'now' is initialized. Otherwise, some compilers complain that 'now' may be used uninitialized, even though this shouldn't actually be possible: .../src/afs/VNOPS/afs_vnop_create.c: In function ‘afs_create’: .../src/afs/VNOPS/afs_vnop_create.c:452:48: error: ‘now’ may be used uninitialized in this function [-Werror=maybe-uninitialized] tvc->cbExpires = CallBack.ExpirationTime + now; ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ cc1: all warnings being treated as errors Reviewed-on: https://gerrit.openafs.org/16601 Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Cheyenne Wills Reviewed-by: Michael Meffie Reviewed-by: Marcio Brito Barbosa Reviewed-by: Benjamin Kaduk (cherry picked from commit 9a1ae4f4ad6af62b24c4fe4a3a78bea052177043) Change-Id: I4d63ddbc8017216669d60cf0c1bb19d066ec37ae Reviewed-on: https://gerrit.openafs.org/16612 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk commit 0d3c54b6a02dc4b4d9a2e627f3a55be7fc653fc2 Author: Andrew Deason Date: Thu Sep 18 14:11:10 2025 -0500 lwp: Install compat header /usr/include/lock.h Commit 60da5c6988 (lwp: Rename lock.h to afs/afs_lock.h) renamed lwp's lock.h to afs/afs_lock.h, but old software (for example, dumpscan) may still try to include lock.h. For now, provide a lock.h header that just includes afs/afs_lock.h, to allow such software to potentially still build, but is otherwise unnecessary. This commit deliberately names the file in src/lwp something besides lock.h (old_lock_compat.h), to make sure nothing in the OpenAFS tree accidentally includes the header. Reviewed-on: https://gerrit.openafs.org/16550 Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Michael Meffie (cherry picked from commit 8a88905d315d81d7ceeebe0640d5bfbfe3e3f759) Change-Id: I204e5d16edd24cf1e5af6c99b066cd8b464c6c90 Reviewed-on: https://gerrit.openafs.org/16611 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit b95afb6c3acf0439fd011434ca12de2268c72881 Author: Alex Dehnert Date: Sat Aug 23 12:18:06 2025 -0400 lwp: Rename lock.h to afs/afs_lock.h OpenAFS installs a /usr/include/lock.h, which is a very generic name for an OpenAFS-specific file. It seems prudent to avoid using such a generic name to avoid conflicts. In particular, Python 3.13 *also* introduces a "lock.h" file, which means that software that builds with OpenAFS and Python is likely to break (see https://github.com/mit-athena/python-afs/issues/6#issuecomment-3089981708). Python is renaming their lock.h, probably starting in Python 3.15, but it would be good to deconflict on machines with 3.13 and 3.14 as well as other projects that might use that name. This change was partially automated, using the following commands: git grep --name-only '"lock.h"' src/vol | xargs sed -i -e 's%^#include "lock.h"%#include %' git grep --name-only '' | xargs sed -i -e 's%^#include %#include %' find . -name Makefile.in | xargs sed -i -e 's#${TOP_INCDIR}/lock.h#${TOP_INCDIR}/afs/afs_lock.h#' Reviewed-on: https://gerrit.openafs.org/16496 Reviewed-by: Michael Meffie Reviewed-by: Cheyenne Wills Tested-by: BuildBot (cherry picked from commit 60da5c6988f4192c98ad643141e14991b3166c6e) Change-Id: I6d0d5514c0e3f567620d1da78738637c52286f9b Reviewed-on: https://gerrit.openafs.org/16610 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit 5f5d5c48c00b509827166211abde2a7b87f2ae44 Author: Alex Dehnert Date: Sat Aug 2 13:07:00 2025 -0400 bucoord: Remove unneeded lock.h include dump.c doesn't appear to use anything from lock.h, so remove the include. Note that it still includes lock.h indirectly (dump.c -> afs/tcdata.h -> afs/budb.h -> ubik.h -> lock.h), so even if it did depend on something we wouldn't expect an error. Reviewed-on: https://gerrit.openafs.org/16495 Reviewed-by: Michael Meffie Reviewed-by: Alex Dehnert Reviewed-by: Andrew Deason Tested-by: BuildBot (cherry picked from commit 675071c170a64dcc3b734cf551a45ba2444d21b0) Change-Id: I6fb658abb3d394499e673b618d90aa85d003450f Reviewed-on: https://gerrit.openafs.org/16605 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk commit c379ff006d8b7db425f7648321c549ab24919d92 Author: Cheyenne Wills Date: Thu Oct 23 15:15:38 2025 -0600 linux: remove implied def HAVE_LINUX_FILEMAP_GET_FOLIO Commit: Linux: Use struct kiocb * for aops write_begin/end (1ad827ded0ed9) added 2 implied defines in osi_vnodeops, one for HAVE_LINUX_WRITE_BEGIN_END_FOLIO and one for HAVE_LINUX_FILEMAP_GET_FOLIO. The HAVE_LINUX_FILEMAP_GET_FOLIO was not needed, and causes a build failure: osi_vnodeops.c:4056:10: error: "HAVE_LINUX_FILEMAP_GET_FOLIO" redefined [-Werror] 4056 | # define HAVE_LINUX_FILEMAP_GET_FOLIO | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is because the configure test for __filemap_get_folio() succeeds (linux 6.15 and later) and the test for write_begin/end functions take a kiocb also succeeds (6.17 or later). Remove the unnecessary define. Reviewed-on: https://gerrit.openafs.org/16589 Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason Reviewed-by: Marcio Brito Barbosa Tested-by: BuildBot (cherry picked from commit 503ef823970695eb646a323f38b9c07d52971e69) Change-Id: I6a5768ac8e8f7cce79c5fbd67d5dcebfb4aead98 Reviewed-on: https://gerrit.openafs.org/16604 Reviewed-by: Andrew Deason Tested-by: BuildBot Reviewed-by: Benjamin Kaduk commit a765a9ddd412c8d1e5cb0f5cf497a8606251811e Author: Cheyenne Wills Date: Tue Oct 21 13:55:48 2025 -0600 Linux: Use struct kiocb * for aops write_begin/end The Linux 6.17 commit: fs: change write_begin/write_end interface to take struct kiocb * (e9d8e2bf23206) changed the address_space_operations members write_begin and write_end to use a 'struct kiocb *' instead of a 'struct file *' as the first parameter. The passed kiocb structure contains a pointer (ki_filp) to the file structure that is associated with the operation. Update the afs_linux_write_begin() and afs_linux_write_end() to accept a 'struct kiocb *' instead of a 'struct file *', and obtain the file pointer directly from kiocb. Add an autoconf test to determine if aops->write_begin()/aops->write_end uses a struct kiocb * as the first parameter. Reviewed-on: https://gerrit.openafs.org/16558 Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Andrew Deason Reviewed-by: Marcio Brito Barbosa (cherry picked from commit 1ad827ded0ed970540b6836250f2395ae31b84bc) Change-Id: I59d37422a280716dac3398c039fc728911a7bef2 Reviewed-on: https://gerrit.openafs.org/16603 Reviewed-by: Andrew Deason Tested-by: BuildBot Reviewed-by: Benjamin Kaduk commit 175cb545c4f3d26c41f21f8578e69b350204000a Author: Andrew Deason Date: Wed Jun 19 16:33:56 2024 -0500 xdr: Set 0 _len with NULL _val When passing a struct to an RPC with an OUT opaque or array arg, a few callers give a NULL _val (to indicate that xdr should allocate the memory for us), but leave _len uninitialized. This is okay, because xdr ignores the _len when _val is NULL, but set _len to 0 in these cases just in case, and to be more consistent with other callers. Reviewed-on: https://gerrit.openafs.org/16240 Reviewed-by: Michael Meffie Reviewed-by: Mark Vitale Reviewed-by: Marcio Brito Barbosa Reviewed-by: Andrew Deason Tested-by: BuildBot (cherry picked from commit 22f87bcb04d9127f8c8c11ebb3b8cd96028c3d4a) Change-Id: I45820542940ce66e7b392f060cd4b867c8f2ee2a Reviewed-on: https://gerrit.openafs.org/16267 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk commit d87b1ebf71367d36c1580c3b4980addfc8af0502 Author: Andrew Deason Date: Mon Jun 17 14:34:37 2024 -0500 afs: Always "goto out" in PGetVolumeStatus A few error code paths in PGetVolumeStatus were "return"ing directly, without going through the "goto out" destructor, allowing our allocated memory to be leaked. Fix these to go through the "goto out" destructor. Reviewed-on: https://gerrit.openafs.org/16238 Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Mark Vitale Reviewed-by: Marcio Brito Barbosa Reviewed-by: Andrew Deason (cherry picked from commit 801c18bf8a973846e4d7be3bc04dc92f14eb9da2) Change-Id: I9f1e8445a3dabb847adb0674611dc853c6629f88 Reviewed-on: https://gerrit.openafs.org/16262 Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie Tested-by: BuildBot Reviewed-by: Benjamin Kaduk commit 73f313faa9c7f33fa297898a52f54096a4a85be5 Author: Andrew Deason Date: Mon Sep 18 16:08:46 2023 -0500 viced: Give an actual 'prname' to hpr_NameToId In MapName_r(), we cast 'uname' (a char*) into a prname* when populating a 'namelist' to give to hpr_NameToId(). A 'prname' is just an rxgen-derived typedef for char[PR_MAXNAMELEN], which looks similar to a char*, but is a fixed-size array. MapName_r() passes the given 'namelist' to hpr_NameToId(), which calls ubik_PR_NameToID() -> PR_NameToID() -> xdr_namelist() -> xdr_array() -> xdr_prname() -> xdr_vector(). That will send exactly PR_MAXNAMELEN characters of the given name to the wire, even if the string is only a few characters long. If the given string is significantly shorter than PR_MAXNAMELEN characters, then we may send uninitialized data from the stack on the wire. The ptserver should ignore any data after the trailing NUL byte in the string, but the data will still be exposed on the wire, possibly allowing others to see the uninitialized stack data. To fix this, copy the given string into a local blanked 'prname', and use that instead, avoiding the cast. Also fix the 'ptclient' program, which uses a proper 'prname' array, but doesn't initialize all of the memory, causing a similar problem. Just change a malloc() to calloc() to fix it. All other callers of PR_NameToID pass a properly-initialized 'prname' (or an array of them), or use strncpy() to copy the given string, which fills the given array with NUL bytes. However, change several callers to memset() or calloc() the relevant memory, to try to avoid similar mistakes in the future (for example, if someone changes a strncpy() call to strlcpy()). The issue in the fileserver calling hpr_NameToId() was introduced in commit 8a040cfd848410b75b4e5ac5498f00f073932598 (viced: remove static local realms), included in OpenAFS 1.8.0, since the given string was no longer NUL-filled by strncpy(). FIXES 135444 Reviewed-on: https://gerrit.openafs.org/16147 Reviewed-by: Andrew Deason Tested-by: Andrew Deason (cherry picked from commit c57eddb1f24eba22902fe7726c54baedef642e06) Change-Id: I92c279ae33ae7de9ce58be4d7cb3cf0ac57bada9 Reviewed-on: https://gerrit.openafs.org/16207 Reviewed-by: Michael Meffie Reviewed-by: Andrew Deason Tested-by: BuildBot Reviewed-by: Benjamin Kaduk commit fb1cfa3b830c04b28a18081654a2fdd01955f4ef Author: Andrew Deason Date: Mon Sep 18 16:03:08 2023 -0500 viced: Protect vlConn in TryLocalVLServer In TryLocalVLServer(), 'vlConn' is a static rx_connection that is initialized just once. But no locks are held in this function, and so theoretically one thread could try to use vlConn while another is setting it, which is not safe. This function is only used for RXAFS_GetVolumeInfo, an old RPC that isn't called by anything in OpenAFS. Maybe this RPC can be disabled entirely, but for now at least protect vlConn with FS_LOCK to make sure it doesn't cause a segfault or memory corruption. Some other races are possible with 'down' and 'lastDownTime', but these just determine whether we exit early, and so racing on those is not such a big problem. FIXES 135444 Reviewed-on: https://gerrit.openafs.org/16146 Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Cheyenne Wills Reviewed-by: Mark Vitale Reviewed-by: Marcio Brito Barbosa Reviewed-by: Andrew Deason (cherry picked from commit 035cb883454eb5a6fac3dc1e3f8ef17a9f3f169e) Change-Id: I1210f01cc42ae563c0b62aa9788018015dadc06c Reviewed-on: https://gerrit.openafs.org/16206 Reviewed-by: Michael Meffie Reviewed-by: Andrew Deason Tested-by: BuildBot Reviewed-by: Benjamin Kaduk commit a9b4ce2ec32994d5873eadeeb58fe73d35e30862 Author: Andrew Deason Date: Mon Sep 18 16:10:27 2023 -0500 viced: calloc stats in SRXAFS_GetStatistics64 Since it was introduced in commit b651ece9bdb2ea9dc19907a5686e9d084f3c03d6 (large-partition-support-20080305), SRXAFS_GetStatistics64 allocates the stats memory with malloc(), and never sets the STATS64_BOOTTIME stat. As a result, the value for STATS64_BOOTTIME contains uninitialized heap data when sent over the wire. To fix this, change the stats to be calloc'd instead of malloc'd. FIXES 135444 Reviewed-on: https://gerrit.openafs.org/16145 Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Mark Vitale Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason (cherry picked from commit d9f6a21326bb609d7c5e1d0d80ad792b9fe786cc) Change-Id: I32ffdcc4b2e14a6d3f4dc8cd903bb5b65d1813b0 Reviewed-on: https://gerrit.openafs.org/16205 Reviewed-by: Mark Vitale Reviewed-by: Michael Meffie Reviewed-by: Andrew Deason Tested-by: BuildBot Reviewed-by: Benjamin Kaduk