diff --git a/pkg/volume/util/atomic_writer.go b/pkg/volume/util/atomic_writer.go index c6fb49192e8..805647ab7ed 100644 --- a/pkg/volume/util/atomic_writer.go +++ b/pkg/volume/util/atomic_writer.go @@ -98,7 +98,10 @@ const ( // data to determine if an update is required. // 5.  A new timestamped dir is created // 6. The payload is written to the new timestamped directory -// 7.  Symlinks and directory for new user-visible files are created (if needed). +// 7.  A symlink to the new timestamped directory ..data_tmp is created that will +// become the new data directory +// 8.  The new data directory symlink is renamed to the data directory; rename is atomic +// 9.  Symlinks and directory for new user-visible files are created (if needed). // // For example, consider the files: // /podName @@ -113,9 +116,9 @@ const ( // The data directory itself is a link to a timestamped directory with // the real data: // /..data -> ..2016_02_01_15_04_05.12345678/ -// 8.  A symlink to the new timestamped directory ..data_tmp is created that will -// become the new data directory -// 9.  The new data directory symlink is renamed to the data directory; rename is atomic +// NOTE(claudiub): We need to create these symlinks AFTER we've finished creating and +// linking everything else. On Windows, if a target does not exist, the created symlink +// will not work properly if the target ends up being a directory. // 10. Old paths are removed from the user-visible portion of the target directory // 11.  The previous timestamped directory is removed, if it exists func (w *AtomicWriter) Write(payload map[string]FileProjection) error { @@ -178,12 +181,6 @@ func (w *AtomicWriter) Write(payload map[string]FileProjection) error { klog.V(4).Infof("%s: performed write of new data to ts data directory: %s", w.logContext, tsDir) // (7) - if err = w.createUserVisibleFiles(cleanPayload); err != nil { - klog.Errorf("%s: error creating visible symlinks in %s: %v", w.logContext, w.targetDir, err) - return err - } - - // (8) newDataDirPath := filepath.Join(w.targetDir, newDataDirName) if err = os.Symlink(tsDirName, newDataDirPath); err != nil { os.RemoveAll(tsDir) @@ -191,7 +188,7 @@ func (w *AtomicWriter) Write(payload map[string]FileProjection) error { return err } - // (9) + // (8) if runtime.GOOS == "windows" { os.Remove(dataDirPath) err = os.Symlink(tsDirName, dataDirPath) @@ -206,6 +203,12 @@ func (w *AtomicWriter) Write(payload map[string]FileProjection) error { return err } + // (9) + if err = w.createUserVisibleFiles(cleanPayload); err != nil { + klog.Errorf("%s: error creating visible symlinks in %s: %v", w.logContext, w.targetDir, err) + return err + } + // (10) if err = w.removeUserVisiblePaths(pathsToRemove); err != nil { klog.Errorf("%s: error removing old visible symlinks: %v", w.logContext, err)