0

I have a configuration file config_file that is stored on an NFSv3 network mount, and I would like to update that file safely.

Here are the conditions and restrictions that I'm working under:

  1. There must always be a config_file available to clients that want to read it
  2. The clients must never read corrupted data from a partially rewritten file
  3. The clients do not need config_file updated immediately. Waiting a minute or two for caches to update is perfectly fine so long as restrictions #1 and #2 are met

The NFSv3 implementations on both ends are RHEL (Red Hat Enterprise Linux).

Here's what I've come up with so far:

The client applications read from /mount/path/config_file, which is really a symlink to /mount/path/config_file_current

Let:

NEW = Path to the new configuration file that I'm try to install ( /path/to/my/workspace/config_file )
SYM = The path to the symlink ( /mount/path/config_file )
CURRENT = The path to the current version of config_file ( /mount/path/config_file_current )
TMP = The path to a temporary version of config_file ( /mount/path/config_file_tmp )
cp ${NEW} ${TMP}       # Initial copy of the new configuration file over the temporary file
ln -f ${TMP} ${SYM}    # Point the symlink to the temporary file [1]
rm ${CURRENT}          # To prevent torn reads, delete the previous file so that the file handle is "stale"
cp ${TMP} ${CURRENT}   # Copy the newest version of config_file back to ${CURRENT}
ln -f ${CURENT} ${SYM} # Point the symlink back to ${CURRENT}

[1] Symlink creation is one of the only two NFSv3 operations that are defined to be atomic in RFC 1813 (the NFSv3 specification file)

This procedure should be safe on a RHEL system operating on a local filesystem but not across any and all implementations of NFSv3 because a client could attempt to read from the stale file handle.

My question for the Server Fault community is this: Is this procedure safe for an NFSv3 implementation where both client and server are running RHEL?

I'm basing much of this on these two articles:

https://utcc.utoronto.ca/~cks/space/blog/sysadmin/SafelyUpdatingUnixFiles

https://utcc.utoronto.ca/~cks/space/blog/sysadmin/SafelyUpdatingNFSFiles

1 Answers1

0

It looks to me like you're making this harder / more complicated than it needs be. You're apparently doing a naming dance that, from my point of view as a system administrator for some, oh, 40 years now, is not only unnecessary but also prevents you from tracking some potentially useful information, though you may have another way to do the tracking.

In particular, this would be simpler:

ConfigDir=/some/path/for/new/and/old/config_files
NewFile=${ConfigDir}/<file_basename>.yyyymmddhhmmss # Tracking, here by timestamp
cp ${NEW} ${NewFile}    # Save the new config file where you're going to link to it
ln -f ${NewFile} ${SYM} # Point the symlink to the new configuration file
# The following is only necessary if you need to hurry along finding the new config
rm ${CURRENT}           # To prevent torn reads, delete the previous file so that the file handle is "stale"
CURRENT=${NewFile}

I don't know if you're running this in a looping structure or what, so maybe you need to set CURRENT and / or NewFile differently, but I think you'll get the idea. ... The old adage is wisdom: "KISS it! - Keep It Simple, Stupid!" It's nearly never bad advice.

Richard T
  • 1,206
  • 12
  • 29