remote fixes

This commit is contained in:
Scott E. Graves 2024-11-08 09:40:56 -06:00
parent af339e6086
commit 2d74fb30de
6 changed files with 243 additions and 161 deletions

View File

@ -33,25 +33,32 @@ protected:
virtual ~remote_open_file_table() = default;
protected:
struct compat_open_info {
std::size_t count{0U};
struct compat_open_info final {
std::string client_id;
std::vector<remote::file_handle> handles;
std::string path;
};
struct open_info {
std::size_t count{0U};
struct open_info final {
std::string client_id;
PVOID directory_buffer{nullptr};
std::vector<native_handle> handles;
std::string path;
};
private:
std::unordered_map<remote::file_handle, compat_open_info> compat_lookup_;
std::recursive_mutex compat_mutex_;
std::unordered_map<std::string, std::unique_ptr<compat_open_info>>
compat_file_lookup_;
std::unordered_map<remote::file_handle, std::string> compat_handle_lookup_;
private:
std::unordered_map<std::string, std::vector<std::uint64_t>> directory_lookup_;
std::recursive_mutex directory_mutex_;
std::unordered_map<native_handle, open_info> file_lookup_;
private:
std::unordered_map<std::string, std::unique_ptr<open_info>> file_lookup_;
std::unordered_map<native_handle, std::string> handle_lookup_;
private:
mutable std::recursive_mutex file_mutex_;
protected:
@ -64,11 +71,11 @@ protected:
PVOID *&buffer) -> bool;
#endif // _WIN32
[[nodiscard]] auto
get_open_file_path(const native_handle &handle) -> std::string;
[[nodiscard]] auto get_open_file_path(const native_handle &handle)
-> std::string;
[[nodiscard]] auto get_open_info(const native_handle &handle,
open_info &oi) -> bool;
[[nodiscard]] auto get_open_info(const native_handle &handle, open_info &oi)
-> bool;
[[nodiscard]] auto has_open_directory(const std::string &client_id,
std::uint64_t handle) -> bool;
@ -77,20 +84,21 @@ protected:
int error_return) -> int;
template <typename error_type>
[[nodiscard]] auto
has_open_info(const native_handle &handle,
const error_type &error_return) -> error_type {
[[nodiscard]] auto has_open_info(const native_handle &handle,
const error_type &error_return)
-> error_type {
recur_mutex_lock file_lock(file_mutex_);
return ((file_lookup_.find(handle) == file_lookup_.end()) ? error_return
: 0);
return handle_lookup_.contains(handle) ? 0 : error_return;
}
void remove_all(const std::string &file_path);
void remove_and_close_all(const native_handle &handle);
void remove_compat_open_info(const remote::file_handle &handle);
auto remove_directory(const std::string &client_id,
std::uint64_t handle) -> bool;
auto remove_directory(const std::string &client_id, std::uint64_t handle)
-> bool;
void remove_open_info(const native_handle &handle);
@ -102,11 +110,11 @@ protected:
void set_compat_open_info(const remote::file_handle &handle,
const std::string &file_path);
void set_open_info(const native_handle &handle, open_info oi);
void set_open_info(const native_handle &handle, open_info op_info);
public:
[[nodiscard]] auto
get_open_file_count(const std::string &file_path) const -> std::size_t;
[[nodiscard]] auto get_open_file_count(const std::string &file_path) const
-> std::size_t;
};
} // namespace repertory

View File

