-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
is_hdd update for windows and linux #4278
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make commit message first line informative (like this PR's title for example).
Also, since you change the is_hdd code completely, I think it might be a good occasion to move this into a separate file as it's becoming a bit crowded here.
src/common/util.cpp
Outdated
@@ -74,6 +75,11 @@ using namespace epee; | |||
#include <boost/asio.hpp> | |||
#include <openssl/sha.h> | |||
|
|||
#ifdef WIN32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we had problems with WIN32 before, and _WIN32 was the "best" one to use.
src/common/util.cpp
Outdated
return false; | ||
} | ||
} | ||
uint16_t val = 0xdead; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably best to make it a unsigned short if using %hu below.
src/common/util.cpp
Outdated
std::string sys_path = "/sys/block/" + device + "/queue/rotational"; | ||
FILE *f = fopen(sys_path.c_str(), "r"); | ||
if (!f) | ||
bool win_device_has_seek_penalny(const char *pv, bool &result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
penalty
src/common/util.cpp
Outdated
); | ||
if(success and r_size == sizeof(r)) | ||
{ | ||
result = r.IncursSeekPenalty; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That path seems to leak h.
src/common/util.cpp
Outdated
return false; | ||
} | ||
bool a_result = 0; | ||
bool a_success = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
false
src/common/util.cpp
Outdated
#elif defined(__GLIBC__) | ||
return is_hdd_sysfs(path, result); | ||
#else | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
false
src/common/util.cpp
Outdated
} | ||
else | ||
{ | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
false
tests/unit_tests/CMakeLists.txt
Outdated
@@ -72,6 +72,7 @@ set(unit_tests_sources | |||
ringct.cpp | |||
output_selection.cpp | |||
vercmp.cpp | |||
test_a.cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to something sane
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A first pass at a review.
src/common/util.cpp
Outdated
@@ -733,63 +739,225 @@ std::string get_nix_version_display_string() | |||
#endif | |||
} | |||
|
|||
bool is_hdd(const char *path) | |||
#if defined(__GLIBC__) | |||
bool is_hdd_sysfs(const char *file_path, bool &result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somewhat quirky, but boost::optional<bool>
might be better suited for this. There is also boost::tribool
, but usage of that can be tricky since the library author unfortunately decided to overload operator&&
and operator||
which ruins default semantics.
src/common/util.cpp
Outdated
return false; | ||
} | ||
std::string attr_path = prefix + "/queue/rotational"; | ||
FILE *f = fopen(attr_path.c_str(), "r"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not std::ifstream
here? Streams were already in use a few lines above anyway. The primary advantage is that you don't have to worry about the unsigned short
/ %hu
stuff in scanf
.
src/common/util.cpp
Outdated
if(h != INVALID_HANDLE_VALUE) | ||
{ | ||
char p[MAX_PATH + 1]; | ||
DWORD r_size = GetFinalPathNameByHandleA( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this throws (it shouldn't really), then CloseHandle
is never called. There is a struct close_handle
in this cpp file already that can be used as a helper:
std::unique_ptr<void, close_handle> h{
CreateFile(...)
};
@@ -79,6 +79,7 @@ target_link_libraries(cncrypto | |||
epee | |||
${Boost_SYSTEM_LIBRARY} | |||
PRIVATE | |||
sodium |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this meant for another patch?
src/common/util.cpp
Outdated
std::string dev_path = std::string("/dev/block/") + de->d_name; | ||
char resolved[PATH_MAX]; | ||
if (realpath(dev_path.c_str(), resolved) && !strncmp(resolved, "/dev/", 5)) | ||
std::regex r("^\\\\Device\\\\([^\\\\]+).*$"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, let me walk through this logic, because this should be easy for a boost::spirit
usage. It will require more compile-time, but will be much faster since the expression expands into a specific parser at compile-time, instead of a generic NFA runtime implementation that std::regex
is likely using.
It looks like you want to grab all characters after \\Device\\
until EOF or next \\
. Is that correct? If so the boost::spirit
equivalent is:
#include <boost/range/iterator_range.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_difference.hpp>
#include <boost/spirit/include/qi_kleene.hpp>
#include <boost/spirit/include/qi_lit.hpp>
#include <boost/spirit/include/qi_sequence.hpp>
namespace qi = boost::spirit::qi
boost::iterator_range<const char> match{};
if (qi::parse(p, p + strlen(p), (qi::lit("\\Device\\") >> *(qi::char_ - "\\")), match))
{
...
}
This simply says match \\Device\\
then match zero or more char_
acters unless the next two characters are \\
. Those char_
acters are then stored in the boost::iterator_range<const char*>
. The entire expression doesn't allocate any memory, even when a match is found.
... thoughts ?
src/common/util.cpp
Outdated
HANDLE h = INVALID_HANDLE_VALUE; | ||
std::string lv_path = "\\\\?\\"; | ||
lv_path += lv; | ||
h = CreateFile( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another std::unique_ptr<void, close_handle>
case.
src/common/util.cpp
Outdated
{ | ||
for(uint32_t i = 0; i < r.NumberOfDiskExtents; ++i) | ||
{ | ||
std::ostringstream ss; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pop this before the loop, then do a .str(std::string{})
every iteration. Some easy performance gains (constructing an std::ostream
requires a global synchronization on the current std::locale
object). There might be a better way to reset the state of this type if the manual was inspecting further ...
src/common/util.cpp
Outdated
{ | ||
bool q_result; | ||
bool q_success = win_device_has_seek_penalny(v.c_str(), q_result); | ||
a_success |= q_success; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is damn near obfuscation. Some early return
s are possible. If boost::optional<bool>
suggestion is used:
for (auto const& v : pvs)
{
const auto success = win_device_has_seek_penalty(v.c_str());
if (!success)
return boost::none;
if (success.value())
return true;
}
return false;
Should this be inverted though? If any of the backing physical volumes isn't a local HDD, then LMDB may have a bad time.
src/common/util.cpp
Outdated
HANDLE h = INVALID_HANDLE_VALUE; | ||
std::string pv_path = "\\\\?\\"; | ||
pv_path += pv; | ||
h = CreateFile( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another std::unique_ptr<void, close_handle>
.
src/common/util.cpp
Outdated
} | ||
bool a_result = 0; | ||
bool a_success = 0; | ||
for(auto &v: pvs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto const& v
I don't have write access to push updates. |
If you are the author, then you can open a new bug for it. If you are not, then I suggest you ping the author in #monero-dev (nick in the first post) about it. I PRed because the author did not want to make a github account. |
The final aim is to upload the next commit with all fixes requested in comments. |
1. Move is_hdd() declaration from util.h into is_hdd.h include "common/is_hdd.h" into *.cpp that use is_hdd() 2. Move the following functions from util.cpp into is_hdd.cpp is_hdd_sysfs() fp2lv() lv2pv() win_device_has_seek_penalty() is_hdd_win_ioctl() is_hdd() 3. Fix the following things use _WIN32 instead of WIN32 use unsigned short instead of uint16_t use penalty instead of penalny add CloseHandle(h) in all conditional branches to avoid resource leaking use either 0/1 or true/false to maintain consistency rename tests/unit_tests/test_a.cpp
+duplicate |
Add is_hdd_sysfs(), is_hdd_win_ioctl(), fl2lv(), lv2pv(),
win_device_has_seek_penalny()
Add tests test_a.is_hdd*
Modify is_hdd()
Added bcrypt, sodium
Contributed by crCr62U0_ who does not have nor want a github account.