Merging upstream version 1.14.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
868b5312e8
commit
d6fd2fdea9
305 changed files with 20664 additions and 6099 deletions
|
@ -8,6 +8,8 @@
|
|||
#include <asm/byteorder.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "linux/nvme_ioctl.h"
|
||||
|
||||
|
@ -15,7 +17,6 @@
|
|||
#include "nvme-print.h"
|
||||
#include "nvme-ioctl.h"
|
||||
#include "nvme-status.h"
|
||||
#include "json.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include "argconfig.h"
|
||||
|
@ -28,36 +29,40 @@
|
|||
#define SECTOR_SHIFT 9
|
||||
|
||||
#define SFX_GET_FREESPACE _IOWR('N', 0x240, struct sfx_freespace_ctx)
|
||||
#define IDEMA_CAP(exp_GB) (((__u64)exp_GB - 50ULL) * 1953504ULL + 97696368ULL)
|
||||
#define NVME_IOCTL_CLR_CARD _IO('N', 0x47)
|
||||
|
||||
#define IDEMA_CAP(exp_GB) (((__u64)exp_GB - 50ULL) * 1953504ULL + 97696368ULL)
|
||||
#define IDEMA_CAP2GB(exp_sector) (((__u64)exp_sector - 97696368ULL) / 1953504ULL + 50ULL)
|
||||
|
||||
enum {
|
||||
SFX_LOG_LATENCY_READ_STATS = 0xc1,
|
||||
SFX_LOG_SMART = 0xc2,
|
||||
SFX_LOG_LATENCY_WRITE_STATS = 0xc3,
|
||||
SFX_LOG_LATENCY_WRITE_STATS = 0xc3,
|
||||
SFX_LOG_QUAL = 0xc4,
|
||||
SFX_LOG_MISMATCHLBA = 0xc5,
|
||||
SFX_LOG_MEDIA = 0xc6,
|
||||
SFX_LOG_BBT = 0xc7,
|
||||
SFX_LOG_IDENTIFY = 0xcc,
|
||||
SFX_FEAT_ATOMIC = 0x01,
|
||||
SFX_FEAT_UP_P_CAP = 0xac,
|
||||
SFX_FEAT_CLR_CARD = 0xdc,
|
||||
};
|
||||
|
||||
enum sfx_nvme_admin_opcode {
|
||||
nvme_admin_query_cap_info = 0xd3,
|
||||
nvme_admin_change_cap = 0xd4,
|
||||
nvme_admin_sfx_set_features = 0xd5,
|
||||
nvme_admin_sfx_get_features = 0xd6,
|
||||
nvme_admin_sfx_set_features = 0xd5,
|
||||
nvme_admin_sfx_get_features = 0xd6,
|
||||
};
|
||||
|
||||
struct sfx_freespace_ctx
|
||||
{
|
||||
__u64 free_space;
|
||||
__u64 phy_cap; /* physical capacity, in unit of sector */
|
||||
__u64 phy_space; /* physical space considering OP, in unit of sector */
|
||||
__u64 user_space; /* user required space, in unit of sector*/
|
||||
__u64 hw_used; /* hw space used in 4K */
|
||||
__u64 app_written; /* app data written in 4K */
|
||||
__u64 phy_cap; /* physical capacity, in unit of sector */
|
||||
__u64 phy_space; /* physical space considering OP, in unit of sector */
|
||||
__u64 user_space; /* user required space, in unit of sector*/
|
||||
__u64 hw_used; /* hw space used in 4K */
|
||||
__u64 app_written; /* app data written in 4K */
|
||||
};
|
||||
|
||||
struct nvme_capacity_info {
|
||||
|
@ -66,7 +71,7 @@ struct nvme_capacity_info {
|
|||
__u64 used_space;
|
||||
__u64 free_space;
|
||||
};
|
||||
struct __attribute__((packed)) nvme_additional_smart_log_item {
|
||||
struct __attribute__((packed)) nvme_additional_smart_log_item {
|
||||
uint8_t key;
|
||||
uint8_t _kp[2];
|
||||
uint8_t norm;
|
||||
|
@ -112,11 +117,10 @@ int nvme_change_cap(int fd, __u32 nsid, __u64 capacity)
|
|||
struct nvme_admin_cmd cmd = {
|
||||
.opcode = nvme_admin_change_cap,
|
||||
.nsid = nsid,
|
||||
.cdw10 = (capacity & 0xffffffff),
|
||||
.cdw11 = (capacity >> 32),
|
||||
.cdw10 = (capacity & 0xffffffff),
|
||||
.cdw11 = (capacity >> 32),
|
||||
};
|
||||
|
||||
|
||||
return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
|
||||
}
|
||||
|
||||
|
@ -267,65 +271,65 @@ static void show_sfx_smart_log(struct nvme_additional_smart_log *smart,
|
|||
unsigned int nsid, const char *devname)
|
||||
{
|
||||
printf("Additional Smart Log for ScaleFlux device:%s namespace-id:%x\n",
|
||||
devname, nsid);
|
||||
printf("key normalized raw\n");
|
||||
printf("program_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->program_fail_cnt.norm,
|
||||
int48_to_long(smart->program_fail_cnt.raw));
|
||||
printf("erase_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->erase_fail_cnt.norm,
|
||||
int48_to_long(smart->erase_fail_cnt.raw));
|
||||
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n",
|
||||
smart->wear_leveling_cnt.norm,
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.min),
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.max),
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
|
||||
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n",
|
||||
smart->e2e_err_cnt.norm,
|
||||
int48_to_long(smart->e2e_err_cnt.raw));
|
||||
printf("crc_error_count : %3d%% %"PRIu64"\n",
|
||||
smart->crc_err_cnt.norm,
|
||||
int48_to_long(smart->crc_err_cnt.raw));
|
||||
printf("timed_workload_media_wear : %3d%% %.3f%%\n",
|
||||
smart->timed_workload_media_wear.norm,
|
||||
((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
|
||||
printf("timed_workload_host_reads : %3d%% %"PRIu64"%%\n",
|
||||
smart->timed_workload_host_reads.norm,
|
||||
int48_to_long(smart->timed_workload_host_reads.raw));
|
||||
printf("timed_workload_timer : %3d%% %"PRIu64" min\n",
|
||||
smart->timed_workload_timer.norm,
|
||||
int48_to_long(smart->timed_workload_timer.raw));
|
||||
printf("thermal_throttle_status : %3d%% %u%%, cnt: %u\n",
|
||||
smart->thermal_throttle_status.norm,
|
||||
smart->thermal_throttle_status.thermal_throttle.pct,
|
||||
smart->thermal_throttle_status.thermal_throttle.count);
|
||||
printf("retry_buffer_overflow_count : %3d%% %"PRIu64"\n",
|
||||
smart->retry_buffer_overflow_cnt.norm,
|
||||
int48_to_long(smart->retry_buffer_overflow_cnt.raw));
|
||||
printf("pll_lock_loss_count : %3d%% %"PRIu64"\n",
|
||||
smart->pll_lock_loss_cnt.norm,
|
||||
int48_to_long(smart->pll_lock_loss_cnt.raw));
|
||||
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->nand_bytes_written.norm,
|
||||
int48_to_long(smart->nand_bytes_written.raw));
|
||||
printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->host_bytes_written.norm,
|
||||
int48_to_long(smart->host_bytes_written.raw));
|
||||
printf("raid_recover_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->raid_recover_cnt.norm,
|
||||
int48_to_long(smart->raid_recover_cnt.raw));
|
||||
printf("read_ecc_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->read_ecc_cnt.norm,
|
||||
int48_to_long(smart->read_ecc_cnt.raw));
|
||||
printf("prog_timeout_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->prog_timeout_cnt.norm,
|
||||
int48_to_long(smart->prog_timeout_cnt.raw));
|
||||
printf("erase_timeout_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->erase_timeout_cnt.norm,
|
||||
int48_to_long(smart->erase_timeout_cnt.raw));
|
||||
printf("read_timeout_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->read_timeout_cnt.norm,
|
||||
int48_to_long(smart->read_timeout_cnt.raw));
|
||||
devname, nsid);
|
||||
printf("key normalized raw\n");
|
||||
printf("program_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->program_fail_cnt.norm,
|
||||
int48_to_long(smart->program_fail_cnt.raw));
|
||||
printf("erase_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->erase_fail_cnt.norm,
|
||||
int48_to_long(smart->erase_fail_cnt.raw));
|
||||
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n",
|
||||
smart->wear_leveling_cnt.norm,
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.min),
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.max),
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
|
||||
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n",
|
||||
smart->e2e_err_cnt.norm,
|
||||
int48_to_long(smart->e2e_err_cnt.raw));
|
||||
printf("crc_error_count : %3d%% %"PRIu64"\n",
|
||||
smart->crc_err_cnt.norm,
|
||||
int48_to_long(smart->crc_err_cnt.raw));
|
||||
printf("timed_workload_media_wear : %3d%% %.3f%%\n",
|
||||
smart->timed_workload_media_wear.norm,
|
||||
((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
|
||||
printf("timed_workload_host_reads : %3d%% %"PRIu64"%%\n",
|
||||
smart->timed_workload_host_reads.norm,
|
||||
int48_to_long(smart->timed_workload_host_reads.raw));
|
||||
printf("timed_workload_timer : %3d%% %"PRIu64" min\n",
|
||||
smart->timed_workload_timer.norm,
|
||||
int48_to_long(smart->timed_workload_timer.raw));
|
||||
printf("thermal_throttle_status : %3d%% %u%%, cnt: %u\n",
|
||||
smart->thermal_throttle_status.norm,
|
||||
smart->thermal_throttle_status.thermal_throttle.pct,
|
||||
smart->thermal_throttle_status.thermal_throttle.count);
|
||||
printf("retry_buffer_overflow_count : %3d%% %"PRIu64"\n",
|
||||
smart->retry_buffer_overflow_cnt.norm,
|
||||
int48_to_long(smart->retry_buffer_overflow_cnt.raw));
|
||||
printf("pll_lock_loss_count : %3d%% %"PRIu64"\n",
|
||||
smart->pll_lock_loss_cnt.norm,
|
||||
int48_to_long(smart->pll_lock_loss_cnt.raw));
|
||||
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->nand_bytes_written.norm,
|
||||
int48_to_long(smart->nand_bytes_written.raw));
|
||||
printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->host_bytes_written.norm,
|
||||
int48_to_long(smart->host_bytes_written.raw));
|
||||
printf("raid_recover_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->raid_recover_cnt.norm,
|
||||
int48_to_long(smart->raid_recover_cnt.raw));
|
||||
printf("read_ecc_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->read_ecc_cnt.norm,
|
||||
int48_to_long(smart->read_ecc_cnt.raw));
|
||||
printf("prog_timeout_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->prog_timeout_cnt.norm,
|
||||
int48_to_long(smart->prog_timeout_cnt.raw));
|
||||
printf("erase_timeout_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->erase_timeout_cnt.norm,
|
||||
int48_to_long(smart->erase_timeout_cnt.raw));
|
||||
printf("read_timeout_cnt : %3d%% %"PRIu64"\n",
|
||||
smart->read_timeout_cnt.norm,
|
||||
int48_to_long(smart->read_timeout_cnt.raw));
|
||||
}
|
||||
|
||||
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -357,8 +361,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
|
|||
|
||||
fd = parse_and_open(argc, argv, desc, opts);
|
||||
|
||||
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, sizeof(smart_log),
|
||||
(void *)&smart_log);
|
||||
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, NVME_NO_LOG_LSP,
|
||||
sizeof(smart_log), (void *)&smart_log);
|
||||
if (!err) {
|
||||
if (cfg.json)
|
||||
show_sfx_smart_log_jsn(&smart_log, cfg.namespace_id, devicename);
|
||||
|
@ -373,7 +377,6 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
struct sfx_lat_stats {
|
||||
__u16 maj;
|
||||
__u16 min;
|
||||
|
@ -440,7 +443,8 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
|
|||
|
||||
fd = parse_and_open(argc, argv, desc, opts);
|
||||
|
||||
err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, sizeof(stats), (void *)&stats);
|
||||
err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, NVME_NO_LOG_LSP,
|
||||
sizeof(stats), (void *)&stats);
|
||||
if (!err) {
|
||||
if (!cfg.raw_binary)
|
||||
show_lat_stats(&stats, cfg.write);
|
||||
|
@ -448,7 +452,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
|
|||
d_raw((unsigned char *)&stats, sizeof(stats));
|
||||
} else if (err > 0)
|
||||
fprintf(stderr, "NVMe Status:%s(%x)\n",
|
||||
nvme_status_to_string(err), err);
|
||||
nvme_status_to_string(err), err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -517,16 +521,16 @@ static void bd_table_show(unsigned char *bd_table, __u64 table_size)
|
|||
bb_elem = (__u64 *)(bd_table + 5 * sizeof(__u32));
|
||||
|
||||
printf("Bad Block Table \n");
|
||||
printf("MF_BB_COUNT: %u\n", mf_bb_count);
|
||||
printf("GROWN_BB_COUNT: %u\n", grown_bb_count);
|
||||
printf("TOTAL_BB_COUNT: %u\n", total_bb_count);
|
||||
printf("REMAP_MFBB_COUNT: %u\n", remap_mfbb_count);
|
||||
printf("REMAP_GBB_COUNT: %u\n", remap_gbb_count);
|
||||
printf("MF_BB_COUNT: %u\n", mf_bb_count);
|
||||
printf("GROWN_BB_COUNT: %u\n", grown_bb_count);
|
||||
printf("TOTAL_BB_COUNT: %u\n", total_bb_count);
|
||||
printf("REMAP_MFBB_COUNT: %u\n", remap_mfbb_count);
|
||||
printf("REMAP_GBB_COUNT: %u\n", remap_gbb_count);
|
||||
|
||||
printf("REMAP_MFBB_TABLE [");
|
||||
i = 0;
|
||||
while (bb_elem < elem_end && i < remap_mfbb_count) {
|
||||
printf(" 0x%llx", *(bb_elem++));
|
||||
printf(" 0x%"PRIx64"", (uint64_t)*(bb_elem++));
|
||||
i++;
|
||||
}
|
||||
printf(" ]\n");
|
||||
|
@ -534,14 +538,14 @@ static void bd_table_show(unsigned char *bd_table, __u64 table_size)
|
|||
printf("REMAP_GBB_TABLE [");
|
||||
i = 0;
|
||||
while (bb_elem < elem_end && i < remap_gbb_count) {
|
||||
printf(" 0x%llx",*(bb_elem++));
|
||||
printf(" 0x%"PRIx64"", (uint64_t)*(bb_elem++));
|
||||
i++;
|
||||
}
|
||||
printf(" ]\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "hooks of sfx get-bad-block"
|
||||
* @brief "hooks of sfx get-bad-block"
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
|
@ -592,10 +596,16 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
|
|||
|
||||
static void show_cap_info(struct sfx_freespace_ctx *ctx)
|
||||
{
|
||||
printf("user sectors: %#llx\n", ctx->user_space);
|
||||
printf("totl physical sectors: %#llx\n", ctx->phy_space);
|
||||
printf("free physical sectors: %#llx\n", ctx->free_space);
|
||||
printf("used physical sectors: %#llx\n", ctx->phy_space - ctx->free_space);
|
||||
|
||||
printf("logic capacity:%5lluGB(0x%"PRIx64")\n",
|
||||
IDEMA_CAP2GB(ctx->user_space), (uint64_t)ctx->user_space);
|
||||
printf("provisioned capacity:%5lluGB(0x%"PRIx64")\n",
|
||||
IDEMA_CAP2GB(ctx->phy_space), (uint64_t)ctx->phy_space);
|
||||
printf("free provisioned capacity:%5lluGB(0x%"PRIx64")\n",
|
||||
IDEMA_CAP2GB(ctx->free_space), (uint64_t)ctx->free_space);
|
||||
printf("used provisioned capacity:%5lluGB(0x%"PRIx64")\n",
|
||||
IDEMA_CAP2GB(ctx->phy_space) - IDEMA_CAP2GB(ctx->free_space),
|
||||
(uint64_t)(ctx->phy_space - ctx->free_space));
|
||||
}
|
||||
|
||||
static int query_cap_info(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -631,40 +641,92 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu
|
|||
return err;
|
||||
}
|
||||
|
||||
static int change_cap_mem_check(int fd, __u64 trg_in_4k)
|
||||
static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
||||
{
|
||||
struct sfx_freespace_ctx freespace_ctx = { 0 };
|
||||
struct sysinfo s_info;
|
||||
__u64 mem_need = 0;
|
||||
__u64 cur_in_4k = 0;
|
||||
__u64 provisoned_cap_4k = 0;
|
||||
__u32 cnt_ms = 0;
|
||||
int extend = 0;
|
||||
|
||||
while (ioctl(fd, SFX_GET_FREESPACE, &freespace_ctx)) {
|
||||
if (cnt_ms++ > 600) {//1min
|
||||
fprintf(stderr, "vu ioctl fail, errno %d\r\n", errno);
|
||||
return -1;
|
||||
}
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
/*
|
||||
* capacity illegal check
|
||||
*/
|
||||
provisoned_cap_4k = freespace_ctx.phy_space >>
|
||||
(SFX_PAGE_SHIFT - SECTOR_SHIFT);
|
||||
if (trg_in_4k < provisoned_cap_4k ||
|
||||
trg_in_4k > ((__u64)provisoned_cap_4k * 4)) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Only support 1.0~4.0 x provisoned capacity!\n");
|
||||
if (trg_in_4k < provisoned_cap_4k) {
|
||||
fprintf(stderr,
|
||||
"WARNING: The target capacity is less than 1.0 x provisioned capacity!\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"WARNING: The target capacity is larger than 4.0 x provisioned capacity!\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (trg_in_4k > ((__u64)provisoned_cap_4k*4)) {
|
||||
fprintf(stderr, "WARNING: the target capacity is too large\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether mem enough if extend
|
||||
* */
|
||||
cur_in_4k = freespace_ctx.user_space >> (SFX_PAGE_SHIFT - SECTOR_SHIFT);
|
||||
if (cur_in_4k > trg_in_4k) {
|
||||
extend = (cur_in_4k <= trg_in_4k);
|
||||
if (extend) {
|
||||
if (sysinfo(&s_info) < 0) {
|
||||
printf("change-cap query mem info fail\n");
|
||||
return -1;
|
||||
}
|
||||
mem_need = (trg_in_4k - cur_in_4k) * 8;
|
||||
if (s_info.freeram <= 10 || mem_need > s_info.freeram) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Free memory is not enough! "
|
||||
"Please drop cache or extend more memory and retry\n"
|
||||
"WARNING: Memory needed is %"PRIu64", free memory is %"PRIu64"\n",
|
||||
(uint64_t)mem_need, (uint64_t)s_info.freeram);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*shrink = !extend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief prompt and get user confirm input
|
||||
*
|
||||
* @param str, prompt string
|
||||
*
|
||||
* @return 0, cancled; 1 confirmed
|
||||
*/
|
||||
static int sfx_confirm_change(const char *str)
|
||||
{
|
||||
char confirm;
|
||||
fprintf(stderr, "WARNING: %s.\n"
|
||||
"Use the force [--force] option to suppress this warning.\n", str);
|
||||
|
||||
fprintf(stderr, "Confirm Y/y, Others cancel:\n");
|
||||
confirm = fgetc(stdin);
|
||||
if (confirm != 'y' && confirm != 'Y') {
|
||||
fprintf(stderr, "Cancled.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sysinfo(&s_info) < 0) {
|
||||
printf("change-cap query mem info fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_need = (trg_in_4k - cur_in_4k) * 8;
|
||||
if (s_info.freeram <= 10 || mem_need > s_info.freeram) {
|
||||
fprintf(stderr, "WARNING: mem needed is %llu, free mem is %lu\n"
|
||||
"Insufficient memory, please drop cache or add free memory and retry\n",
|
||||
mem_need, s_info.freeram);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
fprintf(stderr, "Sending operation ... \n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int change_cap(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -678,6 +740,8 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
|
|||
const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
|
||||
__u64 cap_in_4k = 0;
|
||||
__u64 cap_in_sec = 0;
|
||||
int shrink = 0;
|
||||
|
||||
struct config {
|
||||
__u64 cap_in_byte;
|
||||
__u32 capacity_in_gb;
|
||||
|
@ -694,7 +758,7 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
|
|||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("cap", 'c', &cfg.capacity_in_gb, cap_gb),
|
||||
OPT_UINT("cap-byte", 'z', &cfg.cap_in_byte, cap_byte),
|
||||
OPT_SUFFIX("cap-byte", 'z', &cfg.cap_in_byte, cap_byte),
|
||||
OPT_FLAG("force", 'f', &cfg.force, force),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_FLAG("json", 'j', &cfg.json, json),
|
||||
|
@ -706,22 +770,21 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
|
|||
return fd;
|
||||
}
|
||||
|
||||
if (!cfg.force) {
|
||||
fprintf(stderr, "WARNING: Changing capacity may irrevocably delete user data.\n"
|
||||
"You have 10 seconds to press Ctrl-C to cancel this operation.\n\n"
|
||||
"Use the force [--force|-f] option to suppress this warning.\n");
|
||||
sleep(10);
|
||||
fprintf(stderr, "Sending operation ... \n");
|
||||
}
|
||||
|
||||
cap_in_sec = IDEMA_CAP(cfg.capacity_in_gb);
|
||||
cap_in_4k = cap_in_sec >> 3;
|
||||
if (cfg.cap_in_byte)
|
||||
cap_in_4k = cfg.cap_in_byte >> 12;
|
||||
printf("%dG %lluB %llu 4K\n",
|
||||
cfg.capacity_in_gb, cfg.cap_in_byte, cap_in_4k);
|
||||
if (change_cap_mem_check(fd, cap_in_4k))
|
||||
printf("%dG %"PRIu64"B %"PRIu64" 4K\n",
|
||||
cfg.capacity_in_gb, (uint64_t)cfg.cap_in_byte, (uint64_t)cap_in_4k);
|
||||
|
||||
if (change_sanity_check(fd, cap_in_4k, &shrink)) {
|
||||
printf("ScaleFlux change-capacity: fail\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!cfg.force && shrink && !sfx_confirm_change("Changing Cap may irrevocably delete this device's data")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = nvme_change_cap(fd, 0xffffffff, cap_in_4k);
|
||||
if (err < 0)
|
||||
|
@ -731,20 +794,54 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
|
|||
nvme_status_to_string(err), err);
|
||||
else {
|
||||
printf("ScaleFlux change-capacity: success\n");
|
||||
if(ioctl(fd, BLKRRPART) < 0) {
|
||||
fprintf(stderr, "failed to re-read partition table\n");
|
||||
err = EFAULT;
|
||||
}
|
||||
ioctl(fd, BLKRRPART);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sfx_verify_chr(int fd)
|
||||
{
|
||||
static struct stat nvme_stat;
|
||||
int err = fstat(fd, &nvme_stat);
|
||||
|
||||
if (err < 0) {
|
||||
perror("fstat");
|
||||
return errno;
|
||||
}
|
||||
if (!S_ISCHR(nvme_stat.st_mode)) {
|
||||
fprintf(stderr,
|
||||
"Error: requesting clean card on non-controller handle\n");
|
||||
return ENOTBLK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sfx_clean_card(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sfx_verify_chr(fd);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ioctl(fd, NVME_IOCTL_CLR_CARD);
|
||||
if (ret)
|
||||
perror("Ioctl Fail.");
|
||||
else
|
||||
printf("ScaleFlux clean card success\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *sfx_feature_to_string(int feature)
|
||||
{
|
||||
switch (feature) {
|
||||
case SFX_FEAT_ATOMIC: return "ATOMIC";
|
||||
case SFX_FEAT_ATOMIC:
|
||||
return "ATOMIC";
|
||||
case SFX_FEAT_UP_P_CAP:
|
||||
return "UPDATE_PROVISION_CAPACITY";
|
||||
|
||||
default: return "Unknown";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -752,27 +849,34 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
{
|
||||
int err = 0, fd;
|
||||
char *desc = "ScaleFlux internal set features\n"
|
||||
"feature id 1: ATOMIC";
|
||||
"feature id 1: ATOMIC\n"
|
||||
"value 0: Disable atomic write\n"
|
||||
" 1: Enable atomic write";
|
||||
const char *value = "new value of feature (required)";
|
||||
const char *feature_id = "hex feature name (required)";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
|
||||
|
||||
struct nvme_id_ns ns;
|
||||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
__u32 feature_id;
|
||||
__u32 value;
|
||||
__u32 force;
|
||||
};
|
||||
struct config cfg = {
|
||||
.namespace_id = 1,
|
||||
.feature_id = 0,
|
||||
.value = 0,
|
||||
.force = 0,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id),
|
||||
OPT_UINT("value", 'v', &cfg.value, value),
|
||||
OPT_UINT("value", 'v', &cfg.value, value),
|
||||
OPT_FLAG("force", 's', &cfg.force, force),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -786,7 +890,17 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
if (cfg.feature_id == SFX_FEAT_ATOMIC) {
|
||||
if (cfg.feature_id == SFX_FEAT_CLR_CARD) {
|
||||
/*Warning for clean card*/
|
||||
if (!cfg.force && !sfx_confirm_change("Going to clean device's data, confirm umount fs and try again")) {
|
||||
return 0;
|
||||
} else {
|
||||
return sfx_clean_card(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) {
|
||||
if (cfg.namespace_id != 0xffffffff) {
|
||||
err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns);
|
||||
if (err) {
|
||||
|
@ -806,14 +920,25 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
return EFAULT;
|
||||
}
|
||||
}
|
||||
} else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) {
|
||||
if (cfg.value <= 0) {
|
||||
fprintf(stderr, "Invalid Param\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*Warning for change pacp by GB*/
|
||||
if (!cfg.force && !sfx_confirm_change("Changing physical capacity may irrevocably delete this device's data")) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
err = nvme_sfx_set_features(fd, cfg.namespace_id, cfg.feature_id, cfg.value);
|
||||
|
||||
if (err < 0) {
|
||||
perror("ScaleFlux-set-feature");
|
||||
return errno;
|
||||
} else if (!err) {
|
||||
printf("ScaleFlux set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
|
||||
printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id,
|
||||
sfx_feature_to_string(cfg.feature_id), cfg.value);
|
||||
} else if (err > 0)
|
||||
fprintf(stderr, "NVMe Status:%s(%x)\n",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue