Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
3a5cf14d
Commit
3a5cf14d
authored
Nov 09, 2020
by
Vladislav Vaintroub
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-24175 Windows - fix detection of SSD
parent
4e24b318
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
143 additions
and
99 deletions
+143
-99
storage/innobase/os/os0file.cc
storage/innobase/os/os0file.cc
+143
-99
No files found.
storage/innobase/os/os0file.cc
View file @
3a5cf14d
...
...
@@ -7556,72 +7556,152 @@ os_file_set_umask(ulint umask)
}
#ifdef _WIN32
static
int
win32_get_block_size
(
HANDLE
volume_handle
,
const
char
*
volume_name
)
{
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
disk_alignment
;
STORAGE_PROPERTY_QUERY
storage_query
;
DWORD
tmp
;
memset
(
&
storage_query
,
0
,
sizeof
(
storage_query
));
storage_query
.
PropertyId
=
StorageAccessAlignmentProperty
;
storage_query
.
QueryType
=
PropertyStandardQuery
;
if
(
os_win32_device_io_control
(
volume_handle
,
IOCTL_STORAGE_QUERY_PROPERTY
,
&
storage_query
,
sizeof
storage_query
,
&
disk_alignment
,
sizeof
disk_alignment
,
&
tmp
)
&&
tmp
==
sizeof
disk_alignment
)
{
return
disk_alignment
.
BytesPerPhysicalSector
;
}
switch
(
GetLastError
())
{
case
ERROR_INVALID_FUNCTION
:
case
ERROR_NOT_SUPPORTED
:
break
;
default:
os_file_handle_error_no_exit
(
volume_name
,
"DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY / StorageAccessAlignmentProperty)"
,
FALSE
);
}
return
512
;
/* Checks whether physical drive is on SSD.*/
static
bool
is_drive_on_ssd
(
DWORD
nr
)
{
char
physical_drive_path
[
32
];
snprintf
(
physical_drive_path
,
sizeof
(
physical_drive_path
),
"
\\\\
.
\\
PhysicalDrive%lu"
,
nr
);
HANDLE
h
=
CreateFile
(
physical_drive_path
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
nullptr
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
nullptr
);
if
(
h
==
INVALID_HANDLE_VALUE
)
return
false
;
DEVICE_SEEK_PENALTY_DESCRIPTOR
seek_penalty
;
STORAGE_PROPERTY_QUERY
storage_query
{};
storage_query
.
PropertyId
=
StorageDeviceSeekPenaltyProperty
;
storage_query
.
QueryType
=
PropertyStandardQuery
;
bool
on_ssd
=
false
;
DWORD
bytes_written
;
if
(
DeviceIoControl
(
h
,
IOCTL_STORAGE_QUERY_PROPERTY
,
&
storage_query
,
sizeof
storage_query
,
&
seek_penalty
,
sizeof
seek_penalty
,
&
bytes_written
,
nullptr
))
{
on_ssd
=
seek_penalty
.
IncursSeekPenalty
;
}
else
{
on_ssd
=
false
;
}
CloseHandle
(
h
);
return
on_ssd
;
}
static
bool
win32_is_ssd
(
HANDLE
volume_handle
)
/*
Checks whether volume is on SSD, by checking all physical drives
in that volume.
*/
static
bool
is_volume_on_ssd
(
const
char
*
volume_mount_point
)
{
DWORD
tmp
;
DEVICE_SEEK_PENALTY_DESCRIPTOR
seek_penalty
;
STORAGE_PROPERTY_QUERY
storage_query
;
memset
(
&
storage_query
,
0
,
sizeof
(
storage_query
));
storage_query
.
PropertyId
=
StorageDeviceSeekPenaltyProperty
;
storage_query
.
QueryType
=
PropertyStandardQuery
;
if
(
os_win32_device_io_control
(
volume_handle
,
IOCTL_STORAGE_QUERY_PROPERTY
,
&
storage_query
,
sizeof
storage_query
,
&
seek_penalty
,
sizeof
seek_penalty
,
&
tmp
)
&&
tmp
==
sizeof
(
seek_penalty
)){
return
!
seek_penalty
.
IncursSeekPenalty
;
char
volume_name
[
MAX_PATH
];
if
(
!
GetVolumeNameForVolumeMountPoint
(
volume_mount_point
,
volume_name
,
array_elements
(
volume_name
)))
{
/* This can fail, e.g if file is on network share */
return
false
;
}
DEVICE_TRIM_DESCRIPTOR
trim
;
storage_query
.
PropertyId
=
StorageDeviceTrimProperty
;
if
(
os_win32_device_io_control
(
volume_handle
,
IOCTL_STORAGE_QUERY_PROPERTY
,
&
storage_query
,
sizeof
storage_query
,
&
trim
,
sizeof
trim
,
&
tmp
)
&&
tmp
==
sizeof
trim
)
{
return
trim
.
TrimEnabled
;
/* Chomp last backslash, this is needed to open volume.*/
size_t
length
=
strlen
(
volume_name
);
if
(
length
&&
volume_name
[
length
-
1
]
==
'\\'
)
volume_name
[
length
-
1
]
=
0
;
/* Open volume handle */
HANDLE
volume_handle
=
CreateFile
(
volume_name
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
nullptr
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
nullptr
);
if
(
volume_handle
==
INVALID_HANDLE_VALUE
)
return
false
;
/*
Enumerate all volume extends, check whether all of them are on SSD
*/
/* Anticipate common case where there is only one extent.*/
VOLUME_DISK_EXTENTS
single_extent
;
/* But also have a place to manage allocated data.*/
std
::
unique_ptr
<
BYTE
[]
>
lifetime
;
DWORD
bytes_written
;
VOLUME_DISK_EXTENTS
*
extents
=
nullptr
;
if
(
DeviceIoControl
(
volume_handle
,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
nullptr
,
0
,
&
single_extent
,
sizeof
(
single_extent
),
&
bytes_written
,
nullptr
))
{
/* Worked on the first try. Use the preallocated buffer.*/
extents
=
&
single_extent
;
}
else
{
VOLUME_DISK_EXTENTS
*
last_query
=
&
single_extent
;
while
(
GetLastError
()
==
ERROR_MORE_DATA
)
{
DWORD
extentCount
=
last_query
->
NumberOfDiskExtents
;
DWORD
allocatedSize
=
FIELD_OFFSET
(
VOLUME_DISK_EXTENTS
,
Extents
[
extentCount
]);
lifetime
.
reset
(
new
BYTE
[
allocatedSize
]);
last_query
=
(
VOLUME_DISK_EXTENTS
*
)
lifetime
.
get
();
if
(
DeviceIoControl
(
volume_handle
,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
nullptr
,
0
,
last_query
,
allocatedSize
,
&
bytes_written
,
nullptr
))
{
extents
=
last_query
;
break
;
}
}
}
return
false
;
CloseHandle
(
volume_handle
);
if
(
!
extents
)
return
false
;
for
(
DWORD
i
=
0
;
i
<
extents
->
NumberOfDiskExtents
;
i
++
)
if
(
!
is_drive_on_ssd
(
extents
->
Extents
[
i
].
DiskNumber
))
return
false
;
return
true
;
}
#include <unordered_map>
static
bool
is_file_on_ssd
(
char
*
file_path
)
{
/* Cache of volume_path => volume_info, protected by rwlock.*/
static
std
::
unordered_map
<
std
::
string
,
bool
>
cache
;
static
SRWLOCK
lock
=
SRWLOCK_INIT
;
/* Preset result, in case something fails, e.g we're on network drive.*/
char
volume_path
[
MAX_PATH
];
if
(
!
GetVolumePathName
(
file_path
,
volume_path
,
array_elements
(
volume_path
)))
return
false
;
/* Try cached volume info first.*/
std
::
string
volume_path_str
(
volume_path
);
bool
found
;
bool
result
;
AcquireSRWLockShared
(
&
lock
);
auto
e
=
cache
.
find
(
volume_path_str
);
if
((
found
=
e
!=
cache
.
end
()))
result
=
e
->
second
;
ReleaseSRWLockShared
(
&
lock
);
if
(
found
)
return
result
;
result
=
is_volume_on_ssd
(
volume_path
);
/* Update cache */
AcquireSRWLockExclusive
(
&
lock
);
cache
[
volume_path_str
]
=
result
;
ReleaseSRWLockExclusive
(
&
lock
);
return
result
;
}
#endif
/** Determine some file metadata when creating or reading the file.
...
...
@@ -7658,48 +7738,12 @@ void fil_node_t::find_metadata(os_file_t file
space
->
atomic_write_supported
=
space
->
purpose
==
FIL_TYPE_TEMPORARY
||
space
->
purpose
==
FIL_TYPE_IMPORT
;
#ifdef _WIN32
block_size
=
512
;
on_ssd
=
false
;
// Open volume for this file, find out it "physical bytes per sector"
char
volume
[
MAX_PATH
+
4
];
if
(
!
GetVolumePathName
(
name
,
volume
+
4
,
MAX_PATH
))
{
os_file_handle_error_no_exit
(
name
,
"GetVolumePathName()"
,
FALSE
);
return
;
}
// Special prefix required for volume names.
memcpy
(
volume
,
"
\\\\
.
\\
"
,
4
);
size_t
len
=
strlen
(
volume
);
if
(
volume
[
len
-
1
]
==
'\\'
)
{
// Trim trailing backslash from volume name.
volume
[
len
-
1
]
=
0
;
}
HANDLE
volume_handle
=
CreateFile
(
volume
,
FILE_READ_ATTRIBUTES
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
0
,
OPEN_EXISTING
,
0
,
0
);
if
(
volume_handle
!=
INVALID_HANDLE_VALUE
)
{
block_size
=
win32_get_block_size
(
volume_handle
,
volume
);
on_ssd
=
win32_is_ssd
(
volume_handle
);
CloseHandle
(
volume_handle
);
on_ssd
=
is_file_on_ssd
(
name
);
FILE_STORAGE_INFO
info
;
if
(
GetFileInformationByHandleEx
(
file
,
FileStorageInfo
,
&
info
,
sizeof
(
info
)))
{
block_size
=
info
.
PhysicalBytesPerSectorForAtomicity
;
}
else
{
/*
Report error, unless it is expected, e.g
missing permissions, or error when trying to
open volume for UNC share.
*/
if
(
GetLastError
()
!=
ERROR_ACCESS_DENIED
&&
GetDriveType
(
volume
)
==
DRIVE_FIXED
)
{
os_file_handle_error_no_exit
(
volume
,
"CreateFile()"
,
FALSE
);
}
}
/* Currently we support file block size up to 4KiB */
if
(
block_size
>
4096
)
{
block_size
=
4096
;
}
else
if
(
block_size
<
512
)
{
block_size
=
512
;
}
#else
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment