Windows 2008 R2 и Windows 7 Ultimate демонстрируют такое поведение ...
Итак, у меня есть структура каталогов, например ... YEAR \ MONTH \ file_x.ext, где YEAR восходит к 2007 году, а каждый каталог MONTH содержит от сотен до тысяч (максимум 2500) файлов.
У меня есть программа, которая случайным образом выбирает файл для работы, но работает только с одним каталогом. Итак, я создал новый каталог и создал там жесткую ссылку для каждого файла в моей структуре (40 000+).
Все работает отлично, за исключением того, что теперь Explorer сообщает, что на диске осталось всего несколько МБ, и отказывается разрешать запись дополнительных данных на диск.
Поскольку это жесткие ссылки, я полагаю, что на диске должно оставаться около 40 ГБ.
Есть мысли о том, как это решить? (например, позволить приложению с одним каталогом работать правильно, сохраняя при этом организованную структуру и не увеличивая вдвое использование дискового пространства)
Вы уверены, что ваш диск заполняется жесткими ссылками? Я проверил это здесь, но не смог воспроизвести.
Теоретически CreateHardLink
должен быть эквивалентен mklink /h
команда; но на всякий случай я создал следующий скрипт AutoIt, чтобы убедиться, что использую тот же вызов функции, что и вы. (Мне было лень писать что-то на VC ++…)
#include <WinAPI.au3>
#include <WinAPIError.au3>
Local $kernel = DllOpen("kernel32.dll")
If $CmdLine[0] <> 2 Then
ConsoleWriteError("usage: CreateHardLink Link Target" & @CRLF)
Exit
EndIf
Local $result = DllCall($kernel, "BOOL", "CreateHardLink", "str", $CmdLine[1], "str", $CmdLine[2], "LONG_PTR", 0)
If $result[0] == 0 Then
ConsoleWriteError("Windows error " & _WinAPI_GetLastError() & ": " & _WinAPI_GetLastErrorMessage())
Else
ConsoleWrite("Hardlink created for " & $CmdLine[1] & " <<===>> " & $CmdLine[2] & @CRLF)
EndIf
Затем я создал в VMware отдельный диск объемом 2,0 ГБ и подключил его, чтобы тесты не находились на том же диске, что и файл подкачки и т. Д.
Я поместил один файл в корневой каталог и создал дополнительные 1023 ссылки на него (максимальное поддерживаемое количество) с помощью следующего командного файла:
@echo off
dir | find "(s)"
for /l %%i in (0,1,1023) do C:CreateHardLink.exe %%i %1
dir | find "(s)"
Использование диска до:
1 File(s) 3,212,078 bytes
0 Dir(s) 2,089,775,104 bytes free
Использование диска после:
1024 File(s) 3,289,167,872 bytes
0 Dir(s) 2,089,222,144 bytes free
И Explorer говорит, что из 1,99 свободно 1,94 ГБ.
Я скопировал около 1,08 ГБ данных (в файлах разного размера и расположенных в разных каталогах) в раздел и создал по одной жесткой ссылке для каждого найденного файла в каталог с именем HardLinks. Этот командный файл:
@echo off
setlocal
setlocal enabledelayedexpansion
dir /s | find "(s)"
set /a i=0
for /r %%a in (*) do (
C:CreateHardLink "HardLinks\!i!_%%~nxa" "%%~a"
set /a i=!i!+1
)
dir /s | find "(s)"
Использование диска до:
2034 File(s) 1,109,324,978 bytes
1998 Dir(s) 975,511,552 bytes free
Использование диска после:
4246 File(s) 2,490,368,854 bytes
1998 Dir(s) 973,955,072 bytes free
Это было бы физически невозможно без жестких ссылок, поскольку мой диск занимает всего 2,0 ГБ.
Дисковое пространство действительно уменьшилось ровно на 1520 КБ, что составляет ~ 1,46 КБ на каждую созданную жесткую ссылку. В таком случае, чтобы использовать 40 ГБ только метаданных для жестких ссылок, вам потребуется около 29 миллионов из них. (Я полагаю, что к этому моменту вы столкнетесь с другим ограничением, например, количеством файловых записей в одном каталоге. ;-)
Приносим извинения за то, что это не лучший «ответ» сам по себе; но, надеюсь, это даст вам некоторую уверенность в том, что жесткие ссылки не должны заполнять ваш диск. На вашем месте я бы создавал больше жестких ссылок меньшими партиями и измерял использование дискового пространства до и после. Также может быть полезно посмотреть, использует ли что-то еще на том же диске больше места, чем должно быть.
Я также не могу придумать для вас альтернативного решения; жесткие ссылки кажутся идеальными для этого случая, не так ли?