Skip to content

Commit 54a18f3

Browse files
committed
Prefer CoW over hard link
1 parent 7c6d60d commit 54a18f3

File tree

5 files changed

+28
-10
lines changed

5 files changed

+28
-10
lines changed

osu.Game/Database/ImportParameters.cs

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public struct ImportParameters
1717
/// </remarks>
1818
public bool Batch { get; set; }
1919

20+
/// <summary>
21+
/// Whether this import should use copy on write cloning if available.
22+
/// </summary>
23+
public bool PreferCopyOnWrite { get; set; }
24+
2025
/// <summary>
2126
/// Whether this import should use hard links rather than file copy operations if available.
2227
/// </summary>

osu.Game/Database/LegacyModelImporter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public Task ImportFromStableAsync(StableStorage stableStorage)
6161
{
6262
var tasks = GetStableImportPaths(storage).Select(p => new ImportTask(p)).ToArray();
6363

64-
await Importer.Import(tasks, new ImportParameters { Batch = true, PreferHardLinks = true }).ConfigureAwait(false);
64+
await Importer.Import(tasks, new ImportParameters { Batch = true, PreferHardLinks = true, PreferCopyOnWrite = true }).ConfigureAwait(false);
6565
});
6666
}
6767

osu.Game/Database/RealmArchiveModelImporter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public async Task<ExternalEditOperation<TModel>> BeginExternalEditing(TModel mod
336336
foreach (var filenames in getShortenedFilenames(archive))
337337
{
338338
using (Stream s = archive.GetStream(filenames.original))
339-
files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false, parameters.PreferHardLinks), filenames.shortened));
339+
files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false, parameters.PreferHardLinks, parameters.PreferCopyOnWrite), filenames.shortened));
340340
}
341341
}
342342

osu.Game/Database/RealmFileStore.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public RealmFileStore(RealmAccess realm, Storage storage)
4141
/// <param name="realm">The realm instance to add to. Should already be in a transaction.</param>
4242
/// <param name="addToRealm">Whether the <see cref="RealmFile"/> should immediately be added to the underlying realm. If <c>false</c> is provided here, the instance must be manually added.</param>
4343
/// <param name="preferHardLinks">Whether this import should use hard links rather than file copy operations if available.</param>
44-
public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool preferHardLinks = false)
44+
public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool preferHardLinks = false, bool preferCopyOnWrite = false)
4545
{
4646
string hash = data.ComputeSHA2Hash();
4747

@@ -50,20 +50,24 @@ public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool pref
5050
var file = existing ?? new RealmFile { Hash = hash };
5151

5252
if (!checkFileExistsAndMatchesHash(file))
53-
copyToStore(file, data, preferHardLinks);
53+
copyToStore(file, data, preferHardLinks, preferCopyOnWrite);
5454

5555
if (addToRealm && !file.IsManaged)
5656
realm.Add(file);
5757

5858
return file;
5959
}
6060

61-
private void copyToStore(RealmFile file, Stream data, bool preferHardLinks)
61+
private void copyToStore(RealmFile file, Stream data, bool preferHardLinks, bool preferCopyOnWrite)
6262
{
63-
if (data is FileStream fs && preferHardLinks)
63+
if (data is FileStream fs)
6464
{
65+
// Prefer CoW over hard link because it provides better isolation.
66+
if (preferCopyOnWrite && HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name))
67+
return;
68+
6569
// attempt to do a fast hard link rather than copy.
66-
if (HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name))
70+
if (preferHardLinks && HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name))
6771
return;
6872
}
6973

osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs

+12-3
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,19 @@ private void updateStablePath()
122122
stableLocatorTextBox.Current.Value = storage.GetFullPath(string.Empty);
123123
importButton.Enabled.Value = true;
124124

125-
bool available = legacyImportManager.CheckSongsFolderHardLinkAvailability();
126-
Logger.Log($"Hard link support for beatmaps is {available}");
125+
bool cowAvailable = legacyImportManager.CheckSongsFolderCoWAvailability();
126+
Logger.Log($"CoW support for beatmaps is {cowAvailable}");
127127

128-
if (available)
128+
bool hardLinkAvailable = legacyImportManager.CheckSongsFolderHardLinkAvailability();
129+
Logger.Log($"Hard link support for beatmaps is {hardLinkAvailable}");
130+
131+
if (cowAvailable)
132+
{
133+
copyInformation.Text = FirstRunOverlayImportFromStableScreenStrings.DataMigrationNoExtraSpaceWithCoW;
134+
copyInformation.AddText(@" "); // just to ensure correct spacing
135+
copyInformation.AddLink(FirstRunOverlayImportFromStableScreenStrings.LearnMoreAboutCoW, LinkAction.OpenWiki, @"Client/Release_stream/Lazer/File_storage#via-copy-on-write");
136+
}
137+
else if (hardLinkAvailable)
129138
{
130139
copyInformation.Text = FirstRunOverlayImportFromStableScreenStrings.DataMigrationNoExtraSpace;
131140
copyInformation.AddText(@" "); // just to ensure correct spacing

0 commit comments

Comments
 (0)