Atomically replace symlink with the folder it points to

66 Views Asked by At

I have a symlink that points to a directory mounted via network file system like so:

2023 -> /mnt/bulk013/obs_data_archive/metwatch/2023/

now I want to replace the symlink with the folder that it points to in a fashion that doesn't disturb a productive application that frequently reads from this directory (atomically). This meant in my case first copying all the data to my local harddrive (where the folder 2023 lives). I did so and used a temporary directory to store the files:

2023.tmp/

So now the question is, how can I atomically switch the symlink with the actual folder, so that the folder then has the name 2023?

2023 -> /mnt/bulk013/obs_data_archive/metwatch/2023/   # remove this
2023.tmp/  # and replaced with this (renamed to 2023)
1

There are 1 best solutions below

2
Kaz On

In brief notation, if we have:

link -> dir/

and want to swizzle this to become:

link/

It would seem that what we want is to execute the system call rename("dir", "link/").

Unfortunately, that refuses to work on Linux with an errno of 20 (ENOTDIR). This is documented for rename by POSIX: one of the reasons rename can return ENOTDIR is:

the old argument names a directory and the new argument names a non-directory file

Looks like there may not be a way to do this; it has to be done in two operations, requiring the accessing application to be suspended.

If the application consists of a small number of processes, you may be able to kill -STOP them all, do the swizzle, and then kill -CONT. To a stopped process, the operation will appear atomic.