@ -137,12 +137,12 @@ public:
if (ret == STATUS_SUCCESS) {
#if defined(_WIN32)
this->set_client_id(file_desc, client_id);
#else
#else // !defined(_WIN32)
this->set_client_id(
static_cast<native_handle>(
reinterpret_cast<std::uintptr_t>(file_desc)),
client_id);
#endif
#endif // defined(_WIN32)
response.encode(file_desc);
response.encode(file_info);
response.encode(normalized_name);
@ -277,12 +277,12 @@ public:
if (ret == STATUS_SUCCESS) {
#if defined(_WIN32)
this->set_client_id(file_desc, client_id);
#else
#else // !defined(_WIN32)
this->set_client_id(
static_cast<native_handle>(
reinterpret_cast<std::uintptr_t>(file_desc)),
client_id);
#endif
#endif // defined(_WIN32)
response.encode(file_desc);
response.encode(file_info);
response.encode(normalized_name);
@ -585,9 +585,9 @@ public:
0) {
#if defined(_WIN32)
this->set_compat_client_id(handle, client_id);
#else
#else // !defined(_WIN32)
this->set_client_id(static_cast<native_handle>(handle), client_id);
#endif
#endif // defined(_WIN32)
response.encode(handle);
}
return ret;
@ -841,9 +841,9 @@ public:
if ((ret = this->fuse_open(path.c_str(), flags, handle)) >= 0) {
#if defined(_WIN32)
this->set_compat_client_id(handle, client_id);
#else
#else // !defined(_WIN32)
this->set_client_id(static_cast<native_handle>(handle), client_id);
#endif
#endif // defined(_WIN32)
response.encode(handle);
}
return ret;

View File

@ -24,12 +24,13 @@
#include "events/event_system.hpp"
#include "events/events.hpp"
#include "utils/collection.hpp"
#include "utils/config.hpp"
#include "utils/utils.hpp"
namespace repertory {
void remote_open_file_table::add_directory(const std::string &client_id,
std::uint64_t handle) {
recur_mutex_lock directory_lock(directory_mutex_);
recur_mutex_lock lock(file_mutex_);
auto &list = directory_lookup_[client_id];
if (utils::collection::excludes(list, handle)) {
directory_lookup_[client_id].emplace_back(handle);
@ -37,14 +38,32 @@ void remote_open_file_table::add_directory(const std::string &client_id,
}
void remote_open_file_table::close_all(const std::string &client_id) {
std::vector<remote::file_handle> compat_handles;
unique_recur_mutex_lock compat_lock(compat_mutex_);
for (auto &&kv : compat_lookup_) {
if (kv.second.client_id == client_id) {
compat_handles.emplace_back(kv.first);
unique_recur_mutex_lock lock(file_mutex_);
auto compat_handles =
std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(),
std::vector<remote::file_handle>(),
[&client_id](auto &&list, auto &&value) {
auto &&op_info = value.second;
if (op_info->client_id == client_id) {
list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
return list;
});
auto handles = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
[&client_id](auto &&list, auto &&value) {
auto &&op_info = value.second;
if (op_info->client_id == client_id) {
list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
compat_lock.unlock();
return list;
});
lock.unlock();
for (auto &&handle : compat_handles) {
#if defined(_WIN32)
@ -55,32 +74,23 @@ void remote_open_file_table::close_all(const std::string &client_id) {
remove_compat_open_info(handle);
}
std::vector<native_handle> handles;
unique_recur_mutex_lock file_lock(file_mutex_);
for (auto &&kv : file_lookup_) {
if (kv.second.client_id == client_id) {
handles.emplace_back(kv.first);
}
}
file_lock.unlock();
for (auto &&handle : handles) {
#if defined(_WIN32)
::CloseHandle(handle);
#else
#else // !defined(_WIN32)
close(handle);
#endif
#endif // defined(_WIN32)
remove_open_info(handle);
}
std::vector<std::uint64_t> dirs;
unique_recur_mutex_lock directory_lock(directory_mutex_);
lock.lock();
for (auto &&kv : directory_lookup_) {
if (kv.first == client_id) {
dirs.insert(dirs.end(), kv.second.begin(), kv.second.end());
}
}
directory_lock.unlock();
lock.unlock();
for (auto &&dir : dirs) {
remove_directory(client_id, dir);
@ -90,123 +100,123 @@ void remote_open_file_table::close_all(const std::string &client_id) {
#if defined(_WIN32)
auto remote_open_file_table::get_directory_buffer(const native_handle &handle,
PVOID *&buffer) -> bool {
recur_mutex_lock file_lock(file_mutex_);
if (file_lookup_.find(handle) != file_lookup_.end()) {
buffer = &file_lookup_[handle].directory_buffer;
return true;
}
recur_mutex_lock lock(file_mutex_);
if (not handle_lookup_.contains(handle)) {
return false;
}
buffer = &file_lookup_.at(handle_lookup_.at(handle))->directory_buffer;
return true;
}
#endif
#endif // defined(_WIN32)
auto remote_open_file_table::get_open_file_count(
const std::string &file_path) const -> std::size_t {
unique_recur_mutex_lock file_lock(file_mutex_);
const auto count = std::accumulate(
file_lookup_.cbegin(), file_lookup_.cend(), std::size_t(0U),
[&file_path](std::size_t total, const auto &kv) -> std::size_t {
if (kv.second.path == file_path) {
return ++total;
}
return total;
});
return std::accumulate(
compat_lookup_.cbegin(), compat_lookup_.cend(), count,
[&file_path](std::size_t total, const auto &kv) -> std::size_t {
if (kv.second.path == file_path) {
return ++total;
}
return total;
});
recur_mutex_lock lock(file_mutex_);
return (file_lookup_.contains(file_path)
? file_lookup_.at(file_path)->handles.size()
: 0ULL) +
(compat_file_lookup_.contains(file_path)
? compat_file_lookup_.at(file_path)->handles.size()
: 0ULL);
}
auto remote_open_file_table::get_open_info(const native_handle &handle,
open_info &oi) -> bool {
recur_mutex_lock file_lock(file_mutex_);
if (file_lookup_.find(handle) != file_lookup_.end()) {
oi = file_lookup_[handle];
return true;
}
recur_mutex_lock lock(file_mutex_);
if (not handle_lookup_.contains(handle)) {
return false;
}
oi = *file_lookup_.at(handle_lookup_.at(handle)).get();
return true;
}
auto remote_open_file_table::get_open_file_path(const native_handle &handle)
-> std::string {
recur_mutex_lock file_lock(file_mutex_);
if (file_lookup_.find(handle) != file_lookup_.end()) {
return file_lookup_[handle].path;
recur_mutex_lock lock(file_mutex_);
if (not handle_lookup_.contains(handle)) {
return "";
}
return "";
return file_lookup_.at(handle_lookup_.at(handle))->path;
}
auto remote_open_file_table::has_open_directory(const std::string &client_id,
std::uint64_t handle) -> bool {
recur_mutex_lock directory_lock(directory_mutex_);
auto &list = directory_lookup_[client_id];
return (utils::collection::includes(list, handle));
recur_mutex_lock lock(file_mutex_);
return (utils::collection::includes(directory_lookup_[client_id], handle));
}
auto remote_open_file_table::has_compat_open_info(
const remote::file_handle &handle, int error_return) -> int {
recur_mutex_lock compat_lock(compat_mutex_);
const auto res =
((compat_lookup_.find(handle) == compat_lookup_.end()) ? -1 : 0);
recur_mutex_lock compat_lock(file_mutex_);
auto res = compat_handle_lookup_.contains(handle) ? 0 : -1;
if (res == -1) {
errno = error_return;
}
return res;
}
void remote_open_file_table::remove_all(const std::string &file_path) {
unique_recur_mutex_lock file_lock(file_mutex_);
const auto open_list = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
[&file_path](std::vector<native_handle> v,
const auto &kv) -> std::vector<native_handle> {
if (kv.second.path == file_path) {
v.emplace_back(kv.first);
}
return v;
});
const auto compat_open_list = std::accumulate(
compat_lookup_.begin(), compat_lookup_.end(),
unique_recur_mutex_lock lock(file_mutex_);
auto compat_open_list = std::accumulate(
compat_file_lookup_.begin(), compat_file_lookup_.end(),
std::vector<remote::file_handle>(),
[&file_path](std::vector<remote::file_handle> v,
const auto &kv) -> std::vector<remote::file_handle> {
if (kv.second.path == file_path) {
v.emplace_back(kv.first);
[&file_path](auto &&list, auto &&kv) -> std::vector<remote::file_handle> {
if (kv.first == file_path) {
auto *op_info = kv.second.get();
list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
return v;
return list;
});
file_lock.unlock();
for (auto &&handle : open_list) {
remove_open_info(handle);
auto open_list = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
[&file_path](auto &&list, auto &&kv) -> std::vector<native_handle> {
if (kv.first == file_path) {
auto *op_info = kv.second.get();
list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
return list;
});
lock.unlock();
for (auto &&handle : compat_open_list) {
remove_compat_open_info(handle);
}
for (auto &&handle : open_list) {
remove_open_info(handle);
}
}
void remote_open_file_table::remove_compat_open_info(
const remote::file_handle &handle) {
recur_mutex_lock compat_lock(compat_mutex_);
if (compat_lookup_[handle].count > 0) {
compat_lookup_[handle].count--;
recur_mutex_lock compat_lock(file_mutex_);
if (not compat_handle_lookup_.contains(handle)) {
return;
}
if (not compat_lookup_[handle].count) {
compat_lookup_.erase(handle);
auto *op_info =
compat_file_lookup_.at(compat_handle_lookup_.at(handle)).get();
utils::collection::remove_element(op_info->handles, handle);
compat_handle_lookup_.erase(handle);
if (not op_info->handles.empty()) {
return;
}
auto path = op_info->path;
compat_file_lookup_.erase(path);
}
auto remote_open_file_table::remove_directory(const std::string &client_id,
std::uint64_t handle) -> bool {
recur_mutex_lock directory_lock(directory_mutex_);
recur_mutex_lock lock(file_mutex_);
auto &list = directory_lookup_[client_id];
if (utils::collection::includes(list, handle)) {
utils::collection::remove_element(list, handle);
@ -220,48 +230,93 @@ auto remote_open_file_table::remove_directory(const std::string &client_id,
}
void remote_open_file_table::remove_open_info(const native_handle &handle) {
recur_mutex_lock file_lock(file_mutex_);
if (file_lookup_[handle].count > 0) {
file_lookup_[handle].count--;
recur_mutex_lock lock(file_mutex_);
if (not handle_lookup_.contains(handle)) {
return;
}
if (not file_lookup_[handle].count) {
auto *op_info = file_lookup_.at(handle_lookup_.at(handle)).get();
utils::collection::remove_element(op_info->handles, handle);
handle_lookup_.erase(handle);
if (not op_info->handles.empty()) {
return;
}
#if defined(_WIN32)
if (file_lookup_[handle].directory_buffer) {
FspFileSystemDeleteDirectoryBuffer(
&file_lookup_[handle].directory_buffer);
if (op_info->directory_buffer) {
FspFileSystemDeleteDirectoryBuffer(&op_info->directory_buffer);
}
#endif
file_lookup_.erase(handle);
auto path = op_info->path;
file_lookup_.erase(path);
}
void remote_open_file_table::remove_and_close_all(const native_handle &handle) {
unique_recur_mutex_lock lock(file_mutex_);
if (not handle_lookup_.contains(handle)) {
return;
}
auto op_info = *file_lookup_.at(handle_lookup_.at(handle));
lock.unlock();
for (auto &&open_handle : op_info.handles) {
#if defined(_WIN32)
::CloseHandle(open_handle);
#else // !defined(_WIN32)
close(open_handle);
#endif // defined(_WIN32)
remove_open_info(open_handle);
}
}
void remote_open_file_table::set_compat_client_id(
const remote::file_handle &handle, const std::string &client_id) {
recur_mutex_lock compat_lock(compat_mutex_);
compat_lookup_[handle].client_id = client_id;
recur_mutex_lock compat_lock(file_mutex_);
compat_file_lookup_.at(compat_handle_lookup_.at(handle))->client_id =
client_id;
}
void remote_open_file_table::set_client_id(const native_handle &handle,
const std::string &client_id) {
recur_mutex_lock file_lock(file_mutex_);
file_lookup_[handle].client_id = client_id;
recur_mutex_lock lock(file_mutex_);
file_lookup_.at(handle_lookup_.at(handle))->client_id = client_id;
}
void remote_open_file_table::set_compat_open_info(
const remote::file_handle &handle, const std::string &file_path) {
recur_mutex_lock compat_lock(compat_mutex_);
if (compat_lookup_.find(handle) == compat_lookup_.end()) {
compat_lookup_[handle] = {0, "", file_path};
recur_mutex_lock compat_lock(file_mutex_);
if (compat_handle_lookup_.contains(handle)) {
return;
}
compat_lookup_[handle].count++;
if (not compat_file_lookup_.contains(file_path)) {
compat_file_lookup_[file_path] =
std::make_unique<compat_open_info>(compat_open_info{
"",
{},
file_path,
});
}
compat_handle_lookup_[handle] = file_path;
compat_file_lookup_.at(file_path)->handles.emplace_back(handle);
}
void remote_open_file_table::set_open_info(const native_handle &handle,
open_info oi) {
recur_mutex_lock file_lock(file_mutex_);
if (file_lookup_.find(handle) == file_lookup_.end()) {
file_lookup_[handle] = std::move(oi);
open_info op_info) {
recur_mutex_lock lock(file_mutex_);
if (handle_lookup_.contains(handle)) {
return;
}
file_lookup_[handle].count++;
if (not file_lookup_.contains(op_info.path)) {
file_lookup_[op_info.path] = std::make_unique<open_info>(op_info);
}
handle_lookup_[handle] = op_info.path;
file_lookup_.at(op_info.path)->handles.emplace_back(handle);
}
} // namespace repertory

View File

@ -160,10 +160,12 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
auto ret{
packet_client_.send(function_name, request, response, service_flags),
};
DECODE_OR_IGNORE(&response, was_closed);
if (was_closed != 0U) {
remove_all(file_path);
}
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret);
return ret;
}
@ -222,11 +224,16 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
DECODE_OR_IGNORE(&response, *file_info);
DECODE_OR_IGNORE(&response, normalized_name);
DECODE_OR_IGNORE(&response, exists);
if (ret == STATUS_SUCCESS) {
*file_desc = reinterpret_cast<PVOID>(handle);
set_open_info(
to_handle(*file_desc),
open_info{0, "", nullptr, utils::string::to_utf8(file_name)});
set_open_info(to_handle(*file_desc),
open_info{
"",
nullptr,
{},
utils::string::to_utf8(file_name),
});
#if defined(_WIN32)
if (exists) {
::SetLastError(ERROR_ALREADY_EXISTS);
@ -390,9 +397,13 @@ auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options,
if (ret == STATUS_SUCCESS) {
*file_desc = reinterpret_cast<PVOID>(handle);
set_open_info(
to_handle(*file_desc),
open_info{0, "", nullptr, utils::string::to_utf8(file_name)});
set_open_info(to_handle(*file_desc),
open_info{
"",
nullptr,
{},
utils::string::to_utf8(file_name),
});
}
}

View File

@ -945,12 +945,12 @@ auto remote_server::winfsp_cleanup(PVOID file_desc, PWSTR /*file_name*/,
auto *handle = reinterpret_cast<HANDLE>(file_desc);
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
if (ret == STATUS_SUCCESS) {
if ((flags & FileSystemBase::CleanupDelete) != 0U) {
::CloseHandle(handle);
remove_open_info(file_desc);
if ((flags & FspCleanupDelete) != 0U) {
remove_and_close_all(file_desc);
was_closed = TRUE;
}
}
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
return ret;
}
@ -1005,8 +1005,12 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
if (handle != INVALID_HANDLE_VALUE) {
*file_desc = reinterpret_cast<PVOID>(handle);
normalized_name = utils::string::to_utf8(file_name);
set_open_info(*file_desc,
open_info{0, "", nullptr, utils::string::to_utf8(file_path)});
set_open_info(*file_desc, open_info{
"",
nullptr,
{},
utils::string::to_utf8(file_path),
});
}
auto ret =
@ -1140,8 +1144,12 @@ auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options,
if (handle != INVALID_HANDLE_VALUE) {
*file_desc = reinterpret_cast<PVOID>(handle);
normalized_name = utils::string::to_utf8(file_name);
set_open_info(*file_desc,
open_info{0, "", nullptr, utils::string::to_utf8(file_path)});
set_open_info(*file_desc, open_info{
"",
nullptr,
{},
utils::string::to_utf8(file_path),
});
}
auto ret =

View File

@ -203,7 +203,10 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
}
if (directory) {
if (not directory) {
return handle_error(fm_->remove_file(api_path));
}
if (provider_.get_directory_item_count(api_path) == 0) {
return handle_error(provider_.remove_directory(api_path));
}
@ -211,9 +214,6 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
return handle_error(api_error::directory_not_empty);
}
return handle_error(fm_->remove_file(api_path));
}
if (((flags & FspCleanupSetArchiveBit) != 0U) && not directory) {
api_meta_map meta;
if (provider_.get_item_meta(api_path, meta) == api_error::success) {