C2: Add icsneoc2_device_force_disk_config_update

This commit is contained in:
David Rebbe
2026-06-29 09:55:18 -04:00
committed by Kyle Schwarz
parent 9d91524dc0
commit 19232def41
6 changed files with 128 additions and 2 deletions
+16
View File
@@ -71,6 +71,7 @@ icsneoc2_error_t icsneoc2_error_code_get(icsneoc2_error_t error_code, char* valu
"Close failed", // icsneoc2_error_close_failed "Close failed", // icsneoc2_error_close_failed
"Reconnect failed", // icsneoc2_error_reconnect_failed "Reconnect failed", // icsneoc2_error_reconnect_failed
"Invalid data", // icsneoc2_error_invalid_data "Invalid data", // icsneoc2_error_invalid_data
"Force disk config update failed", // icsneoc2_error_force_disk_config_update_failed
}; };
static_assert(std::size(error_strings) == icsneoc2_error_maxsize, static_assert(std::size(error_strings) == icsneoc2_error_maxsize,
"error_strings is out of sync with _icsneoc2_error_t enum - update both together"); "error_strings is out of sync with _icsneoc2_error_t enum - update both together");
@@ -1097,6 +1098,21 @@ icsneoc2_error_t icsneoc2_device_format_disk(const icsneoc2_device_t* device, ic
return icsneoc2_error_success; return icsneoc2_error_success;
} }
icsneoc2_error_t icsneoc2_device_force_disk_config_update(const icsneoc2_device_t* device, icsneoc2_disk_details_t* disk_details) {
auto res = icsneoc2_device_is_valid(device);
if(res != icsneoc2_error_success) {
return res;
}
if(!disk_details || !disk_details->details) {
return icsneoc2_error_invalid_parameters;
}
if(!device->device->forceDiskConfigUpdate(*disk_details->details)) {
return icsneoc2_error_force_disk_config_update_failed;
}
return icsneoc2_error_success;
}
static icsneoc2_error_t get_supported_networks(const icsneoc2_device_t* device, const std::vector<Network>& nets, icsneoc2_netid_t* networks, size_t* count) { static icsneoc2_error_t get_supported_networks(const icsneoc2_device_t* device, const std::vector<Network>& nets, icsneoc2_netid_t* networks, size_t* count) {
auto res = icsneoc2_device_is_valid(device); auto res = icsneoc2_device_is_valid(device);
if(res != icsneoc2_error_success) { if(res != icsneoc2_error_success) {
+79
View File
@@ -109,6 +109,85 @@ int main() {
} }
} }
/* Choose operation */
printf("\n\tChoose operation:\n");
printf("\t [f] Format the disk(s)\n");
printf("\t [u] Update the disk configuration without formatting\n");
printf("\t [q] Quit\n");
printf("\tSelection [f/u/q]: ");
char choice[8] = {0};
if(scanf("%7s", choice) != 1) {
choice[0] = 'q';
}
if(choice[0] == 'u' || choice[0] == 'U') {
/* Force a disk config update (e.g. changing the disk layout) without formatting.
* Unlike a format, this preserves the existing data on the disk(s). */
printf("\n\tChoose disk layout:\n");
printf("\t [s] Spanned\n");
printf("\t [r] RAID0\n");
printf("\tSelection [s/r] (current: %s): ", layout == icsneoc2_disk_layout_raid0 ? "RAID0" : "Spanned");
char layout_choice[8] = {0};
if(scanf("%7s", layout_choice) != 1) {
layout_choice[0] = '\0';
}
if(layout_choice[0] == 'r' || layout_choice[0] == 'R') {
icsneoc2_disk_details_layout_set(details, icsneoc2_disk_layout_raid0);
} else if(layout_choice[0] == 's' || layout_choice[0] == 'S') {
icsneoc2_disk_details_layout_set(details, icsneoc2_disk_layout_spanned);
} else {
printf("\tKeeping current layout.\n");
}
/* Enable/disable individual disks in the configuration. A disk's enabled
* state is carried by the FORMATTED flag; only present disks can be enabled. */
for(size_t i = 0; i < detail_count; i++) {
icsneoc2_disk_format_flags_t flags = 0;
icsneoc2_disk_details_flags_get(details, i, &flags);
if(!(flags & ICSNEOC2_DISK_FORMAT_FLAGS_PRESENT)) {
continue; /* Can't enable a disk that isn't present */
}
printf("\tEnable disk [%zu]? [y/N] (currently %s): ", i,
(flags & ICSNEOC2_DISK_FORMAT_FLAGS_FORMATTED) ? "enabled" : "disabled");
char disk_choice[8] = {0};
if(scanf("%7s", disk_choice) != 1) {
disk_choice[0] = '\0';
}
if(disk_choice[0] == 'y' || disk_choice[0] == 'Y') {
flags |= ICSNEOC2_DISK_FORMAT_FLAGS_FORMATTED;
} else {
flags &= ~(icsneoc2_disk_format_flags_t)ICSNEOC2_DISK_FORMAT_FLAGS_FORMATTED;
}
icsneoc2_disk_details_flags_set(details, i, flags);
}
icsneoc2_disk_layout_t new_layout = 0;
icsneoc2_disk_details_layout_get(details, &new_layout);
printf("\n\tForcing disk config update on %s to %s layout (no data will be erased)...\n",
description, new_layout == icsneoc2_disk_layout_raid0 ? "RAID0" : "Spanned");
res = icsneoc2_device_force_disk_config_update(device, details);
if(res != icsneoc2_error_success) {
print_error_code("\tForce disk config update failed", res);
icsneoc2_disk_details_free(details);
icsneoc2_device_close(device);
icsneoc2_device_free(device);
return -1;
}
printf("\tDisk config update complete!\n");
icsneoc2_disk_details_free(details);
icsneoc2_device_close(device);
icsneoc2_device_free(device);
return 0;
}
if(choice[0] != 'f' && choice[0] != 'F') {
printf("\tAborted.\n");
icsneoc2_disk_details_free(details);
icsneoc2_device_close(device);
icsneoc2_device_free(device);
return 0;
}
/* Build format config: mark present disks for formatting */ /* Build format config: mark present disks for formatting */
bool any_present = false; bool any_present = false;
for(size_t i = 0; i < detail_count; i++) { for(size_t i = 0; i < detail_count; i++) {
+2 -1
View File
@@ -18,7 +18,8 @@ enum class DiskLayout : uint8_t {
struct DiskInfo { struct DiskInfo {
bool present; // Disk is connected bool present; // Disk is connected
bool initialized; // Disk is initialized bool initialized; // Disk is initialized
bool formatted; // Disk is formatted // getDiskDetails: disk is formatted | formatDisk: disk to format | forceDiskConfigUpdate: disk enabled in layout (also reported as formatted)
bool formatted;
uint64_t sectors; uint64_t sectors;
uint32_t bytesPerSector; uint32_t bytesPerSector;
+19
View File
@@ -47,6 +47,7 @@ typedef enum _icsneoc2_error_t {
icsneoc2_error_close_failed, // Failed to close device icsneoc2_error_close_failed, // Failed to close device
icsneoc2_error_reconnect_failed, // Failed to reconnect to device icsneoc2_error_reconnect_failed, // Failed to reconnect to device
icsneoc2_error_invalid_data, // Failed to get/set data due to invalid data pointer or size icsneoc2_error_invalid_data, // Failed to get/set data due to invalid data pointer or size
icsneoc2_error_force_disk_config_update_failed, // Failed to force a disk config update
// NOTE: Any new values added here should be updated in icsneoc2_error_code_get // NOTE: Any new values added here should be updated in icsneoc2_error_code_get
icsneoc2_error_maxsize icsneoc2_error_maxsize
} _icsneoc2_error_t; } _icsneoc2_error_t;
@@ -846,6 +847,24 @@ icsneoc2_error_t icsneoc2_disk_details_full_format_set(const icsneoc2_disk_detai
*/ */
icsneoc2_error_t icsneoc2_device_format_disk(const icsneoc2_device_t* device, icsneoc2_disk_details_t* disk_details, icsneoc2_disk_format_progress_fn progress_callback, void* user_data); icsneoc2_error_t icsneoc2_device_format_disk(const icsneoc2_device_t* device, icsneoc2_disk_details_t* disk_details, icsneoc2_disk_format_progress_fn progress_callback, void* user_data);
/**
* Force a disk layout/configuration change on a device without formatting.
*
* Unlike icsneoc2_device_format_disk(), this applies the configuration described by the
* disk details handle (such as the disk layout) and enables the change without erasing data.
*
* @param[in] device The device whose disk configuration should be updated.
* @param[in] disk_details A disk details handle describing the desired configuration.
* Use icsneoc2_device_disk_details_get() to obtain a handle, then modify it
* (e.g. set the layout with icsneoc2_disk_details_layout_set()).
* In this context the per-disk ICSNEOC2_DISK_FORMAT_FLAGS_FORMATTED flag
* selects whether that disk is enabled in the layout (no formatting occurs).
*
* @return icsneoc2_error_t icsneoc2_error_success if successful,
* icsneoc2_error_force_disk_config_update_failed otherwise.
*/
icsneoc2_error_t icsneoc2_device_force_disk_config_update(const icsneoc2_device_t* device, icsneoc2_disk_details_t* disk_details);
/** /**
* Get the list of networks this device supports for receiving. * Get the list of networks this device supports for receiving.
* *
+1 -1
View File
@@ -413,7 +413,7 @@ typedef uint8_t icsneoc2_disk_layout_t;
#define ICSNEOC2_DISK_FORMAT_FLAGS_PRESENT 0x1 // Indicates that the disk is present #define ICSNEOC2_DISK_FORMAT_FLAGS_PRESENT 0x1 // Indicates that the disk is present
#define ICSNEOC2_DISK_FORMAT_FLAGS_INITIALIZED 0x2 // Indicates that the disk is initialized #define ICSNEOC2_DISK_FORMAT_FLAGS_INITIALIZED 0x2 // Indicates that the disk is initialized
#define ICSNEOC2_DISK_FORMAT_FLAGS_FORMATTED 0x4 // Indicates that the disk is already formatted #define ICSNEOC2_DISK_FORMAT_FLAGS_FORMATTED 0x4 // disk_details_get: disk is formatted | format_disk: disk to format | force_disk_config_update: disk enabled in layout (also reported as formatted)
typedef uint32_t icsneoc2_disk_format_flags_t; typedef uint32_t icsneoc2_disk_format_flags_t;
+11
View File
@@ -338,6 +338,7 @@ TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device)
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_supports_disk_formatting(NULL, &placeholderBool)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_supports_disk_formatting(NULL, &placeholderBool));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_disk_details_get(NULL, NULL)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_disk_details_get(NULL, NULL));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_format_disk(NULL, NULL, NULL, NULL)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_format_disk(NULL, NULL, NULL, NULL));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_force_disk_config_update(NULL, NULL));
// Disk details accessors with NULL details // Disk details accessors with NULL details
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_disk_details_count_get(NULL, &placeholderSizeT)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_disk_details_count_get(NULL, &placeholderSizeT));
@@ -1391,6 +1392,16 @@ TEST(icsneoc2, test_icsneoc2_format_disk_error_code)
ASSERT_STREQ(error_str, "Disk format failed"); ASSERT_STREQ(error_str, "Disk format failed");
} }
TEST(icsneoc2, test_icsneoc2_force_disk_config_update_error_code)
{
// Verify the new error code exists and has a valid string
char error_str[64] = {0};
size_t error_str_len = sizeof(error_str);
ASSERT_EQ(icsneoc2_error_success, icsneoc2_error_code_get(icsneoc2_error_force_disk_config_update_failed, error_str, &error_str_len));
ASSERT_GT(error_str_len, 0u);
ASSERT_STREQ(error_str, "Force disk config update failed");
}
TEST(icsneoc2, test_icsneoc2_memory_type_enums) TEST(icsneoc2, test_icsneoc2_memory_type_enums)
{ {
// Memory type enum values should match Disk::MemoryType // Memory type enum values should match Disk::MemoryType