Skip to content
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

Closed

Conversation

moneromooo-monero
Copy link
Collaborator

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.

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
Copy link
Collaborator Author

@moneromooo-monero moneromooo-monero left a 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.

@@ -74,6 +75,11 @@ using namespace epee;
#include <boost/asio.hpp>
#include <openssl/sha.h>

#ifdef WIN32
Copy link
Collaborator Author

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.

return false;
}
}
uint16_t val = 0xdead;
Copy link
Collaborator Author

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.

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)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

penalty

);
if(success and r_size == sizeof(r))
{
result = r.IncursSeekPenalty;
Copy link
Collaborator Author

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.

return false;
}
bool a_result = 0;
bool a_success = 0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false

#elif defined(__GLIBC__)
return is_hdd_sysfs(path, result);
#else
return 0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false

}
else
{
return 0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false

@@ -72,6 +72,7 @@ set(unit_tests_sources
ringct.cpp
output_selection.cpp
vercmp.cpp
test_a.cpp
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to something sane

Copy link
Contributor

@vtnerd vtnerd left a 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.

@@ -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)
Copy link
Contributor

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.

return false;
}
std::string attr_path = prefix + "/queue/rotational";
FILE *f = fopen(attr_path.c_str(), "r");
Copy link
Contributor

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.

if(h != INVALID_HANDLE_VALUE)
{
char p[MAX_PATH + 1];
DWORD r_size = GetFinalPathNameByHandleA(
Copy link
Contributor

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
Copy link
Contributor

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?

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\\\\([^\\\\]+).*$");
Copy link
Contributor

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 ?

HANDLE h = INVALID_HANDLE_VALUE;
std::string lv_path = "\\\\?\\";
lv_path += lv;
h = CreateFile(
Copy link
Contributor

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.

{
for(uint32_t i = 0; i < r.NumberOfDiskExtents; ++i)
{
std::ostringstream ss;
Copy link
Contributor

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 ...

{
bool q_result;
bool q_success = win_device_has_seek_penalny(v.c_str(), q_result);
a_success |= q_success;
Copy link
Contributor

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 returns 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.

HANDLE h = INVALID_HANDLE_VALUE;
std::string pv_path = "\\\\?\\";
pv_path += pv;
h = CreateFile(
Copy link
Contributor

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>.

}
bool a_result = 0;
bool a_success = 0;
for(auto &v: pvs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto const& v

@p8p
Copy link
Contributor

p8p commented Aug 20, 2018

I don't have write access to push updates.

@moneromooo-monero
Copy link
Collaborator Author

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.

@p8p
Copy link
Contributor

p8p commented Aug 20, 2018

The final aim is to upload the next commit with all fixes requested in comments.
It was possible to ask moneromoo-monero to create pull request with the first commit.
What way should be used for the next commit?
It seems that p8p account (newly created github) has been flagged therefore I'm forbidden to use all github features.
I'd like to send updates without using github account because of this useless censorship.
The way to use someone in #monero-dev as a proxy to upload updates is too slow and not efficient.

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
@moneromooo-monero
Copy link
Collaborator Author

+duplicate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants