Update to latest upstream
Update to 4.3 and add gating test Resolves: RHEL-30530 Signed-off-by: Xiao Ni <xni@redhat.com>
This commit is contained in:
parent
fbe794e269
commit
ebabcd5c79
44
0042-mdadm-Move-pr_vrb-define-to-mdadm.h.patch
Normal file
44
0042-mdadm-Move-pr_vrb-define-to-mdadm.h.patch
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
From cc75b0faaa016e54d569486c9a7abe6c39cb883a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:51:15 +0100
|
||||||
|
Subject: [PATCH 42/66] mdadm: Move pr_vrb define to mdadm.h
|
||||||
|
|
||||||
|
Move pr_vrb define from super-intel.c to mdadm.h to make it widely
|
||||||
|
available. This change will be used in the next patches.
|
||||||
|
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
mdadm.h | 2 ++
|
||||||
|
super-intel.c | 2 --
|
||||||
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index ae2106a2..fbb161ba 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1911,6 +1911,8 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
|
||||||
|
|
||||||
|
#define pr_info(fmt, args...) printf("%s: "fmt, Name, ##args)
|
||||||
|
|
||||||
|
+#define pr_vrb(fmt, arg...) ((void)(verbose && pr_err(fmt, ##arg)))
|
||||||
|
+
|
||||||
|
void *xmalloc(size_t len);
|
||||||
|
void *xrealloc(void *ptr, size_t len);
|
||||||
|
void *xcalloc(size_t num, size_t size);
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 70f3c4ef..212387ec 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -393,8 +393,6 @@ struct md_list {
|
||||||
|
struct md_list *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define pr_vrb(fmt, arg...) (void) (verbose && pr_err(fmt, ##arg))
|
||||||
|
-
|
||||||
|
static __u8 migr_type(struct imsm_dev *dev)
|
||||||
|
{
|
||||||
|
if (dev->vol.migr_type == MIGR_VERIFY &&
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
463
0043-Add-reading-Opal-NVMe-encryption-information.patch
Normal file
463
0043-Add-reading-Opal-NVMe-encryption-information.patch
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
From cc48406887b3bc439e3462e8e4d20f992e81b87e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:51:16 +0100
|
||||||
|
Subject: [PATCH 43/66] Add reading Opal NVMe encryption information
|
||||||
|
|
||||||
|
For NVMe devices with Opal support, encryption information, status and
|
||||||
|
ability are determined based on Opal Level 0 discovery response. Technical
|
||||||
|
documentation used is given in the implementation.
|
||||||
|
|
||||||
|
Ability in general describes what type of encryption is supported, Status
|
||||||
|
describes in what state the disk with encryption support is. The current
|
||||||
|
patch includes only the implementation of reading encryption information,
|
||||||
|
functions will be used in one of the next patches.
|
||||||
|
|
||||||
|
Motivation for adding this functionality is to block mixing of disks in
|
||||||
|
IMSM arrays with encryption enabled and disabled. The main goal is to not
|
||||||
|
allow stealing data by rebuilding array to not encrypted drive which can be
|
||||||
|
read elsewhere.
|
||||||
|
|
||||||
|
Value ENA_OTHER from enum encryption_ability will be used in the next
|
||||||
|
patch.
|
||||||
|
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Makefile | 4 +-
|
||||||
|
drive_encryption.c | 362 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
drive_encryption.h | 32 ++++
|
||||||
|
3 files changed, 396 insertions(+), 2 deletions(-)
|
||||||
|
create mode 100644 drive_encryption.c
|
||||||
|
create mode 100644 drive_encryption.h
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index cbdba49a..7c221a89 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -170,7 +170,7 @@ OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o uuid.o util.o maps.o lib.o u
|
||||||
|
mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \
|
||||||
|
super-mbr.o super-gpt.o \
|
||||||
|
restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o xmalloc.o \
|
||||||
|
- platform-intel.o probe_roms.o crc32c.o
|
||||||
|
+ platform-intel.o probe_roms.o crc32c.o drive_encryption.o
|
||||||
|
|
||||||
|
CHECK_OBJS = restripe.o uuid.o sysfs.o maps.o lib.o xmalloc.o dlink.o
|
||||||
|
|
||||||
|
@@ -183,7 +183,7 @@ MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o c
|
||||||
|
Kill.o sg_io.o dlink.o ReadMe.o super-intel.o \
|
||||||
|
super-mbr.o super-gpt.o \
|
||||||
|
super-ddf.o sha1.o crc32.o msg.o bitmap.o xmalloc.o \
|
||||||
|
- platform-intel.o probe_roms.o crc32c.o
|
||||||
|
+ platform-intel.o probe_roms.o crc32c.o drive_encryption.o
|
||||||
|
|
||||||
|
MON_SRCS = $(patsubst %.o,%.c,$(MON_OBJS))
|
||||||
|
|
||||||
|
diff --git a/drive_encryption.c b/drive_encryption.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..b44585a7
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drive_encryption.c
|
||||||
|
@@ -0,0 +1,362 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
+/*
|
||||||
|
+ * Read encryption information for Opal and ATA devices.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2024 Intel Corporation
|
||||||
|
+ * Author: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "mdadm.h"
|
||||||
|
+
|
||||||
|
+#include <asm/types.h>
|
||||||
|
+#include <linux/nvme_ioctl.h>
|
||||||
|
+#include "drive_encryption.h"
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Opal defines
|
||||||
|
+ * TCG Storage Opal SSC 2.01 chapter 3.3.3
|
||||||
|
+ * NVM ExpressTM Revision 1.4c, chapter 5
|
||||||
|
+ */
|
||||||
|
+#define TCG_SECP_01 (0x01)
|
||||||
|
+#define TCG_SECP_00 (0x00)
|
||||||
|
+#define OPAL_DISCOVERY_COMID (0x0001)
|
||||||
|
+#define OPAL_LOCKING_FEATURE (0x0002)
|
||||||
|
+#define OPAL_IO_BUFFER_LEN 2048
|
||||||
|
+#define OPAL_DISCOVERY_FEATURE_HEADER_LEN (4)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * NVMe defines
|
||||||
|
+ * NVM ExpressTM Revision 1.4c, chapter 5
|
||||||
|
+ */
|
||||||
|
+#define NVME_SECURITY_RECV (0x82)
|
||||||
|
+#define NVME_IDENTIFY (0x06)
|
||||||
|
+#define NVME_IDENTIFY_RESPONSE_LEN 4096
|
||||||
|
+#define NVME_OACS_BYTE_POSITION (256)
|
||||||
|
+#define NVME_IDENTIFY_CONTROLLER_DATA (1)
|
||||||
|
+
|
||||||
|
+typedef enum drive_feature_support_status {
|
||||||
|
+ /* Drive feature is supported. */
|
||||||
|
+ DRIVE_FEAT_SUP_ST = 0,
|
||||||
|
+ /* Drive feature is not supported. */
|
||||||
|
+ DRIVE_FEAT_NOT_SUP_ST,
|
||||||
|
+ /* Drive feature support check failed. */
|
||||||
|
+ DRIVE_FEAT_CHECK_FAILED_ST
|
||||||
|
+} drive_feat_sup_st;
|
||||||
|
+
|
||||||
|
+/* TCG Storage Opal SSC 2.01 chapter 3.1.1.3 */
|
||||||
|
+typedef struct opal_locking_feature {
|
||||||
|
+ /* feature header */
|
||||||
|
+ __u16 feature_code;
|
||||||
|
+ __u8 reserved : 4;
|
||||||
|
+ __u8 version : 4;
|
||||||
|
+ __u8 description_length;
|
||||||
|
+ /* feature description */
|
||||||
|
+ __u8 locking_supported : 1;
|
||||||
|
+ __u8 locking_enabled : 1;
|
||||||
|
+ __u8 locked : 1;
|
||||||
|
+ __u8 media_encryption : 1;
|
||||||
|
+ __u8 mbr_enabled : 1;
|
||||||
|
+ __u8 mbr_done : 1;
|
||||||
|
+ __u8 mbr_shadowing_not_supported : 1;
|
||||||
|
+ __u8 hw_reset_for_dor_supported : 1;
|
||||||
|
+ __u8 reserved1[11];
|
||||||
|
+} __attribute__((__packed__)) opal_locking_feature_t;
|
||||||
|
+
|
||||||
|
+/* TCG Storage Opal SSC 2.01 chapter 3.1.1.1 */
|
||||||
|
+typedef struct opal_level0_header {
|
||||||
|
+ __u32 length;
|
||||||
|
+ __u32 version;
|
||||||
|
+ __u64 reserved;
|
||||||
|
+ __u8 vendor_specific[32];
|
||||||
|
+} opal_level0_header_t;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * NVM ExpressTM Revision 1.4c, Figure 249
|
||||||
|
+ * Structure specifies only OACS filed, which is needed in the current use case.
|
||||||
|
+ */
|
||||||
|
+typedef struct nvme_identify_ctrl {
|
||||||
|
+ __u8 reserved[255];
|
||||||
|
+ __u16 oacs;
|
||||||
|
+ __u8 reserved2[3839];
|
||||||
|
+} nvme_identify_ctrl_t;
|
||||||
|
+
|
||||||
|
+/* SCSI Primary Commands - 4 (SPC-4), Table 512 */
|
||||||
|
+typedef struct supported_security_protocols {
|
||||||
|
+ __u8 reserved[6];
|
||||||
|
+ __u16 list_length;
|
||||||
|
+ __u8 list[504];
|
||||||
|
+} supported_security_protocols_t;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_opal_locking_feature_description() - get opal locking feature description.
|
||||||
|
+ * @response: response from Opal Discovery Level 0.
|
||||||
|
+ *
|
||||||
|
+ * Based on the documentation TCG Storage Opal SSC 2.01 chapter 3.1.1,
|
||||||
|
+ * a Locking feature is searched for in Opal Level 0 Discovery response.
|
||||||
|
+ *
|
||||||
|
+ * Return: if locking feature is found, pointer to struct %opal_locking_feature_t, NULL otherwise.
|
||||||
|
+ */
|
||||||
|
+static opal_locking_feature_t *get_opal_locking_feature_description(__u8 *response)
|
||||||
|
+{
|
||||||
|
+ opal_level0_header_t *response_header = (opal_level0_header_t *)response;
|
||||||
|
+ int features_length = __be32_to_cpu(response_header->length);
|
||||||
|
+ int current_position = sizeof(*response_header);
|
||||||
|
+
|
||||||
|
+ while (current_position < features_length) {
|
||||||
|
+ opal_locking_feature_t *feature;
|
||||||
|
+
|
||||||
|
+ feature = (opal_locking_feature_t *)(response + current_position);
|
||||||
|
+
|
||||||
|
+ if (__be16_to_cpu(feature->feature_code) == OPAL_LOCKING_FEATURE)
|
||||||
|
+ return feature;
|
||||||
|
+
|
||||||
|
+ current_position += feature->description_length + OPAL_DISCOVERY_FEATURE_HEADER_LEN;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * nvme_security_recv_ioctl() - nvme security receive ioctl.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @sec_protocol: security protocol.
|
||||||
|
+ * @comm_id: command id.
|
||||||
|
+ * @response_buffer: response buffer to fill out.
|
||||||
|
+ * @buf_size: response buffer size.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Based on the documentations TCG Storage Opal SSC 2.01 chapter 3.3.3 and
|
||||||
|
+ * NVM ExpressTM Revision 1.4c, chapter 5.25,
|
||||||
|
+ * read security receive command via ioctl().
|
||||||
|
+ * On success, @response_buffer is completed.
|
||||||
|
+ *
|
||||||
|
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
|
||||||
|
+ */
|
||||||
|
+static mdadm_status_t
|
||||||
|
+nvme_security_recv_ioctl(int disk_fd, __u8 sec_protocol, __u16 comm_id, void *response_buffer,
|
||||||
|
+ size_t buf_size, const int verbose)
|
||||||
|
+{
|
||||||
|
+ struct nvme_admin_cmd nvme_cmd = {0};
|
||||||
|
+ int status;
|
||||||
|
+
|
||||||
|
+ nvme_cmd.opcode = NVME_SECURITY_RECV;
|
||||||
|
+ nvme_cmd.cdw10 = sec_protocol << 24 | comm_id << 8;
|
||||||
|
+ nvme_cmd.cdw11 = buf_size;
|
||||||
|
+ nvme_cmd.data_len = buf_size;
|
||||||
|
+ nvme_cmd.addr = (__u64)response_buffer;
|
||||||
|
+
|
||||||
|
+ status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
|
||||||
|
+ if (status != 0) {
|
||||||
|
+ pr_vrb("Failed to read NVMe security receive ioctl() for device /dev/%s, status: %d\n",
|
||||||
|
+ fd2kname(disk_fd), status);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * nvme_identify_ioctl() - NVMe identify ioctl.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @response_buffer: response buffer to fill out.
|
||||||
|
+ * @buf_size: response buffer size.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Based on the documentations TCG Storage Opal SSC 2.01 chapter 3.3.3 and
|
||||||
|
+ * NVM ExpressTM Revision 1.4c, chapter 5.25,
|
||||||
|
+ * read NVMe identify via ioctl().
|
||||||
|
+ * On success, @response_buffer will be completed.
|
||||||
|
+ *
|
||||||
|
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
|
||||||
|
+ */
|
||||||
|
+static mdadm_status_t
|
||||||
|
+nvme_identify_ioctl(int disk_fd, void *response_buffer, size_t buf_size, const int verbose)
|
||||||
|
+{
|
||||||
|
+ struct nvme_admin_cmd nvme_cmd = {0};
|
||||||
|
+ int status;
|
||||||
|
+
|
||||||
|
+ nvme_cmd.opcode = NVME_IDENTIFY;
|
||||||
|
+ nvme_cmd.cdw10 = NVME_IDENTIFY_CONTROLLER_DATA;
|
||||||
|
+ nvme_cmd.data_len = buf_size;
|
||||||
|
+ nvme_cmd.addr = (__u64)response_buffer;
|
||||||
|
+
|
||||||
|
+ status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
|
||||||
|
+ if (status != 0) {
|
||||||
|
+ pr_vrb("Failed to read NVMe identify ioctl() for device /dev/%s, status: %d\n",
|
||||||
|
+ fd2kname(disk_fd), status);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * is_sec_prot_01h_supported() - check if security protocol 01h supported.
|
||||||
|
+ * @security_protocols: struct with response from disk (NVMe, SATA) describing supported
|
||||||
|
+ * security protocols.
|
||||||
|
+ *
|
||||||
|
+ * Return: true if TCG_SECP_01 found, false otherwise.
|
||||||
|
+ */
|
||||||
|
+static bool is_sec_prot_01h_supported(supported_security_protocols_t *security_protocols)
|
||||||
|
+{
|
||||||
|
+ int list_length = be16toh(security_protocols->list_length);
|
||||||
|
+ int index;
|
||||||
|
+
|
||||||
|
+ for (index = 0 ; index < list_length; index++) {
|
||||||
|
+ if (security_protocols->list[index] == TCG_SECP_01)
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * is_sec_prot_01h_supported_nvme() - check if security protocol 01h supported for given NVMe disk.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
|
||||||
|
+ * %DRIVE_FEAT_CHECK_FAILED_ST if failed to check.
|
||||||
|
+ */
|
||||||
|
+static drive_feat_sup_st is_sec_prot_01h_supported_nvme(int disk_fd, const int verbose)
|
||||||
|
+{
|
||||||
|
+ supported_security_protocols_t security_protocols = {0};
|
||||||
|
+
|
||||||
|
+ /* security_protocol: TCG_SECP_00, comm_id: not applicable */
|
||||||
|
+ if (nvme_security_recv_ioctl(disk_fd, TCG_SECP_00, 0x0, &security_protocols,
|
||||||
|
+ sizeof(security_protocols), verbose))
|
||||||
|
+ return DRIVE_FEAT_CHECK_FAILED_ST;
|
||||||
|
+
|
||||||
|
+ if (is_sec_prot_01h_supported(&security_protocols))
|
||||||
|
+ return DRIVE_FEAT_SUP_ST;
|
||||||
|
+
|
||||||
|
+ return DRIVE_FEAT_NOT_SUP_ST;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * is_nvme_sec_send_recv_supported() - check if Security Send and Security Receive is supported.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Check if "Optional Admin Command Support" bit 0 is set in NVMe identify.
|
||||||
|
+ * Bit 0 set to 1 means controller supports the Security Send and Security Receive commands.
|
||||||
|
+ *
|
||||||
|
+ * Return: %DRIVE_FEAT_SUP_ST if security send/receive supported,
|
||||||
|
+ * %DRIVE_FEAT_NOT_SUP_ST if not supported, %DRIVE_FEAT_CHECK_FAILED_ST if check failed.
|
||||||
|
+ */
|
||||||
|
+static drive_feat_sup_st is_nvme_sec_send_recv_supported(int disk_fd, const int verbose)
|
||||||
|
+{
|
||||||
|
+ nvme_identify_ctrl_t nvme_identify = {0};
|
||||||
|
+ int status = 0;
|
||||||
|
+
|
||||||
|
+ status = nvme_identify_ioctl(disk_fd, &nvme_identify, sizeof(nvme_identify), verbose);
|
||||||
|
+ if (status)
|
||||||
|
+ return DRIVE_FEAT_CHECK_FAILED_ST;
|
||||||
|
+
|
||||||
|
+ if ((__le16_to_cpu(nvme_identify.oacs) & 0x1) == 0x1)
|
||||||
|
+ return DRIVE_FEAT_SUP_ST;
|
||||||
|
+
|
||||||
|
+ return DRIVE_FEAT_NOT_SUP_ST;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_opal_encryption_information() - get Opal encryption information.
|
||||||
|
+ * @buffer: buffer with Opal Level 0 Discovery response.
|
||||||
|
+ * @information: struct to fill out, describing encryption status of disk.
|
||||||
|
+ *
|
||||||
|
+ * If Locking feature frame is in response from Opal Level 0 discovery, &encryption_information_t
|
||||||
|
+ * structure is completed with status and ability otherwise the status is set to &None.
|
||||||
|
+ * For possible encryption statuses and abilities,
|
||||||
|
+ * please refer to enums &encryption_status and &encryption_ability.
|
||||||
|
+ *
|
||||||
|
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
|
||||||
|
+ */
|
||||||
|
+static mdadm_status_t get_opal_encryption_information(__u8 *buffer,
|
||||||
|
+ encryption_information_t *information)
|
||||||
|
+{
|
||||||
|
+ opal_locking_feature_t *opal_locking_feature =
|
||||||
|
+ get_opal_locking_feature_description(buffer);
|
||||||
|
+
|
||||||
|
+ if (!opal_locking_feature)
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (opal_locking_feature->locking_supported == 1) {
|
||||||
|
+ information->ability = ENC_ABILITY_SED;
|
||||||
|
+
|
||||||
|
+ if (opal_locking_feature->locking_enabled == 0)
|
||||||
|
+ information->status = ENC_STATUS_UNENCRYPTED;
|
||||||
|
+ else if (opal_locking_feature->locked == 1)
|
||||||
|
+ information->status = ENC_STATUS_LOCKED;
|
||||||
|
+ else
|
||||||
|
+ information->status = ENC_STATUS_UNLOCKED;
|
||||||
|
+ } else {
|
||||||
|
+ information->ability = ENC_ABILITY_NONE;
|
||||||
|
+ information->status = ENC_STATUS_UNENCRYPTED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_nvme_opal_encryption_information() - get NVMe Opal encryption information.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @information: struct to fill out, describing encryption status of disk.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * In case the disk supports Opal Level 0 discovery, &encryption_information_t structure
|
||||||
|
+ * is completed with status and ability based on ioctl response,
|
||||||
|
+ * otherwise the ability is set to %ENC_ABILITY_NONE and &status to %ENC_STATUS_UNENCRYPTED.
|
||||||
|
+ * As the current use case does not need the knowledge of Opal support, if there is no support,
|
||||||
|
+ * %MDADM_STATUS_SUCCESS will be returned, with the values described above.
|
||||||
|
+ * For possible encryption statuses and abilities,
|
||||||
|
+ * please refer to enums &encryption_status and &encryption_ability.
|
||||||
|
+ *
|
||||||
|
+ * %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
|
||||||
|
+ */
|
||||||
|
+mdadm_status_t
|
||||||
|
+get_nvme_opal_encryption_information(int disk_fd, encryption_information_t *information,
|
||||||
|
+ const int verbose)
|
||||||
|
+{
|
||||||
|
+ __u8 buffer[OPAL_IO_BUFFER_LEN];
|
||||||
|
+ int sec_send_recv_supported = 0;
|
||||||
|
+ int protocol_01h_supported = 0;
|
||||||
|
+ mdadm_status_t status;
|
||||||
|
+
|
||||||
|
+ information->ability = ENC_ABILITY_NONE;
|
||||||
|
+ information->status = ENC_STATUS_UNENCRYPTED;
|
||||||
|
+
|
||||||
|
+ sec_send_recv_supported = is_nvme_sec_send_recv_supported(disk_fd, verbose);
|
||||||
|
+ if (sec_send_recv_supported == DRIVE_FEAT_CHECK_FAILED_ST)
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ /* Opal not supported */
|
||||||
|
+ if (sec_send_recv_supported == DRIVE_FEAT_NOT_SUP_ST)
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * sec_send_recv_supported determine that it should be possible to read
|
||||||
|
+ * supported sec protocols
|
||||||
|
+ */
|
||||||
|
+ protocol_01h_supported = is_sec_prot_01h_supported_nvme(disk_fd, verbose);
|
||||||
|
+ if (protocol_01h_supported == DRIVE_FEAT_CHECK_FAILED_ST)
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ /* Opal not supported */
|
||||||
|
+ if (sec_send_recv_supported == DRIVE_FEAT_SUP_ST &&
|
||||||
|
+ protocol_01h_supported == DRIVE_FEAT_NOT_SUP_ST)
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+
|
||||||
|
+ if (nvme_security_recv_ioctl(disk_fd, TCG_SECP_01, OPAL_DISCOVERY_COMID, (void *)&buffer,
|
||||||
|
+ OPAL_IO_BUFFER_LEN, verbose))
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ status = get_opal_encryption_information((__u8 *)&buffer, information);
|
||||||
|
+ if (status)
|
||||||
|
+ pr_vrb("Locking feature description not found in Level 0 discovery response. Device /dev/%s.\n",
|
||||||
|
+ fd2kname(disk_fd));
|
||||||
|
+
|
||||||
|
+ if (information->ability == ENC_ABILITY_NONE)
|
||||||
|
+ assert(information->status == ENC_STATUS_UNENCRYPTED);
|
||||||
|
+
|
||||||
|
+ return status;
|
||||||
|
+}
|
||||||
|
diff --git a/drive_encryption.h b/drive_encryption.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..82c2c624
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drive_encryption.h
|
||||||
|
@@ -0,0 +1,32 @@
|
||||||
|
+/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
+/*
|
||||||
|
+ * Read encryption information for Opal and ATA devices.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2024 Intel Corporation
|
||||||
|
+ * Author: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+typedef enum encryption_status {
|
||||||
|
+ /* The drive is not currently encrypted. */
|
||||||
|
+ ENC_STATUS_UNENCRYPTED = 0,
|
||||||
|
+ /* The drive is encrypted and the data is not accessible. */
|
||||||
|
+ ENC_STATUS_LOCKED,
|
||||||
|
+ /* The drive is encrypted but the data is accessible in unencrypted form. */
|
||||||
|
+ ENC_STATUS_UNLOCKED
|
||||||
|
+} encryption_status_t;
|
||||||
|
+
|
||||||
|
+typedef enum encryption_ability {
|
||||||
|
+ ENC_ABILITY_NONE = 0,
|
||||||
|
+ ENC_ABILITY_OTHER,
|
||||||
|
+ /* Self encrypted drive */
|
||||||
|
+ ENC_ABILITY_SED
|
||||||
|
+} encryption_ability_t;
|
||||||
|
+
|
||||||
|
+typedef struct encryption_information {
|
||||||
|
+ encryption_ability_t ability;
|
||||||
|
+ encryption_status_t status;
|
||||||
|
+} encryption_information_t;
|
||||||
|
+
|
||||||
|
+mdadm_status_t
|
||||||
|
+get_nvme_opal_encryption_information(int disk_fd, struct encryption_information *information,
|
||||||
|
+ const int verbose);
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
459
0044-Add-reading-SATA-encryption-information.patch
Normal file
459
0044-Add-reading-SATA-encryption-information.patch
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
From df38df3052c3386c0fd076e0d534b4f688b5c8a4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:51:17 +0100
|
||||||
|
Subject: [PATCH 44/66] Add reading SATA encryption information
|
||||||
|
|
||||||
|
Functionality reads information about SATA disk encryption. Technical
|
||||||
|
documentation used is given in the implementation.
|
||||||
|
|
||||||
|
The implementation is able to recognized two encryption standards for SATA
|
||||||
|
drives, OPAL and ATA security.
|
||||||
|
|
||||||
|
If the SATA drive supports OPAL, encryption status and ability are
|
||||||
|
determined based on Opal Level 0 discovery response, for ATA security,
|
||||||
|
based on ATA identify response. If SATA supports OPAL, ability is set to
|
||||||
|
"SED", for ATA security to "Other".
|
||||||
|
|
||||||
|
SED(Self-Encrypting Drive) is commonly used to describe drive which using
|
||||||
|
OPAL or Enterprise standards developed by Trusted Computing Group. Ability
|
||||||
|
"Other" is used for ATA security because we rely only on information from
|
||||||
|
ATA identify which describe the overall state of encryption.
|
||||||
|
|
||||||
|
It is allowed to mix disks with different encryption ability such as "SED"
|
||||||
|
and "Other" and it is not security gap.
|
||||||
|
|
||||||
|
Motivation for adding this functionality is to block mixing of disks in
|
||||||
|
IMSM arrays with encryption enabled and disabled. The main goal is to not
|
||||||
|
allow stealing data by rebuilding array to not encrypted drive which can be
|
||||||
|
read elsewhere.
|
||||||
|
|
||||||
|
For SATA Opal drives, libata allow_tmp parameter enabled is required, which
|
||||||
|
is necessary for Opal Security commands to work, therefore, if the
|
||||||
|
parameter is not enabled, SATA Opal disk cannot be used in case the
|
||||||
|
encryption will be checked by metadata.
|
||||||
|
|
||||||
|
Implemented functions will be used in one of the next patches. In one of
|
||||||
|
the next patches, a flag will be added to enable disabling SATA Opal
|
||||||
|
encryption checking due to allow_tpm kernel setting dependency.
|
||||||
|
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
drive_encryption.c | 318 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
drive_encryption.h | 3 +
|
||||||
|
mdadm.h | 1 +
|
||||||
|
sysfs.c | 29 +++++
|
||||||
|
4 files changed, 351 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drive_encryption.c b/drive_encryption.c
|
||||||
|
index b44585a7..d520f0c7 100644
|
||||||
|
--- a/drive_encryption.c
|
||||||
|
+++ b/drive_encryption.c
|
||||||
|
@@ -10,8 +10,12 @@
|
||||||
|
|
||||||
|
#include <asm/types.h>
|
||||||
|
#include <linux/nvme_ioctl.h>
|
||||||
|
+#include <scsi/sg.h>
|
||||||
|
+#include <scsi/scsi.h>
|
||||||
|
#include "drive_encryption.h"
|
||||||
|
|
||||||
|
+#define DEFAULT_SECTOR_SIZE (512)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Opal defines
|
||||||
|
* TCG Storage Opal SSC 2.01 chapter 3.3.3
|
||||||
|
@@ -34,6 +38,35 @@
|
||||||
|
#define NVME_OACS_BYTE_POSITION (256)
|
||||||
|
#define NVME_IDENTIFY_CONTROLLER_DATA (1)
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * ATA defines
|
||||||
|
+ * ATA/ATAPI Command Set ATA8-ACS
|
||||||
|
+ * SCSI / ATA Translation - 3 (SAT-3)
|
||||||
|
+ * SCSI Primary Commands - 4 (SPC-4)
|
||||||
|
+ * AT Attachment-8 - ATA Serial Transport (ATA8-AST)
|
||||||
|
+ * ATA Command Pass-Through
|
||||||
|
+ */
|
||||||
|
+#define ATA_IDENTIFY (0xec)
|
||||||
|
+#define ATA_TRUSTED_RECEIVE (0x5c)
|
||||||
|
+#define ATA_SECURITY_WORD_POSITION (128)
|
||||||
|
+#define HDIO_DRIVE_CMD (0x031f)
|
||||||
|
+#define ATA_TRUSTED_COMPUTING_POS (48)
|
||||||
|
+#define ATA_PASS_THROUGH_12 (0xa1)
|
||||||
|
+#define ATA_IDENTIFY_RESPONSE_LEN (512)
|
||||||
|
+#define ATA_PIO_DATA_IN (4)
|
||||||
|
+#define SG_CHECK_CONDITION (0x02)
|
||||||
|
+#define ATA_STATUS_RETURN_DESCRIPTOR (0x09)
|
||||||
|
+#define ATA_PT_INFORMATION_AVAILABLE_ASCQ (0x1d)
|
||||||
|
+#define ATA_PT_INFORMATION_AVAILABLE_ASC (0x00)
|
||||||
|
+#define ATA_INQUIRY_LENGTH (0x0c)
|
||||||
|
+#define SG_INTERFACE_ID 'S'
|
||||||
|
+#define SG_IO_TIMEOUT (60000)
|
||||||
|
+#define SG_SENSE_SIZE (32)
|
||||||
|
+#define SENSE_DATA_CURRENT_FIXED (0x70)
|
||||||
|
+#define SENSE_DATA_CURRENT_DESC (0x72)
|
||||||
|
+#define SENSE_CURRENT_RES_DESC_POS (8)
|
||||||
|
+#define SG_DRIVER_SENSE (0x08)
|
||||||
|
+
|
||||||
|
typedef enum drive_feature_support_status {
|
||||||
|
/* Drive feature is supported. */
|
||||||
|
DRIVE_FEAT_SUP_ST = 0,
|
||||||
|
@@ -87,6 +120,27 @@ typedef struct supported_security_protocols {
|
||||||
|
__u8 list[504];
|
||||||
|
} supported_security_protocols_t;
|
||||||
|
|
||||||
|
+/* ATA/ATAPI Command Set - 3 (ACS-3), Table 45 */
|
||||||
|
+typedef struct ata_security_status {
|
||||||
|
+ __u16 security_supported : 1;
|
||||||
|
+ __u16 security_enabled : 1;
|
||||||
|
+ __u16 security_locked : 1;
|
||||||
|
+ __u16 security_frozen : 1;
|
||||||
|
+ __u16 security_count_expired : 1;
|
||||||
|
+ __u16 enhanced_security_erase_supported : 1;
|
||||||
|
+ __u16 reserved1 : 2;
|
||||||
|
+ __u16 security_level : 1;
|
||||||
|
+ __u16 reserved2 : 7;
|
||||||
|
+} __attribute__((__packed__)) ata_security_status_t;
|
||||||
|
+
|
||||||
|
+/* ATA/ATAPI Command Set - 3 (ACS-3), Table 45 */
|
||||||
|
+typedef struct ata_trusted_computing {
|
||||||
|
+ __u16 tc_feature :1;
|
||||||
|
+ __u16 reserved : 13;
|
||||||
|
+ __u16 var1 : 1;
|
||||||
|
+ __u16 var2 : 1;
|
||||||
|
+} __attribute__((__packed__)) ata_trusted_computing_t;
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* get_opal_locking_feature_description() - get opal locking feature description.
|
||||||
|
* @response: response from Opal Discovery Level 0.
|
||||||
|
@@ -360,3 +414,267 @@ get_nvme_opal_encryption_information(int disk_fd, encryption_information_t *info
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * ata_pass_through12_ioctl() - ata pass through12 ioctl.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @ata_command: ata command.
|
||||||
|
+ * @sec_protocol: security protocol.
|
||||||
|
+ * @comm_id: additional command id.
|
||||||
|
+ * @response_buffer: response buffer to fill out.
|
||||||
|
+ * @buf_size: response buffer size.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Based on the documentations ATA Command Pass-Through, chapter 13.2.2 and
|
||||||
|
+ * ATA Translation - 3 (SAT-3), send read ata pass through 12 command via ioctl().
|
||||||
|
+ * On success, @response_buffer will be completed.
|
||||||
|
+ *
|
||||||
|
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
|
||||||
|
+ */
|
||||||
|
+static mdadm_status_t
|
||||||
|
+ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u16 comm_id,
|
||||||
|
+ void *response_buffer, size_t buf_size, const int verbose)
|
||||||
|
+{
|
||||||
|
+ __u8 cdb[ATA_INQUIRY_LENGTH] = {0};
|
||||||
|
+ __u8 sense[SG_SENSE_SIZE] = {0};
|
||||||
|
+ __u8 *sense_desc = NULL;
|
||||||
|
+ sg_io_hdr_t sg = {0};
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * ATA Command Pass-Through, chapter 13.2.2
|
||||||
|
+ * SCSI Primary Commands - 4 (SPC-4)
|
||||||
|
+ * ATA Translation - 3 (SAT-3)
|
||||||
|
+ */
|
||||||
|
+ cdb[0] = ATA_PASS_THROUGH_12;
|
||||||
|
+ /* protocol, bits 1-4 */
|
||||||
|
+ cdb[1] = ATA_PIO_DATA_IN << 1;
|
||||||
|
+ /* Bytes: CK_COND=1, T_DIR = 1, BYTE_BLOCK = 1, Length in Sector Count = 2 */
|
||||||
|
+ cdb[2] = 0x2E;
|
||||||
|
+ cdb[3] = sec_protocol;
|
||||||
|
+ /* Sector count */
|
||||||
|
+ cdb[4] = buf_size / DEFAULT_SECTOR_SIZE;
|
||||||
|
+ cdb[6] = (comm_id) & 0xFF;
|
||||||
|
+ cdb[7] = (comm_id >> 8) & 0xFF;
|
||||||
|
+ cdb[9] = ata_command;
|
||||||
|
+
|
||||||
|
+ sg.interface_id = SG_INTERFACE_ID;
|
||||||
|
+ sg.cmd_len = sizeof(cdb);
|
||||||
|
+ sg.mx_sb_len = sizeof(sense);
|
||||||
|
+ sg.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||||
|
+ sg.dxfer_len = buf_size;
|
||||||
|
+ sg.dxferp = response_buffer;
|
||||||
|
+ sg.cmdp = cdb;
|
||||||
|
+ sg.sbp = sense;
|
||||||
|
+ sg.timeout = SG_IO_TIMEOUT;
|
||||||
|
+ sg.usr_ptr = NULL;
|
||||||
|
+
|
||||||
|
+ if (ioctl(disk_fd, SG_IO, &sg) < 0) {
|
||||||
|
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((sg.status && sg.status != SG_CHECK_CONDITION) || sg.host_status ||
|
||||||
|
+ (sg.driver_status && sg.driver_status != SG_DRIVER_SENSE)) {
|
||||||
|
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
|
||||||
|
+ pr_vrb("SG_IO error: ATA_12 Status: %d Host Status: %d, Driver Status: %d\n",
|
||||||
|
+ sg.status, sg.host_status, sg.driver_status);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* verify expected sense response code */
|
||||||
|
+ if (!(sense[0] == SENSE_DATA_CURRENT_DESC || sense[0] == SENSE_DATA_CURRENT_FIXED)) {
|
||||||
|
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sense_desc = sense + SENSE_CURRENT_RES_DESC_POS;
|
||||||
|
+ /* verify sense data current response with descriptor format */
|
||||||
|
+ if (sense[0] == SENSE_DATA_CURRENT_DESC &&
|
||||||
|
+ !(sense_desc[0] == ATA_STATUS_RETURN_DESCRIPTOR &&
|
||||||
|
+ sense_desc[1] == ATA_INQUIRY_LENGTH)) {
|
||||||
|
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
|
||||||
|
+ fd2kname(disk_fd), sense[2], sense[3]);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* verify sense data current response with fixed format */
|
||||||
|
+ if (sense[0] == SENSE_DATA_CURRENT_FIXED &&
|
||||||
|
+ !(sense[12] == ATA_PT_INFORMATION_AVAILABLE_ASC &&
|
||||||
|
+ sense[13] == ATA_PT_INFORMATION_AVAILABLE_ASCQ)) {
|
||||||
|
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
|
||||||
|
+ fd2kname(disk_fd), sense[12], sense[13]);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * is_sec_prot_01h_supported_ata() - check if security protocol 01h supported for given SATA disk.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
|
||||||
|
+ * %DRIVE_FEAT_CHECK_FAILED_ST if failed.
|
||||||
|
+ */
|
||||||
|
+static drive_feat_sup_st is_sec_prot_01h_supported_ata(int disk_fd, const int verbose)
|
||||||
|
+{
|
||||||
|
+ supported_security_protocols_t security_protocols;
|
||||||
|
+
|
||||||
|
+ mdadm_status_t result = ata_pass_through12_ioctl(disk_fd, ATA_TRUSTED_RECEIVE, TCG_SECP_00,
|
||||||
|
+ 0x0, &security_protocols,
|
||||||
|
+ sizeof(security_protocols), verbose);
|
||||||
|
+ if (result)
|
||||||
|
+ return DRIVE_FEAT_CHECK_FAILED_ST;
|
||||||
|
+
|
||||||
|
+ if (is_sec_prot_01h_supported(&security_protocols))
|
||||||
|
+ return DRIVE_FEAT_SUP_ST;
|
||||||
|
+
|
||||||
|
+ return DRIVE_FEAT_NOT_SUP_ST;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * is_ata_trusted_computing_supported() - check if ata trusted computing supported.
|
||||||
|
+ * @buffer: buffer with ATA identify response, not NULL.
|
||||||
|
+ *
|
||||||
|
+ * Return: true if trusted computing bit set, false otherwise.
|
||||||
|
+ */
|
||||||
|
+bool is_ata_trusted_computing_supported(__u16 *buffer)
|
||||||
|
+{
|
||||||
|
+ /* Added due to warnings from the compiler about a possible uninitialized variable below. */
|
||||||
|
+ assert(buffer);
|
||||||
|
+
|
||||||
|
+ __u16 security_tc_frame = __le16_to_cpu(buffer[ATA_TRUSTED_COMPUTING_POS]);
|
||||||
|
+ ata_trusted_computing_t *security_tc = (ata_trusted_computing_t *)&security_tc_frame;
|
||||||
|
+
|
||||||
|
+ if (security_tc->tc_feature == 1)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_ata_standard_security_status() - get ATA disk encryption information from ATA identify.
|
||||||
|
+ * @buffer: buffer with response from ATA identify, not NULL.
|
||||||
|
+ * @information: struct to fill out, describing encryption status of disk.
|
||||||
|
+ *
|
||||||
|
+ * The function based on the Security status frame from ATA identify,
|
||||||
|
+ * completed encryption information.
|
||||||
|
+ * For possible encryption statuses and abilities,
|
||||||
|
+ * please refer to enums &encryption_status and &encryption_ability.
|
||||||
|
+ *
|
||||||
|
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
|
||||||
|
+ */
|
||||||
|
+static mdadm_status_t get_ata_standard_security_status(__u16 *buffer,
|
||||||
|
+ struct encryption_information *information)
|
||||||
|
+{
|
||||||
|
+ /* Added due to warnings from the compiler about a possible uninitialized variable below. */
|
||||||
|
+ assert(buffer);
|
||||||
|
+
|
||||||
|
+ __u16 security_status_frame = __le16_to_cpu(buffer[ATA_SECURITY_WORD_POSITION]);
|
||||||
|
+ ata_security_status_t *security_status = (ata_security_status_t *)&security_status_frame;
|
||||||
|
+
|
||||||
|
+ if (!security_status->security_supported) {
|
||||||
|
+ information->ability = ENC_ABILITY_NONE;
|
||||||
|
+ information->status = ENC_STATUS_UNENCRYPTED;
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ information->ability = ENC_ABILITY_OTHER;
|
||||||
|
+
|
||||||
|
+ if (security_status->security_enabled == 0)
|
||||||
|
+ information->status = ENC_STATUS_UNENCRYPTED;
|
||||||
|
+ else if (security_status->security_locked == 1)
|
||||||
|
+ information->status = ENC_STATUS_LOCKED;
|
||||||
|
+ else
|
||||||
|
+ information->status = ENC_STATUS_UNLOCKED;
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * is_ata_opal() - check if SATA disk support Opal.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @buffer: buffer with ATA identify response.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
|
||||||
|
+ * %DRIVE_FEAT_CHECK_FAILED_ST if failed to check.
|
||||||
|
+ */
|
||||||
|
+static drive_feat_sup_st is_ata_opal(int disk_fd, __u16 *buffer_identify, const int verbose)
|
||||||
|
+{
|
||||||
|
+ bool tc_status = is_ata_trusted_computing_supported(buffer_identify);
|
||||||
|
+ drive_feat_sup_st tcg_sec_prot_status;
|
||||||
|
+
|
||||||
|
+ if (!tc_status)
|
||||||
|
+ return DRIVE_FEAT_NOT_SUP_ST;
|
||||||
|
+
|
||||||
|
+ tcg_sec_prot_status = is_sec_prot_01h_supported_ata(disk_fd, verbose);
|
||||||
|
+
|
||||||
|
+ if (tcg_sec_prot_status == DRIVE_FEAT_CHECK_FAILED_ST) {
|
||||||
|
+ pr_vrb("Failed to verify if security protocol 01h supported. Device /dev/%s.\n",
|
||||||
|
+ fd2kname(disk_fd));
|
||||||
|
+ return DRIVE_FEAT_CHECK_FAILED_ST;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (tc_status && tcg_sec_prot_status == DRIVE_FEAT_SUP_ST)
|
||||||
|
+ return DRIVE_FEAT_SUP_ST;
|
||||||
|
+
|
||||||
|
+ return DRIVE_FEAT_NOT_SUP_ST;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_ata_encryption_information() - get ATA disk encryption information.
|
||||||
|
+ * @disk_fd: a disk file descriptor.
|
||||||
|
+ * @information: struct to fill out, describing encryption status of disk.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * The function reads information about encryption, if the disk supports Opal,
|
||||||
|
+ * the information is completed based on Opal Level 0 discovery, otherwise,
|
||||||
|
+ * based on ATA security status frame from ATA identification response.
|
||||||
|
+ * For possible encryption statuses and abilities,
|
||||||
|
+ * please refer to enums &encryption_status and &encryption_ability.
|
||||||
|
+ *
|
||||||
|
+ * Based on the documentations ATA/ATAPI Command Set ATA8-ACS and
|
||||||
|
+ * AT Attachment-8 - ATA Serial Transport (ATA8-AST).
|
||||||
|
+ *
|
||||||
|
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
|
||||||
|
+ */
|
||||||
|
+mdadm_status_t
|
||||||
|
+get_ata_encryption_information(int disk_fd, struct encryption_information *information,
|
||||||
|
+ const int verbose)
|
||||||
|
+{
|
||||||
|
+ __u8 buffer_opal_level0_discovery[OPAL_IO_BUFFER_LEN] = {0};
|
||||||
|
+ __u16 buffer_identify[ATA_IDENTIFY_RESPONSE_LEN] = {0};
|
||||||
|
+ drive_feat_sup_st ata_opal_status;
|
||||||
|
+ mdadm_status_t status;
|
||||||
|
+
|
||||||
|
+ /* Get disk ATA identification */
|
||||||
|
+ status = ata_pass_through12_ioctl(disk_fd, ATA_IDENTIFY, 0x0, 0x0, buffer_identify,
|
||||||
|
+ sizeof(buffer_identify), verbose);
|
||||||
|
+ if (status == MDADM_STATUS_ERROR)
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (is_ata_trusted_computing_supported(buffer_identify) &&
|
||||||
|
+ !sysfs_is_libata_allow_tpm_enabled(verbose)) {
|
||||||
|
+ pr_vrb("For SATA with Trusted Computing support, required libata.tpm_enabled=1.\n");
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ata_opal_status = is_ata_opal(disk_fd, buffer_identify, verbose);
|
||||||
|
+ if (ata_opal_status == DRIVE_FEAT_CHECK_FAILED_ST)
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (ata_opal_status == DRIVE_FEAT_NOT_SUP_ST)
|
||||||
|
+ return get_ata_standard_security_status(buffer_identify, information);
|
||||||
|
+
|
||||||
|
+ /* SATA Opal */
|
||||||
|
+ status = ata_pass_through12_ioctl(disk_fd, ATA_TRUSTED_RECEIVE, TCG_SECP_01,
|
||||||
|
+ OPAL_DISCOVERY_COMID, buffer_opal_level0_discovery,
|
||||||
|
+ OPAL_IO_BUFFER_LEN, verbose);
|
||||||
|
+ if (status != MDADM_STATUS_SUCCESS)
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+
|
||||||
|
+ return get_opal_encryption_information(buffer_opal_level0_discovery, information);
|
||||||
|
+}
|
||||||
|
diff --git a/drive_encryption.h b/drive_encryption.h
|
||||||
|
index 82c2c624..77c7f10f 100644
|
||||||
|
--- a/drive_encryption.h
|
||||||
|
+++ b/drive_encryption.h
|
||||||
|
@@ -30,3 +30,6 @@ typedef struct encryption_information {
|
||||||
|
mdadm_status_t
|
||||||
|
get_nvme_opal_encryption_information(int disk_fd, struct encryption_information *information,
|
||||||
|
const int verbose);
|
||||||
|
+mdadm_status_t
|
||||||
|
+get_ata_encryption_information(int disk_fd, struct encryption_information *information,
|
||||||
|
+ const int verbose);
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index fbb161ba..52a66b9a 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -853,6 +853,7 @@ extern int restore_stripes(int *dest, unsigned long long *offsets,
|
||||||
|
int source, unsigned long long read_offset,
|
||||||
|
unsigned long long start, unsigned long long length,
|
||||||
|
char *src_buf);
|
||||||
|
+extern bool sysfs_is_libata_allow_tpm_enabled(const int verbose);
|
||||||
|
|
||||||
|
#ifndef Sendmail
|
||||||
|
#define Sendmail "/usr/lib/sendmail -t"
|
||||||
|
diff --git a/sysfs.c b/sysfs.c
|
||||||
|
index 4ded1672..20fe1e9e 100644
|
||||||
|
--- a/sysfs.c
|
||||||
|
+++ b/sysfs.c
|
||||||
|
@@ -1121,3 +1121,32 @@ void sysfsline(char *line)
|
||||||
|
sr->next = sysfs_rules;
|
||||||
|
sysfs_rules = sr;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * sysfs_is_libata_allow_tpm_enabled() - check if libata allow_tmp is enabled.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * Check if libata allow_tmp flag is set, this is required for SATA Opal Security commands to work.
|
||||||
|
+ *
|
||||||
|
+ * Return: true if allow_tpm enable, false otherwise.
|
||||||
|
+ */
|
||||||
|
+bool sysfs_is_libata_allow_tpm_enabled(const int verbose)
|
||||||
|
+{
|
||||||
|
+ const char *path = "/sys/module/libata/parameters/allow_tpm";
|
||||||
|
+ const char *expected_value = "1";
|
||||||
|
+ int fd = open(path, O_RDONLY);
|
||||||
|
+ char buf[3];
|
||||||
|
+
|
||||||
|
+ if (!is_fd_valid(fd)) {
|
||||||
|
+ pr_vrb("Failed open file descriptor to %s. Cannot check libata allow_tpm param.\n",
|
||||||
|
+ path);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sysfs_fd_get_str(fd, buf, sizeof(buf));
|
||||||
|
+ close(fd);
|
||||||
|
+
|
||||||
|
+ if (strncmp(buf, expected_value, 1) == 0)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
163
0045-Add-key-ENCRYPTION_NO_VERIFY-to-conf.patch
Normal file
163
0045-Add-key-ENCRYPTION_NO_VERIFY-to-conf.patch
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
From 336e13fc5ef43bc5b4633a9dadac5f7208e6c241 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:51:18 +0100
|
||||||
|
Subject: [PATCH 45/66] Add key ENCRYPTION_NO_VERIFY to conf
|
||||||
|
|
||||||
|
Add ENCRYPTION_NO_VERIFY config key and allow to disable checking
|
||||||
|
encryption status for given type of drives.
|
||||||
|
|
||||||
|
The key is introduced because of SATA Opal disks for which TPM commands
|
||||||
|
must be enabled in libata kernel module, (libata.allow_tpm=1), otherwise
|
||||||
|
it is impossible to verify encryption status. TPM commands are disabled by
|
||||||
|
default.
|
||||||
|
|
||||||
|
Currently the key only supports the "sata_opal" value, if necessary,
|
||||||
|
the functionality is ready to support more types of disks. This
|
||||||
|
functionality will be used in the next patches.
|
||||||
|
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
config.c | 25 ++++++++++++++++++++++++-
|
||||||
|
drive_encryption.c | 16 ++++++++++++----
|
||||||
|
mdadm.conf.5.in | 13 +++++++++++++
|
||||||
|
mdadm.h | 1 +
|
||||||
|
4 files changed, 50 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.c b/config.c
|
||||||
|
index 44f7dd2f..b46d71cb 100644
|
||||||
|
--- a/config.c
|
||||||
|
+++ b/config.c
|
||||||
|
@@ -81,7 +81,7 @@ char DefaultAltConfDir[] = CONFFILE2 ".d";
|
||||||
|
|
||||||
|
enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev,
|
||||||
|
Homehost, HomeCluster, AutoMode, Policy, PartPolicy, Sysfs,
|
||||||
|
- MonitorDelay, LTEnd };
|
||||||
|
+ MonitorDelay, EncryptionNoVerify, LTEnd };
|
||||||
|
char *keywords[] = {
|
||||||
|
[Devices] = "devices",
|
||||||
|
[Array] = "array",
|
||||||
|
@@ -96,6 +96,7 @@ char *keywords[] = {
|
||||||
|
[PartPolicy]="part-policy",
|
||||||
|
[Sysfs] = "sysfs",
|
||||||
|
[MonitorDelay] = "monitordelay",
|
||||||
|
+ [EncryptionNoVerify] = "ENCRYPTION_NO_VERIFY",
|
||||||
|
[LTEnd] = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -729,6 +730,19 @@ void monitordelayline(char *line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool sata_opal_encryption_no_verify;
|
||||||
|
+void encryption_no_verify_line(char *line)
|
||||||
|
+{
|
||||||
|
+ char *word;
|
||||||
|
+
|
||||||
|
+ for (word = dl_next(line); word != line; word = dl_next(word)) {
|
||||||
|
+ if (strcasecmp(word, "sata_opal") == 0)
|
||||||
|
+ sata_opal_encryption_no_verify = true;
|
||||||
|
+ else
|
||||||
|
+ pr_err("unrecognised word on ENCRYPTION_NO_VERIFY line: %s\n", word);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
char auto_yes[] = "yes";
|
||||||
|
char auto_no[] = "no";
|
||||||
|
char auto_homehost[] = "homehost";
|
||||||
|
@@ -913,6 +927,9 @@ void conf_file(FILE *f)
|
||||||
|
case MonitorDelay:
|
||||||
|
monitordelayline(line);
|
||||||
|
break;
|
||||||
|
+ case EncryptionNoVerify:
|
||||||
|
+ encryption_no_verify_line(line);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
pr_err("Unknown keyword %s\n", line);
|
||||||
|
}
|
||||||
|
@@ -1075,6 +1092,12 @@ int conf_get_monitor_delay(void)
|
||||||
|
return monitor_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool conf_get_sata_opal_encryption_no_verify(void)
|
||||||
|
+{
|
||||||
|
+ load_conffile();
|
||||||
|
+ return sata_opal_encryption_no_verify;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct createinfo *conf_get_create_info(void)
|
||||||
|
{
|
||||||
|
load_conffile();
|
||||||
|
diff --git a/drive_encryption.c b/drive_encryption.c
|
||||||
|
index d520f0c7..6b2bd358 100644
|
||||||
|
--- a/drive_encryption.c
|
||||||
|
+++ b/drive_encryption.c
|
||||||
|
@@ -656,10 +656,18 @@ get_ata_encryption_information(int disk_fd, struct encryption_information *infor
|
||||||
|
if (status == MDADM_STATUS_ERROR)
|
||||||
|
return MDADM_STATUS_ERROR;
|
||||||
|
|
||||||
|
- if (is_ata_trusted_computing_supported(buffer_identify) &&
|
||||||
|
- !sysfs_is_libata_allow_tpm_enabled(verbose)) {
|
||||||
|
- pr_vrb("For SATA with Trusted Computing support, required libata.tpm_enabled=1.\n");
|
||||||
|
- return MDADM_STATUS_ERROR;
|
||||||
|
+ /* Possible OPAL support, further checks require tpm_enabled.*/
|
||||||
|
+ if (is_ata_trusted_computing_supported(buffer_identify)) {
|
||||||
|
+ /* OPAL SATA encryption checking disabled. */
|
||||||
|
+ if (conf_get_sata_opal_encryption_no_verify())
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+
|
||||||
|
+ if (!sysfs_is_libata_allow_tpm_enabled(verbose)) {
|
||||||
|
+ pr_vrb("Detected SATA drive /dev/%s with Trusted Computing support.\n",
|
||||||
|
+ fd2kname(disk_fd));
|
||||||
|
+ pr_vrb("Cannot verify encryption state. Requires libata.tpm_enabled=1.\n");
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
ata_opal_status = is_ata_opal(disk_fd, buffer_identify, verbose);
|
||||||
|
diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in
|
||||||
|
index 787e51e9..afb0a296 100644
|
||||||
|
--- a/mdadm.conf.5.in
|
||||||
|
+++ b/mdadm.conf.5.in
|
||||||
|
@@ -636,6 +636,17 @@ If multiple
|
||||||
|
.B MINITORDELAY
|
||||||
|
lines are provided, only first non-zero value is considered.
|
||||||
|
|
||||||
|
+.TP
|
||||||
|
+.B ENCRYPTION_NO_VERIFY
|
||||||
|
+The
|
||||||
|
+.B ENCRYPTION_NO_VERIFY
|
||||||
|
+disables encryption verification for devices with particular encryption support detected.
|
||||||
|
+Currently, only verification of SATA OPAL encryption can be disabled.
|
||||||
|
+It does not disable ATA security encryption verification.
|
||||||
|
+Available parameter
|
||||||
|
+.I "sata_opal".
|
||||||
|
+
|
||||||
|
+
|
||||||
|
.SH FILES
|
||||||
|
|
||||||
|
.SS {CONFFILE}
|
||||||
|
@@ -744,6 +755,8 @@ SYSFS uuid=bead5eb6:31c17a27:da120ba2:7dfda40d group_thread_cnt=4
|
||||||
|
sync_speed_max=1000000
|
||||||
|
.br
|
||||||
|
MONITORDELAY 60
|
||||||
|
+.br
|
||||||
|
+ENCRYPTION_NO_VERIFY sata_opal
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR mdadm (8),
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 52a66b9a..2640b396 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1673,6 +1673,7 @@ extern char *conf_get_program(void);
|
||||||
|
extern char *conf_get_homehost(int *require_homehostp);
|
||||||
|
extern char *conf_get_homecluster(void);
|
||||||
|
extern int conf_get_monitor_delay(void);
|
||||||
|
+extern bool conf_get_sata_opal_encryption_no_verify(void);
|
||||||
|
extern char *conf_line(FILE *file);
|
||||||
|
extern char *conf_word(FILE *file, int allow_key);
|
||||||
|
extern void print_quoted(char *str);
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
217
0046-imsm-print-disk-encryption-information.patch
Normal file
217
0046-imsm-print-disk-encryption-information.patch
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
From bf62ed5d9642aa60abf4ac2d1d89f173bd66ae48 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:51:19 +0100
|
||||||
|
Subject: [PATCH 46/66] imsm: print disk encryption information
|
||||||
|
|
||||||
|
Print SATA/NVMe disk encryption information in --detail-platform.
|
||||||
|
Encryption Ability and Status will be printed for each disk.
|
||||||
|
|
||||||
|
There is one exception, Opal SATA drives encryption is not checked when
|
||||||
|
ENCRYPTION_NO_VERIFY key with "sata_opal" value is set in conf, for this
|
||||||
|
reason such drives are treated as without encryption support.
|
||||||
|
|
||||||
|
To test this feature, drives SATA/NVMe with Opal support or SATA drives
|
||||||
|
with encryption support have to be used.
|
||||||
|
|
||||||
|
Example outputs of --detail-platform:
|
||||||
|
|
||||||
|
Non Opal, encryption enabled, SATA drive:
|
||||||
|
Port0 : /dev/sdc (CVPR050600G3120LGN)
|
||||||
|
Encryption(Ability|Status): Other|Unlocked
|
||||||
|
|
||||||
|
NVMe drive without Opal support:
|
||||||
|
NVMe under VMD : /dev/nvme2n1 (PHLF737302GB1P0GGN)
|
||||||
|
Encryption(Ability|Status): None|Unencrypted
|
||||||
|
|
||||||
|
Unencrypted SATA drive with OPAL support:
|
||||||
|
|
||||||
|
- default allow_tpm, we will get an error from mdadm:
|
||||||
|
Port6 : /dev/sdi (CVTS4246015V180IGN)
|
||||||
|
mdadm: Detected SATA drive /dev/sdi with Trusted Computing support.
|
||||||
|
mdadm: Cannot verify encryption state. Requires libata.tpm_enabled=1.
|
||||||
|
mdadm: Failed to get drive encrytpion information.
|
||||||
|
|
||||||
|
- default "allow_tpm" and config entry "ENCRYPTION_NO_VERIFY sata_opal":
|
||||||
|
Port6 : /dev/sdi (CVTS4246015V180IGN)
|
||||||
|
Encryption(Ability|Status): None|Unencrypted
|
||||||
|
|
||||||
|
- added "libata.allow_tpm=1" to boot parameters(requires reboot),
|
||||||
|
the status will be read correctly:
|
||||||
|
Port6 : /dev/sdi (CVTS4246015V180IGN)
|
||||||
|
Encryption(Ability|Status): SED|Unencrypted
|
||||||
|
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
drive_encryption.c | 36 ++++++++++++++++++++++++++++++++++++
|
||||||
|
drive_encryption.h | 2 ++
|
||||||
|
mdadm.conf.5.in | 3 +++
|
||||||
|
super-intel.c | 42 ++++++++++++++++++++++++++++++++++++++----
|
||||||
|
4 files changed, 79 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drive_encryption.c b/drive_encryption.c
|
||||||
|
index 6b2bd358..27da9621 100644
|
||||||
|
--- a/drive_encryption.c
|
||||||
|
+++ b/drive_encryption.c
|
||||||
|
@@ -141,6 +141,42 @@ typedef struct ata_trusted_computing {
|
||||||
|
__u16 var2 : 1;
|
||||||
|
} __attribute__((__packed__)) ata_trusted_computing_t;
|
||||||
|
|
||||||
|
+mapping_t encryption_ability_map[] = {
|
||||||
|
+ { "None", ENC_ABILITY_NONE },
|
||||||
|
+ { "Other", ENC_ABILITY_OTHER },
|
||||||
|
+ { "SED", ENC_ABILITY_SED },
|
||||||
|
+ { NULL, UnSet }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+mapping_t encryption_status_map[] = {
|
||||||
|
+ { "Unencrypted", ENC_STATUS_UNENCRYPTED },
|
||||||
|
+ { "Locked", ENC_STATUS_LOCKED },
|
||||||
|
+ { "Unlocked", ENC_STATUS_UNLOCKED },
|
||||||
|
+ { NULL, UnSet }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_encryption_ability_string() - get encryption ability name string.
|
||||||
|
+ * @ability: encryption ability enum.
|
||||||
|
+ *
|
||||||
|
+ * Return: encryption ability string.
|
||||||
|
+ */
|
||||||
|
+const char *get_encryption_ability_string(enum encryption_ability ability)
|
||||||
|
+{
|
||||||
|
+ return map_num_s(encryption_ability_map, ability);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * get_encryption_status_string() - get encryption status name string.
|
||||||
|
+ * @ability: encryption status enum.
|
||||||
|
+ *
|
||||||
|
+ * Return: encryption status string.
|
||||||
|
+ */
|
||||||
|
+const char *get_encryption_status_string(enum encryption_status status)
|
||||||
|
+{
|
||||||
|
+ return map_num_s(encryption_status_map, status);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* get_opal_locking_feature_description() - get opal locking feature description.
|
||||||
|
* @response: response from Opal Discovery Level 0.
|
||||||
|
diff --git a/drive_encryption.h b/drive_encryption.h
|
||||||
|
index 77c7f10f..0cb8ff1b 100644
|
||||||
|
--- a/drive_encryption.h
|
||||||
|
+++ b/drive_encryption.h
|
||||||
|
@@ -33,3 +33,5 @@ get_nvme_opal_encryption_information(int disk_fd, struct encryption_information
|
||||||
|
mdadm_status_t
|
||||||
|
get_ata_encryption_information(int disk_fd, struct encryption_information *information,
|
||||||
|
const int verbose);
|
||||||
|
+const char *get_encryption_ability_string(enum encryption_ability ability);
|
||||||
|
+const char *get_encryption_status_string(enum encryption_status status);
|
||||||
|
diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in
|
||||||
|
index afb0a296..14302a91 100644
|
||||||
|
--- a/mdadm.conf.5.in
|
||||||
|
+++ b/mdadm.conf.5.in
|
||||||
|
@@ -643,6 +643,9 @@ The
|
||||||
|
disables encryption verification for devices with particular encryption support detected.
|
||||||
|
Currently, only verification of SATA OPAL encryption can be disabled.
|
||||||
|
It does not disable ATA security encryption verification.
|
||||||
|
+Currently effective only for
|
||||||
|
+.I IMSM
|
||||||
|
+metadata.
|
||||||
|
Available parameter
|
||||||
|
.I "sata_opal".
|
||||||
|
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 212387ec..fbd1c11f 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
#include <scsi/sg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
+#include "drive_encryption.h"
|
||||||
|
|
||||||
|
/* MPB == Metadata Parameter Block */
|
||||||
|
#define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. "
|
||||||
|
@@ -2349,12 +2350,41 @@ static int imsm_read_serial(int fd, char *devname, __u8 *serial,
|
||||||
|
size_t serial_buf_len);
|
||||||
|
static void fd2devname(int fd, char *name);
|
||||||
|
|
||||||
|
-static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_base, int verbose)
|
||||||
|
+void print_encryption_information(int disk_fd, enum sys_dev_type hba_type)
|
||||||
|
+{
|
||||||
|
+ struct encryption_information information = {0};
|
||||||
|
+ mdadm_status_t status = MDADM_STATUS_SUCCESS;
|
||||||
|
+ const char *indent = " ";
|
||||||
|
+
|
||||||
|
+ switch (hba_type) {
|
||||||
|
+ case SYS_DEV_VMD:
|
||||||
|
+ case SYS_DEV_NVME:
|
||||||
|
+ status = get_nvme_opal_encryption_information(disk_fd, &information, 1);
|
||||||
|
+ break;
|
||||||
|
+ case SYS_DEV_SATA:
|
||||||
|
+ case SYS_DEV_SATA_VMD:
|
||||||
|
+ status = get_ata_encryption_information(disk_fd, &information, 1);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (status) {
|
||||||
|
+ pr_err("Failed to get drive encryption information.\n");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printf("%sEncryption(Ability|Status): %s|%s\n", indent,
|
||||||
|
+ get_encryption_ability_string(information.ability),
|
||||||
|
+ get_encryption_status_string(information.status));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_base, int verbose)
|
||||||
|
{
|
||||||
|
/* dump an unsorted list of devices attached to AHCI Intel storage
|
||||||
|
* controller, as well as non-connected ports
|
||||||
|
*/
|
||||||
|
- int hba_len = strlen(hba_path) + 1;
|
||||||
|
+ int hba_len = strlen(hba->path) + 1;
|
||||||
|
struct dirent *ent;
|
||||||
|
DIR *dir;
|
||||||
|
char *path = NULL;
|
||||||
|
@@ -2390,7 +2420,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
|
||||||
|
path = devt_to_devpath(makedev(major, minor), 1, NULL);
|
||||||
|
if (!path)
|
||||||
|
continue;
|
||||||
|
- if (!path_attached_to_hba(path, hba_path)) {
|
||||||
|
+ if (!path_attached_to_hba(path, hba->path)) {
|
||||||
|
free(path);
|
||||||
|
path = NULL;
|
||||||
|
continue;
|
||||||
|
@@ -2493,6 +2523,8 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
|
||||||
|
printf(" (%s)\n", buf);
|
||||||
|
else
|
||||||
|
printf(" ()\n");
|
||||||
|
+
|
||||||
|
+ print_encryption_information(fd, hba->type);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
@@ -2557,6 +2589,8 @@ static int print_nvme_info(struct sys_dev *hba)
|
||||||
|
else
|
||||||
|
printf("()\n");
|
||||||
|
|
||||||
|
+ print_encryption_information(fd, hba->type);
|
||||||
|
+
|
||||||
|
skip:
|
||||||
|
close_fd(&fd);
|
||||||
|
}
|
||||||
|
@@ -2812,7 +2846,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
|
||||||
|
hba->path, get_sys_dev_type(hba->type));
|
||||||
|
if (hba->type == SYS_DEV_SATA || hba->type == SYS_DEV_SATA_VMD) {
|
||||||
|
host_base = ahci_get_port_count(hba->path, &port_count);
|
||||||
|
- if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) {
|
||||||
|
+ if (ahci_enumerate_ports(hba, port_count, host_base, verbose)) {
|
||||||
|
if (verbose > 0)
|
||||||
|
pr_err("failed to enumerate ports on %s controller at %s.\n",
|
||||||
|
get_sys_dev_type(hba->type), hba->pci_id);
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
114
0047-imsm-drive-encryption-policy-implementation.patch
Normal file
114
0047-imsm-drive-encryption-policy-implementation.patch
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
From acb8f13be88c224eb1e01f72c1e1fda955bc80ba Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:51:20 +0100
|
||||||
|
Subject: [PATCH 47/66] imsm: drive encryption policy implementation
|
||||||
|
|
||||||
|
IMSM cares about drive encryption state. It is not allowed to mix disks
|
||||||
|
with different encryption state within one md device. This policy will
|
||||||
|
verify that attempt to use disks with different encryption states will
|
||||||
|
fail. Verification is performed for devices NVMe/SATA Opal and SATA.
|
||||||
|
|
||||||
|
There is one exception, Opal SATA drives encryption is not checked when
|
||||||
|
ENCRYPTION_NO_VERIFY key with "sata_opal" value is set in conf, for this
|
||||||
|
reason such drives are treated as without encryption support.
|
||||||
|
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
super-intel.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 73 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index fbd1c11f..1faab607 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -11291,6 +11291,78 @@ test_and_add_drive_controller_policy_imsm(const char * const type, dev_policy_t
|
||||||
|
return MDADM_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * test_and_add_drive_encryption_policy_imsm() - add disk encryption to policies list.
|
||||||
|
+ * @type: policy type to search in the list.
|
||||||
|
+ * @pols: list of currently recorded policies.
|
||||||
|
+ * @disk_fd: file descriptor of the device to check.
|
||||||
|
+ * @hba: The hba to which the drive is attached, could be NULL if verification is disabled.
|
||||||
|
+ * @verbose: verbose flag.
|
||||||
|
+ *
|
||||||
|
+ * IMSM cares about drive encryption state. It is not allowed to mix disks with different
|
||||||
|
+ * encryption state within one md device.
|
||||||
|
+ * If there is no encryption policy on pols we are free to add first one.
|
||||||
|
+ * If there is a policy then, new must be the same.
|
||||||
|
+ */
|
||||||
|
+static mdadm_status_t
|
||||||
|
+test_and_add_drive_encryption_policy_imsm(const char * const type, dev_policy_t **pols, int disk_fd,
|
||||||
|
+ struct sys_dev *hba, const int verbose)
|
||||||
|
+{
|
||||||
|
+ struct dev_policy *expected_policy = pol_find(*pols, (char *)type);
|
||||||
|
+ struct encryption_information information = {0};
|
||||||
|
+ char *encryption_state = "Unknown";
|
||||||
|
+ int status = MDADM_STATUS_SUCCESS;
|
||||||
|
+ bool encryption_checked = true;
|
||||||
|
+ char devname[PATH_MAX];
|
||||||
|
+
|
||||||
|
+ if (!hba)
|
||||||
|
+ goto check_policy;
|
||||||
|
+
|
||||||
|
+ switch (hba->type) {
|
||||||
|
+ case SYS_DEV_NVME:
|
||||||
|
+ case SYS_DEV_VMD:
|
||||||
|
+ status = get_nvme_opal_encryption_information(disk_fd, &information, verbose);
|
||||||
|
+ break;
|
||||||
|
+ case SYS_DEV_SATA:
|
||||||
|
+ case SYS_DEV_SATA_VMD:
|
||||||
|
+ status = get_ata_encryption_information(disk_fd, &information, verbose);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ encryption_checked = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (status) {
|
||||||
|
+ fd2devname(disk_fd, devname);
|
||||||
|
+ pr_vrb("Failed to read encryption information of device %s\n", devname);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (encryption_checked) {
|
||||||
|
+ if (information.status == ENC_STATUS_LOCKED) {
|
||||||
|
+ fd2devname(disk_fd, devname);
|
||||||
|
+ pr_vrb("Device %s is in Locked state, cannot use. Aborting.\n", devname);
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+ encryption_state = (char *)get_encryption_status_string(information.status);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+check_policy:
|
||||||
|
+ if (expected_policy) {
|
||||||
|
+ if (strcmp(expected_policy->value, encryption_state) == 0)
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+
|
||||||
|
+ fd2devname(disk_fd, devname);
|
||||||
|
+ pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected eariler.\n",
|
||||||
|
+ encryption_state, devname, expected_policy->value);
|
||||||
|
+ pr_vrb("Disks with different encryption status cannot be used.\n");
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pol_add(pols, (char *)type, encryption_state, "imsm");
|
||||||
|
+
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct imsm_drive_policy {
|
||||||
|
char *type;
|
||||||
|
mdadm_status_t (*test_and_add_drive_policy)(const char * const type,
|
||||||
|
@@ -11300,6 +11372,7 @@ struct imsm_drive_policy {
|
||||||
|
|
||||||
|
struct imsm_drive_policy imsm_policies[] = {
|
||||||
|
{"controller", test_and_add_drive_controller_policy_imsm},
|
||||||
|
+ {"encryption", test_and_add_drive_encryption_policy_imsm}
|
||||||
|
};
|
||||||
|
|
||||||
|
mdadm_status_t test_and_add_drive_policies_imsm(struct dev_policy **pols, int disk_fd,
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
2010
0048-mdadm-add-CHANGELOG.md.patch
Normal file
2010
0048-mdadm-add-CHANGELOG.md.patch
Normal file
File diff suppressed because it is too large
Load Diff
66
0049-mdadm-Add-MAINTAINERS.md.patch
Normal file
66
0049-mdadm-Add-MAINTAINERS.md.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
From 21d6c5d96a5a467b5877ba1d38106b3746005bcc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
Date: Tue, 26 Mar 2024 13:21:11 +0100
|
||||||
|
Subject: [PATCH 49/66] mdadm: Add MAINTAINERS.md
|
||||||
|
|
||||||
|
Describe rules maintainer should follow.
|
||||||
|
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
MAINTAINERS.md | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 44 insertions(+)
|
||||||
|
create mode 100644 MAINTAINERS.md
|
||||||
|
|
||||||
|
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..9c79ba87
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/MAINTAINERS.md
|
||||||
|
@@ -0,0 +1,44 @@
|
||||||
|
+# Maintainer tools
|
||||||
|
+
|
||||||
|
+Useful tools used in daily routines:
|
||||||
|
+- [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html)
|
||||||
|
+- [kup](https://korg.docs.kernel.org/kup.html)
|
||||||
|
+- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer)
|
||||||
|
+- [b4](https://b4.docs.kernel.org/en/latest/)
|
||||||
|
+
|
||||||
|
+# Checklist before applying patch
|
||||||
|
+
|
||||||
|
+We don't have CI testing yet, so all those steps must be performed manually:
|
||||||
|
+- Style check with [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html):
|
||||||
|
+
|
||||||
|
+ This is the current code style follows. We are not strict to all rules. It must be run
|
||||||
|
+ by **checkpatch --no-tree**, see README.md.
|
||||||
|
+
|
||||||
|
+- [Commit style](https://www.kernel.org/doc/html/v4.10/process/submitting-patches.html):
|
||||||
|
+
|
||||||
|
+ It doesn't need to be followed as strictly as is in kernel but changes should be logically
|
||||||
|
+ separated. Submitter should care at least to mention "It is used in next patches" if unused
|
||||||
|
+ externs/files are added in patch. We love: *Reported-by:*, *Suggested-by:*, *Fixes:* tags.
|
||||||
|
+
|
||||||
|
+- Compilation, ideally on various gcc versions.
|
||||||
|
+- Mdadm test suite execution.
|
||||||
|
+- Consider requesting new tests from submitter, especially for new functionalities.
|
||||||
|
+- Ensure that maintainer *sign-off* is added, before pushing.
|
||||||
|
+
|
||||||
|
+# Making a release
|
||||||
|
+
|
||||||
|
+Assuming that maintainer is certain that release is safe, following steps must be done:
|
||||||
|
+
|
||||||
|
+- Update versions strings in release commit, please refer to previous releases for examples.
|
||||||
|
+
|
||||||
|
+- Create GPG signed tag and push it to repo. Use same format as was used previously, prefixed by
|
||||||
|
+ **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**.
|
||||||
|
+
|
||||||
|
+- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer):
|
||||||
|
+
|
||||||
|
+ Adopt script to our release tag model. When ready, push signed note to repository. If it is done
|
||||||
|
+ correctly, then *(sig)* is added to the package automatically generated by kernel.org automation.
|
||||||
|
+ There is no need to upload archive manually.
|
||||||
|
+
|
||||||
|
+- Update CHANGELOG.md.
|
||||||
|
+- Write "ANNOUNCE" mail to linux-raid@kernel.org to notify community.
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
106
0050-mdadm-Add-README.md.patch
Normal file
106
0050-mdadm-Add-README.md.patch
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
From 256edaef3d43a112356762aaea4a48f021f45aec Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
Date: Tue, 26 Mar 2024 13:21:12 +0100
|
||||||
|
Subject: [PATCH 50/66] mdadm: Add README.md
|
||||||
|
|
||||||
|
Describe supported metadata types, add step-by-step patch sending
|
||||||
|
instruction, mention minimally supported kernel version and licensing.
|
||||||
|
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 83 insertions(+)
|
||||||
|
create mode 100644 README.md
|
||||||
|
|
||||||
|
diff --git a/README.md b/README.md
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..64f2ecec
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/README.md
|
||||||
|
@@ -0,0 +1,83 @@
|
||||||
|
+**mdadm** is a utility used to create and manage **software RAID** devices implemented through
|
||||||
|
+**Multiple devices driver (MD)** in kernel. It supports following RAID metadata formats:
|
||||||
|
+
|
||||||
|
+* [Linux native RAID](https://raid.wiki.kernel.org/index.php/RAID_superblock_formats):
|
||||||
|
+
|
||||||
|
+ Known as **native** or **native RAID**. First and default metadata format. Metadata management
|
||||||
|
+ is implemented in **MD driver**.
|
||||||
|
+
|
||||||
|
+* Matrix Storage Manager Support (no reference, metadata format documentation is proprietary).
|
||||||
|
+
|
||||||
|
+ Known as **IMSM**. Metadata format developed and maintained by **Intel®** as a part of **VROC**
|
||||||
|
+ solution. There are some functional differences between **native** and **imsm**. The most
|
||||||
|
+ important difference is that the metadata is managed from userspace.
|
||||||
|
+
|
||||||
|
+ **CAUTION:** **imsm** is compatible with **Intel RST**, however it is not officially supported.
|
||||||
|
+ You are using it on your own risk.
|
||||||
|
+
|
||||||
|
+* [Common RAID DDF Specification Revision](https://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf)
|
||||||
|
+
|
||||||
|
+ **IMPORTANT:** DDF is in **maintenance only** mode. There is no active development around it.
|
||||||
|
+ Please do not use it in new solutions.
|
||||||
|
+
|
||||||
|
+# How to Contribute
|
||||||
|
+
|
||||||
|
+ **mdadm** is hosted on [kernel.org](https://kernel.org/). You can access repository
|
||||||
|
+[here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git).
|
||||||
|
+
|
||||||
|
+It is maintained similarly to kernel, using *mailing list*. Patches must be send through email.
|
||||||
|
+Please familiarize with general kernel
|
||||||
|
+[submitting patches](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html)
|
||||||
|
+documentation. Formatting, tags and commit message guidelines applies to **mdadm**.
|
||||||
|
+
|
||||||
|
+## Sending patches step-by-step
|
||||||
|
+
|
||||||
|
+To maximize change of patches being taken, follow this instruction when submitting:
|
||||||
|
+
|
||||||
|
+1. Create possibly logically separated commits and generate patches:
|
||||||
|
+
|
||||||
|
+ Use ``git format-patch --cover-letter --signoff -v <nr>`` to create patches:
|
||||||
|
+ * ``--cover-letter`` can be skipped if it is only one patch;
|
||||||
|
+ * ``--signoff`` adds sign-off tag;
|
||||||
|
+ * ``-v <nr>`` indicates review revision number, sender should increment it before resending.
|
||||||
|
+
|
||||||
|
+2. Check style of every patch with kernel
|
||||||
|
+ [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script:
|
||||||
|
+
|
||||||
|
+ It is important to keep same coding style that is why in **mdadm**
|
||||||
|
+ [kernel coding style](https://www.kernel.org/doc/html/v4.10/process/coding-style.html)
|
||||||
|
+ is preferred. ``checkpath --no-tree <patch_file>`` can be used to verify patches.
|
||||||
|
+ Following checkpatch issues can be ignored:
|
||||||
|
+ - New typedefs.
|
||||||
|
+ - comparing with *True/False*.
|
||||||
|
+ - kernel *MAINTAINERS* file warning.
|
||||||
|
+ - *extern* keyword in headers.
|
||||||
|
+
|
||||||
|
+3. Send patches using ``git send-mail --to=linux-raid@vger.kernel.org <cover-letter> <patch1> <patch2> (...)``
|
||||||
|
+
|
||||||
|
+# Maintainers
|
||||||
|
+
|
||||||
|
+It is good practice to add **mdadm maintainers** to recipients for patches:
|
||||||
|
+
|
||||||
|
+- Jes Sorensen <jes@trained-monkey.org>;
|
||||||
|
+- Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>;
|
||||||
|
+
|
||||||
|
+Adding **MD maintainers** could be reasonable, especially if patches may affect MD driver:
|
||||||
|
+
|
||||||
|
+- Song Liu <song@kernel.org>;
|
||||||
|
+- Yu Kuai <yukuai3@huawei.com>;
|
||||||
|
+
|
||||||
|
+# Reviewers
|
||||||
|
+
|
||||||
|
+**mdadm** utility is not part of kernel tree, so there is no certificated *Reviewers* list. Everyone
|
||||||
|
+can comment on mailing list, last decision (and merging) belongs to maintainers.
|
||||||
|
+
|
||||||
|
+# Minimal supported kernel version
|
||||||
|
+
|
||||||
|
+We do not support kernel versions below **v3.10**. Please be aware that maintainers may remove
|
||||||
|
+workarounds and fixes for legacy issues.
|
||||||
|
+
|
||||||
|
+# License
|
||||||
|
+
|
||||||
|
+It is released under the terms of the **GNU General Public License version 2** as published
|
||||||
|
+by the **Free Software Foundation**.
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
41
0051-Create.c-fix-uclibc-build.patch
Normal file
41
0051-Create.c-fix-uclibc-build.patch
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
From 52bead95d2957437c691891fcdc49bd6afccdd49 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
||||||
|
Date: Fri, 12 Apr 2024 18:45:13 +0200
|
||||||
|
Subject: [PATCH 51/66] Create.c: fix uclibc build
|
||||||
|
|
||||||
|
Define FALLOC_FL_ZERO_RANGE if needed as FALLOC_FL_ZERO_RANGE is only
|
||||||
|
defined for aarch64 on uclibc-ng resulting in the following or1k build
|
||||||
|
failure since commit 577fd10486d8d1472a6b559066f344ac30a3a391:
|
||||||
|
|
||||||
|
Create.c: In function 'write_zeroes_fork':
|
||||||
|
Create.c:155:35: error: 'FALLOC_FL_ZERO_RANGE' undeclared (first use in this function)
|
||||||
|
155 | if (fallocate(fd, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
|
||||||
|
| ^~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- http://autobuild.buildroot.org/results/0e04bcdb591ca5642053e1f7e31384f06581e989
|
||||||
|
|
||||||
|
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Create.c | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Create.c b/Create.c
|
||||||
|
index 4397ff49..d94253b1 100644
|
||||||
|
--- a/Create.c
|
||||||
|
+++ b/Create.c
|
||||||
|
@@ -32,6 +32,10 @@
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
+#ifndef FALLOC_FL_ZERO_RANGE
|
||||||
|
+#define FALLOC_FL_ZERO_RANGE 16
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static int round_size_and_verify(unsigned long long *size, int chunk)
|
||||||
|
{
|
||||||
|
if (*size == 0)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
309
0052-mdadm-pass-struct-context-for-external-reshapes.patch
Normal file
309
0052-mdadm-pass-struct-context-for-external-reshapes.patch
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
From bdc2c56998abf76141294b04facf20217cfd1911 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:13 +0200
|
||||||
|
Subject: [PATCH 52/66] mdadm: pass struct context for external reshapes
|
||||||
|
|
||||||
|
This patch alters mutiple functions calls so the context is passed to
|
||||||
|
external reshape functions.
|
||||||
|
|
||||||
|
There are two main reasons behind it:
|
||||||
|
- reduces number of arguments passed and unifies them,
|
||||||
|
- imsm code will make use of context in incoming patches.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Assemble.c | 7 ++----
|
||||||
|
Grow.c | 68 +++++++++++++++++++++------------------------------
|
||||||
|
mdadm.c | 2 +-
|
||||||
|
mdadm.h | 11 +++------
|
||||||
|
super-intel.c | 6 ++---
|
||||||
|
5 files changed, 37 insertions(+), 57 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Assemble.c b/Assemble.c
|
||||||
|
index f6c5b99e..f5e9ab1f 100644
|
||||||
|
--- a/Assemble.c
|
||||||
|
+++ b/Assemble.c
|
||||||
|
@@ -1197,9 +1197,7 @@ static int start_array(int mdfd,
|
||||||
|
rv = sysfs_set_str(content, NULL,
|
||||||
|
"array_state", "readonly");
|
||||||
|
if (rv == 0)
|
||||||
|
- rv = Grow_continue(mdfd, st, content,
|
||||||
|
- c->backup_file, 0,
|
||||||
|
- c->freeze_reshape);
|
||||||
|
+ rv = Grow_continue(mdfd, st, content, 0, c);
|
||||||
|
} else if (c->readonly &&
|
||||||
|
sysfs_attribute_available(content, NULL,
|
||||||
|
"array_state")) {
|
||||||
|
@@ -2180,8 +2178,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
||||||
|
st->update_tail = &st->updates;
|
||||||
|
}
|
||||||
|
|
||||||
|
- err = Grow_continue(mdfd, st, content, c->backup_file,
|
||||||
|
- 0, c->freeze_reshape);
|
||||||
|
+ err = Grow_continue(mdfd, st, content, 0, c);
|
||||||
|
} else switch(content->array.level) {
|
||||||
|
case LEVEL_LINEAR:
|
||||||
|
case LEVEL_MULTIPATH:
|
||||||
|
diff --git a/Grow.c b/Grow.c
|
||||||
|
index 074f1995..f477b438 100644
|
||||||
|
--- a/Grow.c
|
||||||
|
+++ b/Grow.c
|
||||||
|
@@ -864,8 +864,7 @@ static void wait_reshape(struct mdinfo *sra)
|
||||||
|
|
||||||
|
static int reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
int level, int layout, int chunksize, int raid_disks,
|
||||||
|
- int delta_disks, char *backup_file, char *dev,
|
||||||
|
- int direction, int verbose)
|
||||||
|
+ int delta_disks, char *dev, int direction, struct context *c)
|
||||||
|
{
|
||||||
|
/* nothing extra to check in the native case */
|
||||||
|
if (!st->ss->external)
|
||||||
|
@@ -876,9 +875,8 @@ static int reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return st->ss->reshape_super(st, size, level, layout, chunksize,
|
||||||
|
- raid_disks, delta_disks, backup_file, dev,
|
||||||
|
- direction, verbose);
|
||||||
|
+ return st->ss->reshape_super(st, size, level, layout, chunksize, raid_disks,
|
||||||
|
+ delta_disks, dev, direction, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sync_metadata(struct supertype *st)
|
||||||
|
@@ -1764,9 +1762,8 @@ static int reshape_container(char *container, char *devname,
|
||||||
|
int mdfd,
|
||||||
|
struct supertype *st,
|
||||||
|
struct mdinfo *info,
|
||||||
|
- int force,
|
||||||
|
- char *backup_file, int verbose,
|
||||||
|
- int forked, int restart, int freeze_reshape);
|
||||||
|
+ struct context *c,
|
||||||
|
+ int forked, int restart);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare_external_reshape() - prepares update on external metadata if supported.
|
||||||
|
@@ -2004,9 +2001,8 @@ int Grow_reshape(char *devname, int fd,
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
|
||||||
|
- devname, APPLY_METADATA_CHANGES,
|
||||||
|
- c->verbose > 0)) {
|
||||||
|
+ if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet,
|
||||||
|
+ devname, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
rv = 1;
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
@@ -2124,10 +2120,8 @@ size_change_error:
|
||||||
|
int err = errno;
|
||||||
|
|
||||||
|
/* restore metadata */
|
||||||
|
- if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
|
||||||
|
- UnSet, NULL, devname,
|
||||||
|
- ROLLBACK_METADATA_CHANGES,
|
||||||
|
- c->verbose) == 0)
|
||||||
|
+ if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, UnSet,
|
||||||
|
+ devname, ROLLBACK_METADATA_CHANGES, c) == 0)
|
||||||
|
sync_metadata(st);
|
||||||
|
pr_err("Cannot set device size for %s: %s\n",
|
||||||
|
devname, strerror(err));
|
||||||
|
@@ -2338,8 +2332,7 @@ size_change_error:
|
||||||
|
*/
|
||||||
|
close_fd(&fd);
|
||||||
|
rv = reshape_container(container, devname, -1, st, &info,
|
||||||
|
- c->force, c->backup_file, c->verbose,
|
||||||
|
- 0, 0, 0);
|
||||||
|
+ c, 0, 0);
|
||||||
|
frozen = 0;
|
||||||
|
} else {
|
||||||
|
/* get spare devices from external metadata
|
||||||
|
@@ -2356,13 +2349,13 @@ size_change_error:
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Impose these changes on a single array. First
|
||||||
|
- * check that the metadata is OK with the change. */
|
||||||
|
+ * check that the metadata is OK with the change.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
if (reshape_super(st, 0, info.new_level,
|
||||||
|
info.new_layout, info.new_chunk,
|
||||||
|
info.array.raid_disks, info.delta_disks,
|
||||||
|
- c->backup_file, devname,
|
||||||
|
- APPLY_METADATA_CHANGES, c->verbose)) {
|
||||||
|
+ devname, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
rv = 1;
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
@@ -3668,9 +3661,8 @@ int reshape_container(char *container, char *devname,
|
||||||
|
int mdfd,
|
||||||
|
struct supertype *st,
|
||||||
|
struct mdinfo *info,
|
||||||
|
- int force,
|
||||||
|
- char *backup_file, int verbose,
|
||||||
|
- int forked, int restart, int freeze_reshape)
|
||||||
|
+ struct context *c,
|
||||||
|
+ int forked, int restart)
|
||||||
|
{
|
||||||
|
struct mdinfo *cc = NULL;
|
||||||
|
int rv = restart;
|
||||||
|
@@ -3683,8 +3675,7 @@ int reshape_container(char *container, char *devname,
|
||||||
|
reshape_super(st, 0, info->new_level,
|
||||||
|
info->new_layout, info->new_chunk,
|
||||||
|
info->array.raid_disks, info->delta_disks,
|
||||||
|
- backup_file, devname, APPLY_METADATA_CHANGES,
|
||||||
|
- verbose)) {
|
||||||
|
+ devname, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
unfreeze(st);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@@ -3695,7 +3686,7 @@ int reshape_container(char *container, char *devname,
|
||||||
|
*/
|
||||||
|
ping_monitor(container);
|
||||||
|
|
||||||
|
- if (!forked && !freeze_reshape)
|
||||||
|
+ if (!forked && !c->freeze_reshape)
|
||||||
|
if (continue_via_systemd(container, GROW_SERVICE, NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
@@ -3705,7 +3696,7 @@ int reshape_container(char *container, char *devname,
|
||||||
|
unfreeze(st);
|
||||||
|
return 1;
|
||||||
|
default: /* parent */
|
||||||
|
- if (!freeze_reshape)
|
||||||
|
+ if (!c->freeze_reshape)
|
||||||
|
printf("%s: multi-array reshape continues in background\n", Name);
|
||||||
|
return 0;
|
||||||
|
case 0: /* child */
|
||||||
|
@@ -3802,12 +3793,12 @@ int reshape_container(char *container, char *devname,
|
||||||
|
flush_mdmon(container);
|
||||||
|
|
||||||
|
rv = reshape_array(container, fd, adev, st,
|
||||||
|
- content, force, NULL, INVALID_SECTORS,
|
||||||
|
- backup_file, verbose, 1, restart,
|
||||||
|
- freeze_reshape);
|
||||||
|
+ content, c->force, NULL, INVALID_SECTORS,
|
||||||
|
+ c->backup_file, c->verbose, 1, restart,
|
||||||
|
+ c->freeze_reshape);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
- if (freeze_reshape) {
|
||||||
|
+ if (c->freeze_reshape) {
|
||||||
|
sysfs_free(cc);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
@@ -4970,8 +4961,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int Grow_continue_command(char *devname, int fd,
|
||||||
|
- char *backup_file, int verbose)
|
||||||
|
+int Grow_continue_command(char *devname, int fd, struct context *c)
|
||||||
|
{
|
||||||
|
int ret_val = 0;
|
||||||
|
struct supertype *st = NULL;
|
||||||
|
@@ -5157,7 +5147,7 @@ int Grow_continue_command(char *devname, int fd,
|
||||||
|
|
||||||
|
/* continue reshape
|
||||||
|
*/
|
||||||
|
- ret_val = Grow_continue(fd, st, content, backup_file, 1, 0);
|
||||||
|
+ ret_val = Grow_continue(fd, st, content, 1, c);
|
||||||
|
|
||||||
|
Grow_continue_command_exit:
|
||||||
|
if (cfd > -1)
|
||||||
|
@@ -5171,7 +5161,7 @@ Grow_continue_command_exit:
|
||||||
|
}
|
||||||
|
|
||||||
|
int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
|
||||||
|
- char *backup_file, int forked, int freeze_reshape)
|
||||||
|
+ int forked, struct context *c)
|
||||||
|
{
|
||||||
|
int ret_val = 2;
|
||||||
|
|
||||||
|
@@ -5187,14 +5177,12 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
|
||||||
|
st->ss->load_container(st, cfd, st->container_devnm);
|
||||||
|
close(cfd);
|
||||||
|
ret_val = reshape_container(st->container_devnm, NULL, mdfd,
|
||||||
|
- st, info, 0, backup_file, 0,
|
||||||
|
- forked, 1 | info->reshape_active,
|
||||||
|
- freeze_reshape);
|
||||||
|
+ st, info, c, forked, 1 | info->reshape_active);
|
||||||
|
} else
|
||||||
|
ret_val = reshape_array(NULL, mdfd, "array", st, info, 1,
|
||||||
|
- NULL, INVALID_SECTORS, backup_file,
|
||||||
|
+ NULL, INVALID_SECTORS, c->backup_file,
|
||||||
|
0, forked, 1 | info->reshape_active,
|
||||||
|
- freeze_reshape);
|
||||||
|
+ c->freeze_reshape);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
diff --git a/mdadm.c b/mdadm.c
|
||||||
|
index 3f191288..d18619db 100644
|
||||||
|
--- a/mdadm.c
|
||||||
|
+++ b/mdadm.c
|
||||||
|
@@ -1636,7 +1636,7 @@ int main(int argc, char *argv[])
|
||||||
|
c.delay = DEFAULT_BITMAP_DELAY;
|
||||||
|
rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
|
||||||
|
} else if (grow_continue)
|
||||||
|
- rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
|
||||||
|
+ rv = Grow_continue_command(ident.devname, mdfd, &c);
|
||||||
|
else if (s.size > 0 || s.raiddisks || s.layout_str ||
|
||||||
|
s.chunk != 0 || s.level != UnSet ||
|
||||||
|
s.data_offset != INVALID_SECTORS) {
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 2640b396..0ade4beb 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1235,9 +1235,8 @@ extern struct superswitch {
|
||||||
|
int (*reshape_super)(struct supertype *st,
|
||||||
|
unsigned long long size, int level,
|
||||||
|
int layout, int chunksize, int raid_disks,
|
||||||
|
- int delta_disks, char *backup, char *dev,
|
||||||
|
- int direction,
|
||||||
|
- int verbose); /* optional */
|
||||||
|
+ int delta_disks, char *dev, int direction,
|
||||||
|
+ struct context *c);
|
||||||
|
int (*manage_reshape)( /* optional */
|
||||||
|
int afd, struct mdinfo *sra, struct reshape *reshape,
|
||||||
|
struct supertype *st, unsigned long blocks,
|
||||||
|
@@ -1541,8 +1540,7 @@ extern int Grow_reshape(char *devname, int fd,
|
||||||
|
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
|
||||||
|
int *fdlist, int cnt, char *backup_file, int verbose);
|
||||||
|
extern int Grow_continue(int mdfd, struct supertype *st,
|
||||||
|
- struct mdinfo *info, char *backup_file,
|
||||||
|
- int forked, int freeze_reshape);
|
||||||
|
+ struct mdinfo *info, int forked, struct context *c);
|
||||||
|
extern int Grow_consistency_policy(char *devname, int fd,
|
||||||
|
struct context *c, struct shape *s);
|
||||||
|
|
||||||
|
@@ -1552,8 +1550,7 @@ extern int restore_backup(struct supertype *st,
|
||||||
|
int spares,
|
||||||
|
char **backup_filep,
|
||||||
|
int verbose);
|
||||||
|
-extern int Grow_continue_command(char *devname, int fd,
|
||||||
|
- char *backup_file, int verbose);
|
||||||
|
+extern int Grow_continue_command(char *devname, int fd, struct context *c);
|
||||||
|
|
||||||
|
extern int Assemble(struct supertype *st, char *mddev,
|
||||||
|
struct mddev_ident *ident,
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 1faab607..417da267 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -12153,10 +12153,8 @@ exit:
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imsm_reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
- int level,
|
||||||
|
- int layout, int chunksize, int raid_disks,
|
||||||
|
- int delta_disks, char *backup, char *dev,
|
||||||
|
- int direction, int verbose)
|
||||||
|
+ int level, int layout, int chunksize, int raid_disks,
|
||||||
|
+ int delta_disks, char *dev, int direction, struct context *c)
|
||||||
|
{
|
||||||
|
int ret_val = 1;
|
||||||
|
struct geo_params geo;
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
296
0053-mdadm-use-struct-context-in-reshape_super.patch
Normal file
296
0053-mdadm-use-struct-context-in-reshape_super.patch
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
From 0acda7053df653022e46fa3b7caf1f4d4ba31a66 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:14 +0200
|
||||||
|
Subject: [PATCH 53/66] mdadm: use struct context in reshape_super()
|
||||||
|
|
||||||
|
reshape_super() takes too many arguments. Change passing params in
|
||||||
|
favor of single struct.
|
||||||
|
|
||||||
|
Add devname pointer and change direction members to struct shape
|
||||||
|
and use it for reshape_super().
|
||||||
|
|
||||||
|
Create reshape_array_size() and reshape_array_non_size() to handle
|
||||||
|
reshape_super() calls.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Grow.c | 93 +++++++++++++++++++++++++++++++++++++--------------
|
||||||
|
mdadm.h | 18 +++++-----
|
||||||
|
super-intel.c | 43 +++++++++++++++---------
|
||||||
|
3 files changed, 105 insertions(+), 49 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Grow.c b/Grow.c
|
||||||
|
index f477b438..87ed9214 100644
|
||||||
|
--- a/Grow.c
|
||||||
|
+++ b/Grow.c
|
||||||
|
@@ -862,9 +862,7 @@ static void wait_reshape(struct mdinfo *sra)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
- int level, int layout, int chunksize, int raid_disks,
|
||||||
|
- int delta_disks, char *dev, int direction, struct context *c)
|
||||||
|
+static int reshape_super(struct supertype *st, struct shape *shape, struct context *c)
|
||||||
|
{
|
||||||
|
/* nothing extra to check in the native case */
|
||||||
|
if (!st->ss->external)
|
||||||
|
@@ -875,8 +873,65 @@ static int reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return st->ss->reshape_super(st, size, level, layout, chunksize, raid_disks,
|
||||||
|
- delta_disks, dev, direction, c);
|
||||||
|
+ return st->ss->reshape_super(st, shape, c);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * reshape_super_size() - Reshape array, size only.
|
||||||
|
+ *
|
||||||
|
+ * @st: supertype.
|
||||||
|
+ * @devname: device name.
|
||||||
|
+ * @size: component size.
|
||||||
|
+ * @dir metadata changes direction
|
||||||
|
+ * Returns: 0 on success, 1 otherwise.
|
||||||
|
+ *
|
||||||
|
+ * This function is solely used to change size of the volume.
|
||||||
|
+ * Setting size is not valid for container.
|
||||||
|
+ * Size is only change that can be rolled back, thus the @dir param.
|
||||||
|
+ */
|
||||||
|
+static int reshape_super_size(struct supertype *st, char *devname,
|
||||||
|
+ unsigned long long size, change_dir_t direction,
|
||||||
|
+ struct context *c)
|
||||||
|
+{
|
||||||
|
+ struct shape shape = {0};
|
||||||
|
+
|
||||||
|
+ shape.level = UnSet;
|
||||||
|
+ shape.layout = UnSet;
|
||||||
|
+ shape.delta_disks = UnSet;
|
||||||
|
+ shape.dev = devname;
|
||||||
|
+ shape.size = size;
|
||||||
|
+ shape.direction = direction;
|
||||||
|
+
|
||||||
|
+ return reshape_super(st, &shape, c);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * reshape_super_non_size() - Reshape array, non size changes.
|
||||||
|
+ *
|
||||||
|
+ * @st: supertype.
|
||||||
|
+ * @devname: device name.
|
||||||
|
+ * @info: superblock info.
|
||||||
|
+ * Returns: 0 on success, 1 otherwise.
|
||||||
|
+ *
|
||||||
|
+ * This function is used for any external array changes but size.
|
||||||
|
+ * It handles both volumes and containers.
|
||||||
|
+ * For changes other than size, rollback is not possible.
|
||||||
|
+ */
|
||||||
|
+static int reshape_super_non_size(struct supertype *st, char *devname,
|
||||||
|
+ struct mdinfo *info, struct context *c)
|
||||||
|
+{
|
||||||
|
+ struct shape shape = {0};
|
||||||
|
+ /* Size already set to zero, not updating size */
|
||||||
|
+ shape.level = info->new_level;
|
||||||
|
+ shape.layout = info->new_layout;
|
||||||
|
+ shape.chunk = info->new_chunk;
|
||||||
|
+ shape.raiddisks = info->array.raid_disks;
|
||||||
|
+ shape.delta_disks = info->delta_disks;
|
||||||
|
+ shape.dev = devname;
|
||||||
|
+ /* Rollback not possible for non size changes */
|
||||||
|
+ shape.direction = APPLY_METADATA_CHANGES;
|
||||||
|
+
|
||||||
|
+ return reshape_super(st, &shape, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sync_metadata(struct supertype *st)
|
||||||
|
@@ -1979,9 +2034,8 @@ int Grow_reshape(char *devname, int fd,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========= set size =============== */
|
||||||
|
- if (s->size > 0 &&
|
||||||
|
- (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
|
||||||
|
- unsigned long long orig_size = get_component_size(fd)/2;
|
||||||
|
+ if (s->size > 0 && (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
|
||||||
|
+ unsigned long long orig_size = get_component_size(fd) / 2;
|
||||||
|
unsigned long long min_csize;
|
||||||
|
struct mdinfo *mdi;
|
||||||
|
int raid0_takeover = 0;
|
||||||
|
@@ -2001,8 +2055,7 @@ int Grow_reshape(char *devname, int fd,
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet,
|
||||||
|
- devname, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
+ if (reshape_super_size(st, devname, s->size, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
rv = 1;
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
@@ -2120,8 +2173,8 @@ size_change_error:
|
||||||
|
int err = errno;
|
||||||
|
|
||||||
|
/* restore metadata */
|
||||||
|
- if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, UnSet,
|
||||||
|
- devname, ROLLBACK_METADATA_CHANGES, c) == 0)
|
||||||
|
+ if (reshape_super_size(st, devname, orig_size,
|
||||||
|
+ ROLLBACK_METADATA_CHANGES, c) == 0)
|
||||||
|
sync_metadata(st);
|
||||||
|
pr_err("Cannot set device size for %s: %s\n",
|
||||||
|
devname, strerror(err));
|
||||||
|
@@ -2351,11 +2404,7 @@ size_change_error:
|
||||||
|
/* Impose these changes on a single array. First
|
||||||
|
* check that the metadata is OK with the change.
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
- if (reshape_super(st, 0, info.new_level,
|
||||||
|
- info.new_layout, info.new_chunk,
|
||||||
|
- info.array.raid_disks, info.delta_disks,
|
||||||
|
- devname, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
+ if (reshape_super_non_size(st, devname, &info, c)) {
|
||||||
|
rv = 1;
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
@@ -3668,14 +3717,8 @@ int reshape_container(char *container, char *devname,
|
||||||
|
int rv = restart;
|
||||||
|
char last_devnm[32] = "";
|
||||||
|
|
||||||
|
- /* component_size is not meaningful for a container,
|
||||||
|
- * so pass '0' meaning 'no change'
|
||||||
|
- */
|
||||||
|
- if (!restart &&
|
||||||
|
- reshape_super(st, 0, info->new_level,
|
||||||
|
- info->new_layout, info->new_chunk,
|
||||||
|
- info->array.raid_disks, info->delta_disks,
|
||||||
|
- devname, APPLY_METADATA_CHANGES, c)) {
|
||||||
|
+ /* component_size is not meaningful for a container */
|
||||||
|
+ if (!restart && reshape_super_non_size(st, devname, info, c)) {
|
||||||
|
unfreeze(st);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 0ade4beb..2ff3e463 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -594,6 +594,11 @@ enum flag_mode {
|
||||||
|
FlagDefault, FlagSet, FlagClear,
|
||||||
|
};
|
||||||
|
|
||||||
|
+typedef enum {
|
||||||
|
+ ROLLBACK_METADATA_CHANGES,
|
||||||
|
+ APPLY_METADATA_CHANGES
|
||||||
|
+} change_dir_t;
|
||||||
|
+
|
||||||
|
/* structures read from config file */
|
||||||
|
/* List of mddevice names and identifiers
|
||||||
|
* Identifiers can be:
|
||||||
|
@@ -667,7 +672,9 @@ struct context {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shape {
|
||||||
|
+ char *dev;
|
||||||
|
int raiddisks;
|
||||||
|
+ int delta_disks;
|
||||||
|
int sparedisks;
|
||||||
|
int journaldisks;
|
||||||
|
int level;
|
||||||
|
@@ -682,6 +689,7 @@ struct shape {
|
||||||
|
unsigned long long size;
|
||||||
|
unsigned long long data_offset;
|
||||||
|
int consistency_policy;
|
||||||
|
+ change_dir_t direction;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* List of device names - wildcards expanded */
|
||||||
|
@@ -1229,14 +1237,8 @@ extern struct superswitch {
|
||||||
|
* initialized to indicate if reshape is being performed at the
|
||||||
|
* container or subarray level
|
||||||
|
*/
|
||||||
|
-#define APPLY_METADATA_CHANGES 1
|
||||||
|
-#define ROLLBACK_METADATA_CHANGES 0
|
||||||
|
-
|
||||||
|
- int (*reshape_super)(struct supertype *st,
|
||||||
|
- unsigned long long size, int level,
|
||||||
|
- int layout, int chunksize, int raid_disks,
|
||||||
|
- int delta_disks, char *dev, int direction,
|
||||||
|
- struct context *c);
|
||||||
|
+
|
||||||
|
+ int (*reshape_super)(struct supertype *st, struct shape *shape, struct context *c);
|
||||||
|
int (*manage_reshape)( /* optional */
|
||||||
|
int afd, struct mdinfo *sra, struct reshape *reshape,
|
||||||
|
struct supertype *st, unsigned long blocks,
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 417da267..1a8a7b12 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -12152,26 +12152,37 @@ exit:
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int imsm_reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
- int level, int layout, int chunksize, int raid_disks,
|
||||||
|
- int delta_disks, char *dev, int direction, struct context *c)
|
||||||
|
+/**
|
||||||
|
+ * shape_to_geo() - fill geo_params from shape.
|
||||||
|
+ *
|
||||||
|
+ * @shape: array details.
|
||||||
|
+ * @geo: new geometry params.
|
||||||
|
+ * Returns: 0 on success, 1 otherwise.
|
||||||
|
+ */
|
||||||
|
+static void shape_to_geo(struct shape *shape, struct geo_params *geo)
|
||||||
|
+{
|
||||||
|
+ assert(shape);
|
||||||
|
+ assert(geo);
|
||||||
|
+
|
||||||
|
+ geo->dev_name = shape->dev;
|
||||||
|
+ geo->size = shape->size;
|
||||||
|
+ geo->level = shape->level;
|
||||||
|
+ geo->layout = shape->layout;
|
||||||
|
+ geo->chunksize = shape->chunk;
|
||||||
|
+ geo->raid_disks = shape->raiddisks;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct context *c)
|
||||||
|
{
|
||||||
|
int ret_val = 1;
|
||||||
|
- struct geo_params geo;
|
||||||
|
+ struct geo_params geo = {0};
|
||||||
|
|
||||||
|
dprintf("(enter)\n");
|
||||||
|
|
||||||
|
- memset(&geo, 0, sizeof(struct geo_params));
|
||||||
|
-
|
||||||
|
- geo.dev_name = dev;
|
||||||
|
+ shape_to_geo(shape, &geo);
|
||||||
|
strcpy(geo.devnm, st->devnm);
|
||||||
|
- geo.size = size;
|
||||||
|
- geo.level = level;
|
||||||
|
- geo.layout = layout;
|
||||||
|
- geo.chunksize = chunksize;
|
||||||
|
- geo.raid_disks = raid_disks;
|
||||||
|
- if (delta_disks != UnSet)
|
||||||
|
- geo.raid_disks += delta_disks;
|
||||||
|
+ if (shape->delta_disks != UnSet)
|
||||||
|
+ geo.raid_disks += shape->delta_disks;
|
||||||
|
|
||||||
|
dprintf("for level : %i\n", geo.level);
|
||||||
|
dprintf("for raid_disks : %i\n", geo.raid_disks);
|
||||||
|
@@ -12182,7 +12193,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
int old_raid_disks = 0;
|
||||||
|
|
||||||
|
if (imsm_reshape_is_allowed_on_container(
|
||||||
|
- st, &geo, &old_raid_disks, direction)) {
|
||||||
|
+ st, &geo, &old_raid_disks, shape->direction)) {
|
||||||
|
struct imsm_update_reshape *u = NULL;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
@@ -12236,7 +12247,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
|
||||||
|
goto exit_imsm_reshape_super;
|
||||||
|
}
|
||||||
|
super->current_vol = dev->index;
|
||||||
|
- change = imsm_analyze_change(st, &geo, direction);
|
||||||
|
+ change = imsm_analyze_change(st, &geo, shape->direction);
|
||||||
|
switch (change) {
|
||||||
|
case CH_TAKEOVER:
|
||||||
|
ret_val = imsm_takeover(st, &geo);
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
184
0054-imsm-add-support-for-literal-RAID-10.patch
Normal file
184
0054-imsm-add-support-for-literal-RAID-10.patch
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
From 27550b13297adbdefe42fe4eb785b7fde1c0ed91 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:15 +0200
|
||||||
|
Subject: [PATCH 54/66] imsm: add support for literal RAID 10
|
||||||
|
|
||||||
|
As for now, IMSM supports only 4 drive RAID 1+0. This patch is first in
|
||||||
|
series to add support for literal RAID 10 (with more than 4 drives) to
|
||||||
|
imsm.
|
||||||
|
|
||||||
|
Allow setting RAID 10 as raid level for imsm arrays.
|
||||||
|
|
||||||
|
Add update_imsm_raid_level() to handle raid level updates. Set RAID10 as
|
||||||
|
default level for imsm R0 to R10 migrations. Replace magic numbers with
|
||||||
|
defined values for RAID level checks/assigns.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
super-intel.c | 67 ++++++++++++++++++++++++++++++++++++---------------
|
||||||
|
1 file changed, 48 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 1a8a7b12..a7efc8df 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -166,7 +166,8 @@ struct imsm_map {
|
||||||
|
__u8 raid_level;
|
||||||
|
#define IMSM_T_RAID0 0
|
||||||
|
#define IMSM_T_RAID1 1
|
||||||
|
-#define IMSM_T_RAID5 5 /* since metadata version 1.2.02 ? */
|
||||||
|
+#define IMSM_T_RAID5 5
|
||||||
|
+#define IMSM_T_RAID10 10
|
||||||
|
__u8 num_members; /* number of member disks */
|
||||||
|
__u8 num_domains; /* number of parity domains */
|
||||||
|
__u8 failed_disk_num; /* valid only when state is degraded */
|
||||||
|
@@ -1259,14 +1260,42 @@ static int get_imsm_disk_slot(struct imsm_map *map, const unsigned int idx)
|
||||||
|
|
||||||
|
return IMSM_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
+/**
|
||||||
|
+ * update_imsm_raid_level() - update raid level appropriately in &imsm_map.
|
||||||
|
+ * @map: &imsm_map pointer.
|
||||||
|
+ * @new_level: MD style level.
|
||||||
|
+ *
|
||||||
|
+ * For backward compatibility reasons we need to differentiate RAID10.
|
||||||
|
+ * In the past IMSM RAID10 was presented as RAID1.
|
||||||
|
+ * Keep compatibility unless it is not explicitly updated by UEFI driver.
|
||||||
|
+ *
|
||||||
|
+ * Routine needs num_members to be set and (optionally) raid_level.
|
||||||
|
+ */
|
||||||
|
+static void update_imsm_raid_level(struct imsm_map *map, int new_level)
|
||||||
|
+{
|
||||||
|
+ if (new_level != IMSM_T_RAID10) {
|
||||||
|
+ map->raid_level = new_level;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (map->num_members == 4) {
|
||||||
|
+ if (map->raid_level == IMSM_T_RAID10 || map->raid_level == IMSM_T_RAID1)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ map->raid_level = IMSM_T_RAID1;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ map->raid_level = IMSM_T_RAID10;
|
||||||
|
+}
|
||||||
|
|
||||||
|
static int get_imsm_raid_level(struct imsm_map *map)
|
||||||
|
{
|
||||||
|
- if (map->raid_level == 1) {
|
||||||
|
+ if (map->raid_level == IMSM_T_RAID1) {
|
||||||
|
if (map->num_members == 2)
|
||||||
|
- return 1;
|
||||||
|
+ return IMSM_T_RAID1;
|
||||||
|
else
|
||||||
|
- return 10;
|
||||||
|
+ return IMSM_T_RAID10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map->raid_level;
|
||||||
|
@@ -5678,7 +5707,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
|
set_pba_of_lba0(map, super->create_offset);
|
||||||
|
map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
|
||||||
|
map->failed_disk_num = ~0;
|
||||||
|
- if (info->level > 0)
|
||||||
|
+ if (info->level > IMSM_T_RAID0)
|
||||||
|
map->map_state = (info->state ? IMSM_T_STATE_NORMAL
|
||||||
|
: IMSM_T_STATE_UNINITIALIZED);
|
||||||
|
else
|
||||||
|
@@ -5686,16 +5715,15 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
|
IMSM_T_STATE_NORMAL;
|
||||||
|
map->ddf = 1;
|
||||||
|
|
||||||
|
- if (info->level == 1 && info->raid_disks > 2) {
|
||||||
|
+ if (info->level == IMSM_T_RAID1 && info->raid_disks > 2) {
|
||||||
|
free(dev);
|
||||||
|
free(dv);
|
||||||
|
- pr_err("imsm does not support more than 2 disksin a raid1 volume\n");
|
||||||
|
+ pr_err("imsm does not support more than 2 disks in a raid1 volume\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+ map->num_members = info->raid_disks;
|
||||||
|
|
||||||
|
- map->raid_level = info->level;
|
||||||
|
- if (info->level == 10)
|
||||||
|
- map->raid_level = 1;
|
||||||
|
+ update_imsm_raid_level(map, info->level);
|
||||||
|
set_num_domains(map);
|
||||||
|
|
||||||
|
size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION;
|
||||||
|
@@ -5703,7 +5731,6 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
|
size_per_member /
|
||||||
|
BLOCKS_PER_KB));
|
||||||
|
|
||||||
|
- map->num_members = info->raid_disks;
|
||||||
|
update_num_data_stripes(map, array_blocks);
|
||||||
|
for (i = 0; i < map->num_members; i++) {
|
||||||
|
/* initialized in add_to_super */
|
||||||
|
@@ -8275,7 +8302,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
|
||||||
|
info_d->data_offset = pba_of_lba0(map);
|
||||||
|
info_d->component_size = calc_component_size(map, dev);
|
||||||
|
|
||||||
|
- if (map->raid_level == 5) {
|
||||||
|
+ if (map->raid_level == IMSM_T_RAID5) {
|
||||||
|
info_d->ppl_sector = this->ppl_sector;
|
||||||
|
info_d->ppl_size = this->ppl_size;
|
||||||
|
if (this->consistency_policy == CONSISTENCY_POLICY_PPL &&
|
||||||
|
@@ -9533,7 +9560,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
|
||||||
|
}
|
||||||
|
|
||||||
|
to_state = map->map_state;
|
||||||
|
- if ((u->new_level == 5) && (map->raid_level == 0)) {
|
||||||
|
+ if ((u->new_level == IMSM_T_RAID5) && (map->raid_level == IMSM_T_RAID0)) {
|
||||||
|
map->num_members++;
|
||||||
|
/* this should not happen */
|
||||||
|
if (u->new_disks[0] < 0) {
|
||||||
|
@@ -9544,11 +9571,13 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
|
||||||
|
to_state = IMSM_T_STATE_NORMAL;
|
||||||
|
}
|
||||||
|
migrate(new_dev, super, to_state, MIGR_GEN_MIGR);
|
||||||
|
+
|
||||||
|
if (u->new_level > -1)
|
||||||
|
- map->raid_level = u->new_level;
|
||||||
|
+ update_imsm_raid_level(map, u->new_level);
|
||||||
|
+
|
||||||
|
migr_map = get_imsm_map(new_dev, MAP_1);
|
||||||
|
- if ((u->new_level == 5) &&
|
||||||
|
- (migr_map->raid_level == 0)) {
|
||||||
|
+ if ((u->new_level == IMSM_T_RAID5) &&
|
||||||
|
+ (migr_map->raid_level == IMSM_T_RAID0)) {
|
||||||
|
int ord = map->num_members - 1;
|
||||||
|
migr_map->num_members--;
|
||||||
|
if (u->new_disks[0] < 0)
|
||||||
|
@@ -9584,7 +9613,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
|
||||||
|
|
||||||
|
/* add disk
|
||||||
|
*/
|
||||||
|
- if (u->new_level != 5 || migr_map->raid_level != 0 ||
|
||||||
|
+ if (u->new_level != IMSM_T_RAID5 || migr_map->raid_level != IMSM_T_RAID0 ||
|
||||||
|
migr_map->raid_level == map->raid_level)
|
||||||
|
goto skip_disk_add;
|
||||||
|
|
||||||
|
@@ -9963,7 +9992,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
|
||||||
|
/* update map */
|
||||||
|
map->num_members /= map->num_domains;
|
||||||
|
map->map_state = IMSM_T_STATE_NORMAL;
|
||||||
|
- map->raid_level = 0;
|
||||||
|
+ update_imsm_raid_level(map, IMSM_T_RAID0);
|
||||||
|
set_num_domains(map);
|
||||||
|
update_num_data_stripes(map, imsm_dev_size(dev));
|
||||||
|
map->failed_disk_num = -1;
|
||||||
|
@@ -10007,7 +10036,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
|
||||||
|
map = get_imsm_map(dev_new, MAP_0);
|
||||||
|
|
||||||
|
map->map_state = IMSM_T_STATE_DEGRADED;
|
||||||
|
- map->raid_level = 1;
|
||||||
|
+ update_imsm_raid_level(map, IMSM_T_RAID10);
|
||||||
|
set_num_domains(map);
|
||||||
|
map->num_members = map->num_members * map->num_domains;
|
||||||
|
update_num_data_stripes(map, imsm_dev_size(dev));
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
345
0055-imsm-refactor-RAID-level-handling.patch
Normal file
345
0055-imsm-refactor-RAID-level-handling.patch
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
From 191e6ddb1388236c5c54baf5020a87c996be941f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:16 +0200
|
||||||
|
Subject: [PATCH 55/66] imsm: refactor RAID level handling
|
||||||
|
|
||||||
|
Add imsm_level_ops struct for better handling and unifying raid level
|
||||||
|
support. Add helper methods and move "orom_has_raid[...]" methods from
|
||||||
|
header to source file.
|
||||||
|
|
||||||
|
RAID 1e is not supported under Linux, remove RAID 1e associated code.
|
||||||
|
|
||||||
|
Refactor imsm_analyze_change() and is_raid_level_supported().
|
||||||
|
Remove hardcoded check for 4 drives and make devNumChange a multiplier
|
||||||
|
for RAID 10.
|
||||||
|
|
||||||
|
Refactor printing supported raid levels.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
platform-intel.c | 57 ++++++++++++++++++++++++
|
||||||
|
platform-intel.h | 32 ++++++--------
|
||||||
|
super-intel.c | 111 ++++++++++++++++++++++++++++-------------------
|
||||||
|
3 files changed, 138 insertions(+), 62 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/platform-intel.c b/platform-intel.c
|
||||||
|
index ac282bc5..40e8fb82 100644
|
||||||
|
--- a/platform-intel.c
|
||||||
|
+++ b/platform-intel.c
|
||||||
|
@@ -32,6 +32,63 @@
|
||||||
|
|
||||||
|
#define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/"
|
||||||
|
|
||||||
|
+static bool imsm_orom_has_raid0(const struct imsm_orom *orom)
|
||||||
|
+{
|
||||||
|
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imsm_orom_has_raid1(const struct imsm_orom *orom)
|
||||||
|
+{
|
||||||
|
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imsm_orom_has_raid10(const struct imsm_orom *orom)
|
||||||
|
+{
|
||||||
|
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID10);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imsm_orom_has_raid5(const struct imsm_orom *orom)
|
||||||
|
+{
|
||||||
|
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID5);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* IMSM platforms do not define how many disks are allowed for each level,
|
||||||
|
+ * but there are some global limitations we need to follow.
|
||||||
|
+ */
|
||||||
|
+static bool imsm_orom_support_raid_disks_count_raid0(const int raid_disks)
|
||||||
|
+{
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imsm_orom_support_raid_disks_count_raid1(const int raid_disks)
|
||||||
|
+{
|
||||||
|
+ if (raid_disks == 2)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imsm_orom_support_raid_disks_count_raid5(const int raid_disks)
|
||||||
|
+{
|
||||||
|
+ if (raid_disks > 2)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imsm_orom_support_raid_disks_count_raid10(const int raid_disks)
|
||||||
|
+{
|
||||||
|
+ if (raid_disks == 4)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct imsm_level_ops imsm_level_ops[] = {
|
||||||
|
+ {0, imsm_orom_has_raid0, imsm_orom_support_raid_disks_count_raid0, "raid0"},
|
||||||
|
+ {1, imsm_orom_has_raid1, imsm_orom_support_raid_disks_count_raid1, "raid1"},
|
||||||
|
+ {5, imsm_orom_has_raid5, imsm_orom_support_raid_disks_count_raid5, "raid5"},
|
||||||
|
+ {10, imsm_orom_has_raid10, imsm_orom_support_raid_disks_count_raid10, "raid10"},
|
||||||
|
+ {-1, NULL, NULL, NULL}
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static int devpath_to_ll(const char *dev_path, const char *entry,
|
||||||
|
unsigned long long *val);
|
||||||
|
|
||||||
|
diff --git a/platform-intel.h b/platform-intel.h
|
||||||
|
index 3c2bc595..dcc5aaa7 100644
|
||||||
|
--- a/platform-intel.h
|
||||||
|
+++ b/platform-intel.h
|
||||||
|
@@ -109,25 +109,21 @@ struct imsm_orom {
|
||||||
|
#define IMSM_OROM_CAPABILITIES_TPV (1 << 10)
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
-static inline int imsm_orom_has_raid0(const struct imsm_orom *orom)
|
||||||
|
-{
|
||||||
|
- return !!(orom->rlc & IMSM_OROM_RLC_RAID0);
|
||||||
|
-}
|
||||||
|
-static inline int imsm_orom_has_raid1(const struct imsm_orom *orom)
|
||||||
|
-{
|
||||||
|
- return !!(orom->rlc & IMSM_OROM_RLC_RAID1);
|
||||||
|
-}
|
||||||
|
-static inline int imsm_orom_has_raid1e(const struct imsm_orom *orom)
|
||||||
|
-{
|
||||||
|
- return !!(orom->rlc & IMSM_OROM_RLC_RAID1E);
|
||||||
|
-}
|
||||||
|
-static inline int imsm_orom_has_raid10(const struct imsm_orom *orom)
|
||||||
|
-{
|
||||||
|
- return !!(orom->rlc & IMSM_OROM_RLC_RAID10);
|
||||||
|
-}
|
||||||
|
-static inline int imsm_orom_has_raid5(const struct imsm_orom *orom)
|
||||||
|
+/* IMSM metadata requirements for each level */
|
||||||
|
+struct imsm_level_ops {
|
||||||
|
+ int level;
|
||||||
|
+ bool (*is_level_supported)(const struct imsm_orom *);
|
||||||
|
+ bool (*is_raiddisks_count_supported)(const int);
|
||||||
|
+ char *name;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+extern struct imsm_level_ops imsm_level_ops[];
|
||||||
|
+
|
||||||
|
+static inline bool imsm_rlc_has_bit(const struct imsm_orom *orom, const unsigned short bit)
|
||||||
|
{
|
||||||
|
- return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
|
||||||
|
+ if (orom->rlc & bit)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index a7efc8df..da17265d 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -2681,6 +2681,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count)
|
||||||
|
return host_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void print_imsm_level_capability(const struct imsm_orom *orom)
|
||||||
|
+{
|
||||||
|
+ int idx;
|
||||||
|
+
|
||||||
|
+ for (idx = 0; imsm_level_ops[idx].name; idx++)
|
||||||
|
+ if (imsm_level_ops[idx].is_level_supported(orom))
|
||||||
|
+ printf("%s ", imsm_level_ops[idx].name);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void print_imsm_capability(const struct imsm_orom *orom)
|
||||||
|
{
|
||||||
|
printf(" Platform : Intel(R) ");
|
||||||
|
@@ -2699,12 +2708,11 @@ static void print_imsm_capability(const struct imsm_orom *orom)
|
||||||
|
printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
|
||||||
|
orom->minor_ver, orom->hotfix_ver, orom->build);
|
||||||
|
}
|
||||||
|
- printf(" RAID Levels :%s%s%s%s%s\n",
|
||||||
|
- imsm_orom_has_raid0(orom) ? " raid0" : "",
|
||||||
|
- imsm_orom_has_raid1(orom) ? " raid1" : "",
|
||||||
|
- imsm_orom_has_raid1e(orom) ? " raid1e" : "",
|
||||||
|
- imsm_orom_has_raid10(orom) ? " raid10" : "",
|
||||||
|
- imsm_orom_has_raid5(orom) ? " raid5" : "");
|
||||||
|
+
|
||||||
|
+ printf(" RAID Levels : ");
|
||||||
|
+ print_imsm_level_capability(orom);
|
||||||
|
+ printf("\n");
|
||||||
|
+
|
||||||
|
printf(" Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||||
|
imsm_orom_has_chunk(orom, 2) ? " 2k" : "",
|
||||||
|
imsm_orom_has_chunk(orom, 4) ? " 4k" : "",
|
||||||
|
@@ -2739,12 +2747,11 @@ static void print_imsm_capability_export(const struct imsm_orom *orom)
|
||||||
|
if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
|
||||||
|
printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
|
||||||
|
orom->hotfix_ver, orom->build);
|
||||||
|
- printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n",
|
||||||
|
- imsm_orom_has_raid0(orom) ? "raid0 " : "",
|
||||||
|
- imsm_orom_has_raid1(orom) ? "raid1 " : "",
|
||||||
|
- imsm_orom_has_raid1e(orom) ? "raid1e " : "",
|
||||||
|
- imsm_orom_has_raid5(orom) ? "raid10 " : "",
|
||||||
|
- imsm_orom_has_raid10(orom) ? "raid5 " : "");
|
||||||
|
+
|
||||||
|
+ printf("IMSM_SUPPORTED_RAID_LEVELS=");
|
||||||
|
+ print_imsm_level_capability(orom);
|
||||||
|
+ printf("\n");
|
||||||
|
+
|
||||||
|
printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||||
|
imsm_orom_has_chunk(orom, 2) ? "2k " : "",
|
||||||
|
imsm_orom_has_chunk(orom, 4) ? "4k " : "",
|
||||||
|
@@ -6992,26 +6999,41 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
|
||||||
|
return free_size - reservation_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
|
||||||
|
+/**
|
||||||
|
+ * is_raid_level_supported() - check if this count of drives and level is supported by platform.
|
||||||
|
+ * @orom: hardware properties, could be NULL.
|
||||||
|
+ * @level: requested raid level.
|
||||||
|
+ * @raiddisks: requested disk count.
|
||||||
|
+ *
|
||||||
|
+ * IMSM UEFI/OROM does not provide information about supported count of raid disks
|
||||||
|
+ * for particular level. That is why it is hardcoded.
|
||||||
|
+ * It is recommended to not allow of usage other levels than supported,
|
||||||
|
+ * IMSM code is not tested against different level implementations.
|
||||||
|
+ *
|
||||||
|
+ * Return: true if supported, false otherwise.
|
||||||
|
+ */
|
||||||
|
+static bool is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
|
||||||
|
{
|
||||||
|
- if (level < 0 || level == 6 || level == 4)
|
||||||
|
- return 0;
|
||||||
|
+ int idx;
|
||||||
|
|
||||||
|
- /* if we have an orom prevent invalid raid levels */
|
||||||
|
- if (orom)
|
||||||
|
- switch (level) {
|
||||||
|
- case 0: return imsm_orom_has_raid0(orom);
|
||||||
|
- case 1:
|
||||||
|
- if (raiddisks > 2)
|
||||||
|
- return imsm_orom_has_raid1e(orom);
|
||||||
|
- return imsm_orom_has_raid1(orom) && raiddisks == 2;
|
||||||
|
- case 10: return imsm_orom_has_raid10(orom) && raiddisks == 4;
|
||||||
|
- case 5: return imsm_orom_has_raid5(orom) && raiddisks > 2;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- return 1; /* not on an Intel RAID platform so anything goes */
|
||||||
|
+ for (idx = 0; imsm_level_ops[idx].name; idx++) {
|
||||||
|
+ if (imsm_level_ops[idx].level == level)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ if (!imsm_level_ops[idx].name)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (!imsm_level_ops[idx].is_raiddisks_count_supported(raiddisks))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (!orom)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ if (imsm_level_ops[idx].is_level_supported(orom))
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -11962,18 +11984,17 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
int change = -1;
|
||||||
|
int check_devs = 0;
|
||||||
|
int chunk;
|
||||||
|
- /* number of added/removed disks in operation result */
|
||||||
|
- int devNumChange = 0;
|
||||||
|
/* imsm compatible layout value for array geometry verification */
|
||||||
|
int imsm_layout = -1;
|
||||||
|
+ int raid_disks = geo->raid_disks;
|
||||||
|
imsm_status_t rv;
|
||||||
|
|
||||||
|
getinfo_super_imsm_volume(st, &info, NULL);
|
||||||
|
- if (geo->level != info.array.level && geo->level >= 0 &&
|
||||||
|
+ if (geo->level != info.array.level && geo->level >= IMSM_T_RAID0 &&
|
||||||
|
geo->level != UnSet) {
|
||||||
|
switch (info.array.level) {
|
||||||
|
- case 0:
|
||||||
|
- if (geo->level == 5) {
|
||||||
|
+ case IMSM_T_RAID0:
|
||||||
|
+ if (geo->level == IMSM_T_RAID5) {
|
||||||
|
change = CH_MIGRATION;
|
||||||
|
if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) {
|
||||||
|
pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n");
|
||||||
|
@@ -11982,20 +12003,20 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
}
|
||||||
|
imsm_layout = geo->layout;
|
||||||
|
check_devs = 1;
|
||||||
|
- devNumChange = 1; /* parity disk added */
|
||||||
|
- } else if (geo->level == 10) {
|
||||||
|
+ raid_disks += 1; /* parity disk added */
|
||||||
|
+ } else if (geo->level == IMSM_T_RAID10) {
|
||||||
|
change = CH_TAKEOVER;
|
||||||
|
check_devs = 1;
|
||||||
|
- devNumChange = 2; /* two mirrors added */
|
||||||
|
+ raid_disks *= 2; /* mirrors added */
|
||||||
|
imsm_layout = 0x102; /* imsm supported layout */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
- case 1:
|
||||||
|
- case 10:
|
||||||
|
+ case IMSM_T_RAID1:
|
||||||
|
+ case IMSM_T_RAID10:
|
||||||
|
if (geo->level == 0) {
|
||||||
|
change = CH_TAKEOVER;
|
||||||
|
check_devs = 1;
|
||||||
|
- devNumChange = -(geo->raid_disks/2);
|
||||||
|
+ raid_disks /= 2;
|
||||||
|
imsm_layout = 0; /* imsm raid0 layout */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
@@ -12011,10 +12032,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
if (geo->layout != info.array.layout &&
|
||||||
|
(geo->layout != UnSet && geo->layout != -1)) {
|
||||||
|
change = CH_MIGRATION;
|
||||||
|
- if (info.array.layout == 0 && info.array.level == 5 &&
|
||||||
|
+ if (info.array.layout == 0 && info.array.level == IMSM_T_RAID5 &&
|
||||||
|
geo->layout == 5) {
|
||||||
|
/* reshape 5 -> 4 */
|
||||||
|
- } else if (info.array.layout == 5 && info.array.level == 5 &&
|
||||||
|
+ } else if (info.array.layout == 5 && info.array.level == IMSM_T_RAID5 &&
|
||||||
|
geo->layout == 0) {
|
||||||
|
/* reshape 4 -> 5 */
|
||||||
|
geo->layout = 0;
|
||||||
|
@@ -12033,7 +12054,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
|
||||||
|
if (geo->chunksize > 0 && geo->chunksize != UnSet &&
|
||||||
|
geo->chunksize != info.array.chunk_size) {
|
||||||
|
- if (info.array.level == 10) {
|
||||||
|
+ if (info.array.level == IMSM_T_RAID10) {
|
||||||
|
pr_err("Error. Chunk size change for RAID 10 is not supported.\n");
|
||||||
|
change = -1;
|
||||||
|
goto analyse_change_exit;
|
||||||
|
@@ -12058,14 +12079,16 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
rv = imsm_analyze_expand(st, geo, &info, direction);
|
||||||
|
if (rv != IMSM_STATUS_OK)
|
||||||
|
goto analyse_change_exit;
|
||||||
|
+ raid_disks = geo->raid_disks;
|
||||||
|
change = CH_ARRAY_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = geo->chunksize / 1024;
|
||||||
|
+
|
||||||
|
if (!validate_geometry_imsm(st,
|
||||||
|
geo->level,
|
||||||
|
imsm_layout,
|
||||||
|
- geo->raid_disks + devNumChange,
|
||||||
|
+ raid_disks,
|
||||||
|
&chunk,
|
||||||
|
geo->size, INVALID_SECTORS,
|
||||||
|
0, 0, info.consistency_policy, 1))
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
180
0056-imsm-bump-minimal-version.patch
Normal file
180
0056-imsm-bump-minimal-version.patch
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
From ec7e873ba6643a9e5e74311b00ede66a3d2e36c9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:17 +0200
|
||||||
|
Subject: [PATCH 56/66] imsm: bump minimal version
|
||||||
|
|
||||||
|
IMSM version 1.3 (called ATTRIBS) brought attributes used to define array
|
||||||
|
properties which require support in driver. The goal of this change was
|
||||||
|
to avoid changing version when adding new features.
|
||||||
|
|
||||||
|
For some reasons migration has never been completed and currently (after
|
||||||
|
10 years of implementing) IMSM can use older versions.
|
||||||
|
|
||||||
|
It is right time to finally switch it. There is no point in using old
|
||||||
|
versions, use 1.3.00 as minimal one.
|
||||||
|
|
||||||
|
Define JD_VERSION used by Windows driver.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
super-intel.c | 87 ++++++++++++++++++++++-----------------------------
|
||||||
|
1 file changed, 38 insertions(+), 49 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index da17265d..4b168add 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -32,14 +32,19 @@
|
||||||
|
/* MPB == Metadata Parameter Block */
|
||||||
|
#define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. "
|
||||||
|
#define MPB_SIG_LEN (strlen(MPB_SIGNATURE))
|
||||||
|
-#define MPB_VERSION_RAID0 "1.0.00"
|
||||||
|
-#define MPB_VERSION_RAID1 "1.1.00"
|
||||||
|
-#define MPB_VERSION_MANY_VOLUMES_PER_ARRAY "1.2.00"
|
||||||
|
-#define MPB_VERSION_3OR4_DISK_ARRAY "1.2.01"
|
||||||
|
-#define MPB_VERSION_RAID5 "1.2.02"
|
||||||
|
-#define MPB_VERSION_5OR6_DISK_ARRAY "1.2.04"
|
||||||
|
-#define MPB_VERSION_CNG "1.2.06"
|
||||||
|
+
|
||||||
|
+/* Legacy IMSM versions:
|
||||||
|
+ * MPB_VERSION_RAID0 1.0.00
|
||||||
|
+ * MPB_VERSION_RAID1 1.1.00
|
||||||
|
+ * MPB_VERSION_MANY_VOLUMES_PER_ARRAY 1.2.00
|
||||||
|
+ * MPB_VERSION_3OR4_DISK_ARRAY 1.2.01
|
||||||
|
+ * MPB_VERSION_RAID5 1.2.02
|
||||||
|
+ * MPB_VERSION_5OR6_DISK_ARRAY 1.2.04
|
||||||
|
+ * MPB_VERSION_CNG 1.2.06
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
#define MPB_VERSION_ATTRIBS "1.3.00"
|
||||||
|
+#define MPB_VERSION_ATTRIBS_JD "2.0.00"
|
||||||
|
#define MAX_SIGNATURE_LENGTH 32
|
||||||
|
#define MAX_RAID_SERIAL_LEN 16
|
||||||
|
|
||||||
|
@@ -5512,51 +5517,46 @@ static unsigned long long info_to_blocks_per_member(mdu_array_info_t *info,
|
||||||
|
return (size * 2) & ~(info_to_blocks_per_strip(info) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void imsm_write_signature(struct imsm_super *mpb)
|
||||||
|
+{
|
||||||
|
+ /* It is safer to eventually truncate version rather than left it not NULL ended */
|
||||||
|
+ snprintf((char *) mpb->sig, MAX_SIGNATURE_LENGTH, MPB_SIGNATURE MPB_VERSION_ATTRIBS);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void imsm_update_version_info(struct intel_super *super)
|
||||||
|
{
|
||||||
|
/* update the version and attributes */
|
||||||
|
struct imsm_super *mpb = super->anchor;
|
||||||
|
- char *version;
|
||||||
|
struct imsm_dev *dev;
|
||||||
|
struct imsm_map *map;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
+ mpb->attributes |= MPB_ATTRIB_CHECKSUM_VERIFY;
|
||||||
|
+
|
||||||
|
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||||
|
dev = get_imsm_dev(super, i);
|
||||||
|
map = get_imsm_map(dev, MAP_0);
|
||||||
|
+
|
||||||
|
if (__le32_to_cpu(dev->size_high) > 0)
|
||||||
|
mpb->attributes |= MPB_ATTRIB_2TB;
|
||||||
|
|
||||||
|
- /* FIXME detect when an array spans a port multiplier */
|
||||||
|
- #if 0
|
||||||
|
- mpb->attributes |= MPB_ATTRIB_PM;
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- if (mpb->num_raid_devs > 1 ||
|
||||||
|
- mpb->attributes != MPB_ATTRIB_CHECKSUM_VERIFY) {
|
||||||
|
- version = MPB_VERSION_ATTRIBS;
|
||||||
|
- switch (get_imsm_raid_level(map)) {
|
||||||
|
- case 0: mpb->attributes |= MPB_ATTRIB_RAID0; break;
|
||||||
|
- case 1: mpb->attributes |= MPB_ATTRIB_RAID1; break;
|
||||||
|
- case 10: mpb->attributes |= MPB_ATTRIB_RAID10; break;
|
||||||
|
- case 5: mpb->attributes |= MPB_ATTRIB_RAID5; break;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- if (map->num_members >= 5)
|
||||||
|
- version = MPB_VERSION_5OR6_DISK_ARRAY;
|
||||||
|
- else if (dev->status == DEV_CLONE_N_GO)
|
||||||
|
- version = MPB_VERSION_CNG;
|
||||||
|
- else if (get_imsm_raid_level(map) == 5)
|
||||||
|
- version = MPB_VERSION_RAID5;
|
||||||
|
- else if (map->num_members >= 3)
|
||||||
|
- version = MPB_VERSION_3OR4_DISK_ARRAY;
|
||||||
|
- else if (get_imsm_raid_level(map) == 1)
|
||||||
|
- version = MPB_VERSION_RAID1;
|
||||||
|
- else
|
||||||
|
- version = MPB_VERSION_RAID0;
|
||||||
|
+ switch (get_imsm_raid_level(map)) {
|
||||||
|
+ case IMSM_T_RAID0:
|
||||||
|
+ mpb->attributes |= MPB_ATTRIB_RAID0;
|
||||||
|
+ break;
|
||||||
|
+ case IMSM_T_RAID1:
|
||||||
|
+ mpb->attributes |= MPB_ATTRIB_RAID1;
|
||||||
|
+ break;
|
||||||
|
+ case IMSM_T_RAID5:
|
||||||
|
+ mpb->attributes |= MPB_ATTRIB_RAID5;
|
||||||
|
+ break;
|
||||||
|
+ case IMSM_T_RAID10:
|
||||||
|
+ mpb->attributes |= MPB_ATTRIB_RAID10;
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
- strcpy(((char *) mpb->sig) + strlen(MPB_SIGNATURE), version);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ imsm_write_signature(mpb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -5785,7 +5785,6 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
|
||||||
|
struct intel_super *super;
|
||||||
|
struct imsm_super *mpb;
|
||||||
|
size_t mpb_size;
|
||||||
|
- char *version;
|
||||||
|
|
||||||
|
if (data_offset != INVALID_SECTORS) {
|
||||||
|
pr_err("data-offset not supported by imsm\n");
|
||||||
|
@@ -5828,13 +5827,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- mpb->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
|
||||||
|
-
|
||||||
|
- version = (char *) mpb->sig;
|
||||||
|
- strcpy(version, MPB_SIGNATURE);
|
||||||
|
- version += strlen(MPB_SIGNATURE);
|
||||||
|
- strcpy(version, MPB_VERSION_RAID0);
|
||||||
|
-
|
||||||
|
+ imsm_update_version_info(super);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -6208,7 +6201,6 @@ static union {
|
||||||
|
|
||||||
|
static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
|
||||||
|
{
|
||||||
|
- struct imsm_super *mpb = super->anchor;
|
||||||
|
struct imsm_super *spare = &spare_record.anchor;
|
||||||
|
__u32 sum;
|
||||||
|
|
||||||
|
@@ -6217,14 +6209,11 @@ static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
|
||||||
|
|
||||||
|
spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super));
|
||||||
|
spare->generation_num = __cpu_to_le32(1UL);
|
||||||
|
- spare->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
|
||||||
|
spare->num_disks = 1;
|
||||||
|
spare->num_raid_devs = 0;
|
||||||
|
- spare->cache_size = mpb->cache_size;
|
||||||
|
spare->pwr_cycle_count = __cpu_to_le32(1);
|
||||||
|
|
||||||
|
- snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH,
|
||||||
|
- MPB_SIGNATURE MPB_VERSION_RAID0);
|
||||||
|
+ imsm_write_signature(spare);
|
||||||
|
|
||||||
|
spare->disk[0] = d->disk;
|
||||||
|
if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
67
0057-imsm-define-RAID_10-attribute.patch
Normal file
67
0057-imsm-define-RAID_10-attribute.patch
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
From 610fc2ee6fc09e828b14e8fa221b3f4f70fc7b2b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:18 +0200
|
||||||
|
Subject: [PATCH 57/66] imsm: define RAID_10 attribute
|
||||||
|
|
||||||
|
Add MPB_ATTRIB_RAID10_EXT attribute to support RAID 10
|
||||||
|
with more than 4 drives.
|
||||||
|
|
||||||
|
Allow more than 4 drives in imsm_orom_support_raid_disks_raid10().
|
||||||
|
|
||||||
|
This is one of last patches for introducing R10D4+ to imsm.
|
||||||
|
Only small adjustments in reshape behaviours are needed.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
platform-intel.c | 3 ++-
|
||||||
|
super-intel.c | 5 +++++
|
||||||
|
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/platform-intel.c b/platform-intel.c
|
||||||
|
index 40e8fb82..15a9fa5a 100644
|
||||||
|
--- a/platform-intel.c
|
||||||
|
+++ b/platform-intel.c
|
||||||
|
@@ -76,7 +76,8 @@ static bool imsm_orom_support_raid_disks_count_raid5(const int raid_disks)
|
||||||
|
|
||||||
|
static bool imsm_orom_support_raid_disks_count_raid10(const int raid_disks)
|
||||||
|
{
|
||||||
|
- if (raid_disks == 4)
|
||||||
|
+ /* raid_disks count must be higher than 4 and even */
|
||||||
|
+ if (raid_disks >= 4 && (raid_disks & 1) == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 4b168add..2d309316 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -62,6 +62,8 @@
|
||||||
|
#define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020)
|
||||||
|
/* supports expanded stripe sizes of 256K, 512K and 1MB */
|
||||||
|
#define MPB_ATTRIB_EXP_STRIPE_SIZE __cpu_to_le32(0x00000040)
|
||||||
|
+/* supports RAID10 with more than 4 drives */
|
||||||
|
+#define MPB_ATTRIB_RAID10_EXT __cpu_to_le32(0x00000080)
|
||||||
|
|
||||||
|
/* The OROM Support RST Caching of Volumes */
|
||||||
|
#define MPB_ATTRIB_NVM __cpu_to_le32(0x02000000)
|
||||||
|
@@ -89,6 +91,7 @@
|
||||||
|
MPB_ATTRIB_RAID10 | \
|
||||||
|
MPB_ATTRIB_RAID5 | \
|
||||||
|
MPB_ATTRIB_EXP_STRIPE_SIZE | \
|
||||||
|
+ MPB_ATTRIB_RAID10_EXT | \
|
||||||
|
MPB_ATTRIB_BBM)
|
||||||
|
|
||||||
|
/* Define attributes that are unused but not harmful */
|
||||||
|
@@ -5552,6 +5555,8 @@ static void imsm_update_version_info(struct intel_super *super)
|
||||||
|
break;
|
||||||
|
case IMSM_T_RAID10:
|
||||||
|
mpb->attributes |= MPB_ATTRIB_RAID10;
|
||||||
|
+ if (map->num_members > 4)
|
||||||
|
+ mpb->attributes |= MPB_ATTRIB_RAID10_EXT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
153
0058-imsm-simplify-imsm_check_attributes.patch
Normal file
153
0058-imsm-simplify-imsm_check_attributes.patch
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
From e0e56f4b2ed514f5049eb96b4ff8f7fdf30a4c49 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:19 +0200
|
||||||
|
Subject: [PATCH 58/66] imsm: simplify imsm_check_attributes()
|
||||||
|
|
||||||
|
imsm_check_attributes() is too complex for that it really does.
|
||||||
|
|
||||||
|
Remove repeating code and simplify the function.
|
||||||
|
Fix function calls.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
super-intel.c | 106 ++++++++------------------------------------------
|
||||||
|
1 file changed, 16 insertions(+), 90 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 2d309316..d60915e8 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -2135,91 +2135,18 @@ void convert_from_4k(struct intel_super *super)
|
||||||
|
mpb->check_sum = __gen_imsm_checksum(mpb);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*******************************************************************************
|
||||||
|
- * function: imsm_check_attributes
|
||||||
|
- * Description: Function checks if features represented by attributes flags
|
||||||
|
- * are supported by mdadm.
|
||||||
|
- * Parameters:
|
||||||
|
- * attributes - Attributes read from metadata
|
||||||
|
- * Returns:
|
||||||
|
- * 0 - passed attributes contains unsupported features flags
|
||||||
|
- * 1 - all features are supported
|
||||||
|
- ******************************************************************************/
|
||||||
|
-static int imsm_check_attributes(__u32 attributes)
|
||||||
|
+/**
|
||||||
|
+ * imsm_check_attributes() - Check if features represented by attributes flags are supported.
|
||||||
|
+ *
|
||||||
|
+ * @attributes: attributes read from metadata.
|
||||||
|
+ * Returns: true if all features are supported, false otherwise.
|
||||||
|
+ */
|
||||||
|
+static bool imsm_check_attributes(__u32 attributes)
|
||||||
|
{
|
||||||
|
- int ret_val = 1;
|
||||||
|
- __u32 not_supported = MPB_ATTRIB_SUPPORTED^0xffffffff;
|
||||||
|
-
|
||||||
|
- not_supported &= ~MPB_ATTRIB_IGNORED;
|
||||||
|
-
|
||||||
|
- not_supported &= attributes;
|
||||||
|
- if (not_supported) {
|
||||||
|
- pr_err("(IMSM): Unsupported attributes : %x\n",
|
||||||
|
- (unsigned)__le32_to_cpu(not_supported));
|
||||||
|
- if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY \n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_2TB) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_2TB\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_2TB;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_RAID0) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_RAID0\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_RAID0;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_RAID1) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_RAID1\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_RAID1;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_RAID10) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_RAID10\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_RAID10;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_RAID1E) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_RAID1E\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_RAID1E;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_RAID5) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_RAID5\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_RAID5;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_RAIDCNG) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_RAIDCNG\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_RAIDCNG;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_BBM) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_BBM\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_BBM;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY (== MPB_ATTRIB_LEGACY)\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_EXP_STRIPE_SIZE) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_EXP_STRIP_SIZE\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_EXP_STRIPE_SIZE;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_2TB_DISK) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_2TB_DISK\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_2TB_DISK;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_NEVER_USE2) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_NEVER_USE2\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_NEVER_USE2;
|
||||||
|
- }
|
||||||
|
- if (not_supported & MPB_ATTRIB_NEVER_USE) {
|
||||||
|
- dprintf("\t\tMPB_ATTRIB_NEVER_USE\n");
|
||||||
|
- not_supported ^= MPB_ATTRIB_NEVER_USE;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (not_supported)
|
||||||
|
- dprintf("(IMSM): Unknown attributes : %x\n", not_supported);
|
||||||
|
-
|
||||||
|
- ret_val = 0;
|
||||||
|
- }
|
||||||
|
+ if ((attributes & (MPB_ATTRIB_SUPPORTED | MPB_ATTRIB_IGNORED)) == attributes)
|
||||||
|
+ return true;
|
||||||
|
|
||||||
|
- return ret_val;
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map);
|
||||||
|
@@ -2247,11 +2174,10 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
|
||||||
|
creation_time = __le64_to_cpu(mpb->creation_time);
|
||||||
|
printf(" Creation Time : %.24s\n",
|
||||||
|
creation_time ? ctime(&creation_time) : "Unknown");
|
||||||
|
- printf(" Attributes : ");
|
||||||
|
- if (imsm_check_attributes(mpb->attributes))
|
||||||
|
- printf("All supported\n");
|
||||||
|
- else
|
||||||
|
- printf("not supported\n");
|
||||||
|
+
|
||||||
|
+ printf(" Attributes : %08x (%s)\n", mpb->attributes,
|
||||||
|
+ imsm_check_attributes(mpb->attributes) ? "supported" : "not supported");
|
||||||
|
+
|
||||||
|
getinfo_super_imsm(st, &info, NULL);
|
||||||
|
fname_from_uuid(&info, nbuf);
|
||||||
|
printf(" UUID : %s\n", nbuf + 5);
|
||||||
|
@@ -8182,9 +8108,9 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
|
||||||
|
int current_vol = super->current_vol;
|
||||||
|
|
||||||
|
/* do not assemble arrays when not all attributes are supported */
|
||||||
|
- if (imsm_check_attributes(mpb->attributes) == 0) {
|
||||||
|
+ if (imsm_check_attributes(mpb->attributes) == false) {
|
||||||
|
sb_errors = 1;
|
||||||
|
- pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n");
|
||||||
|
+ pr_err("Unsupported attributes in IMSM metadata. Arrays activation is blocked.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* count spare devices, not used in maps
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
168
0059-imsm-support-RAID-10-with-more-than-4-drives.patch
Normal file
168
0059-imsm-support-RAID-10-with-more-than-4-drives.patch
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
From 44463edeb303a464c4a44fcea184b267aeb53302 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Mon, 29 Apr 2024 15:07:20 +0200
|
||||||
|
Subject: [PATCH 59/66] imsm: support RAID 10 with more than 4 drives
|
||||||
|
|
||||||
|
VROC UEFI driver does not support RAID 10 with more than 4 drives.
|
||||||
|
Add user prompts if such layout is being created and for R0->R10
|
||||||
|
reshapes.
|
||||||
|
|
||||||
|
Refactor ask() function:
|
||||||
|
- simplify the code,
|
||||||
|
- remove dialog reattempts,
|
||||||
|
- do no pass '?' sign on function calls,
|
||||||
|
- highlight default option on output.
|
||||||
|
|
||||||
|
This patch completes adding support for R10D4+ to IMSM.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Create.c | 9 ++++++++-
|
||||||
|
super-intel.c | 14 ++++++++++++--
|
||||||
|
util.c | 39 +++++++++++++++++++++++++--------------
|
||||||
|
3 files changed, 45 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Create.c b/Create.c
|
||||||
|
index d94253b1..d033eb68 100644
|
||||||
|
--- a/Create.c
|
||||||
|
+++ b/Create.c
|
||||||
|
@@ -965,6 +965,13 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (st->ss == &super_imsm && s->level == 10 && s->raiddisks > 4) {
|
||||||
|
+ /* Print no matter runstop was specifed */
|
||||||
|
+ pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n");
|
||||||
|
+ pr_err("Array won't be suitable as boot device.\n");
|
||||||
|
+ warn = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (!have_container && s->level > 0 && ((maxsize-s->size)*100 > maxsize)) {
|
||||||
|
if (c->runstop != 1 || c->verbose >= 0)
|
||||||
|
pr_err("largest drive (%s) exceeds size (%lluK) by more than 1%%\n",
|
||||||
|
@@ -984,7 +991,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
|
||||||
|
|
||||||
|
if (warn) {
|
||||||
|
if (c->runstop!= 1) {
|
||||||
|
- if (!ask("Continue creating array? ")) {
|
||||||
|
+ if (!ask("Continue creating array")) {
|
||||||
|
pr_err("create aborted.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index d60915e8..2b8b6fda 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -523,6 +523,7 @@ enum imsm_reshape_type {
|
||||||
|
CH_TAKEOVER,
|
||||||
|
CH_MIGRATION,
|
||||||
|
CH_ARRAY_SIZE,
|
||||||
|
+ CH_ABORT
|
||||||
|
};
|
||||||
|
|
||||||
|
/* definition of messages passed to imsm_process_update */
|
||||||
|
@@ -11898,7 +11899,7 @@ success:
|
||||||
|
****************************************************************************/
|
||||||
|
enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
struct geo_params *geo,
|
||||||
|
- int direction)
|
||||||
|
+ int direction, struct context *c)
|
||||||
|
{
|
||||||
|
struct mdinfo info;
|
||||||
|
int change = -1;
|
||||||
|
@@ -11925,6 +11926,14 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||||
|
check_devs = 1;
|
||||||
|
raid_disks += 1; /* parity disk added */
|
||||||
|
} else if (geo->level == IMSM_T_RAID10) {
|
||||||
|
+ if (geo->level == IMSM_T_RAID10 && geo->raid_disks > 2 &&
|
||||||
|
+ !c->force) {
|
||||||
|
+ pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n");
|
||||||
|
+ pr_err("Array won't be suitable as boot device.\n");
|
||||||
|
+ pr_err("Note: You can omit this check with \"--force\"\n");
|
||||||
|
+ if (ask("Do you want to continue") < 1)
|
||||||
|
+ return CH_ABORT;
|
||||||
|
+ }
|
||||||
|
change = CH_TAKEOVER;
|
||||||
|
check_devs = 1;
|
||||||
|
raid_disks *= 2; /* mirrors added */
|
||||||
|
@@ -12219,7 +12228,7 @@ static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct
|
||||||
|
goto exit_imsm_reshape_super;
|
||||||
|
}
|
||||||
|
super->current_vol = dev->index;
|
||||||
|
- change = imsm_analyze_change(st, &geo, shape->direction);
|
||||||
|
+ change = imsm_analyze_change(st, &geo, shape->direction, c);
|
||||||
|
switch (change) {
|
||||||
|
case CH_TAKEOVER:
|
||||||
|
ret_val = imsm_takeover(st, &geo);
|
||||||
|
@@ -12262,6 +12271,7 @@ static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct
|
||||||
|
free(u);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
+ case CH_ABORT:
|
||||||
|
default:
|
||||||
|
ret_val = 1;
|
||||||
|
}
|
||||||
|
diff --git a/util.c b/util.c
|
||||||
|
index 9e837045..4fbf11c4 100644
|
||||||
|
--- a/util.c
|
||||||
|
+++ b/util.c
|
||||||
|
@@ -725,23 +725,33 @@ int stat_is_blkdev(char *devname, dev_t *rdev)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * ask() - prompt user for "yes/no" dialog.
|
||||||
|
+ * @mesg: message to be printed, without '?' sign.
|
||||||
|
+ * Returns: 1 if 'Y/y', 0 otherwise.
|
||||||
|
+ *
|
||||||
|
+ * The default value is 'N/n', thus the caps on "N" on prompt.
|
||||||
|
+ */
|
||||||
|
int ask(char *mesg)
|
||||||
|
{
|
||||||
|
- char *add = "";
|
||||||
|
- int i;
|
||||||
|
- for (i = 0; i < 5; i++) {
|
||||||
|
- char buf[100];
|
||||||
|
- fprintf(stderr, "%s%s", mesg, add);
|
||||||
|
- fflush(stderr);
|
||||||
|
- if (fgets(buf, 100, stdin)==NULL)
|
||||||
|
- return 0;
|
||||||
|
- if (buf[0]=='y' || buf[0]=='Y')
|
||||||
|
- return 1;
|
||||||
|
- if (buf[0]=='n' || buf[0]=='N')
|
||||||
|
- return 0;
|
||||||
|
- add = "(y/n) ";
|
||||||
|
+ char buf[3] = {0};
|
||||||
|
+
|
||||||
|
+ fprintf(stderr, "%s [y/N]? ", mesg);
|
||||||
|
+ fflush(stderr);
|
||||||
|
+ if (fgets(buf, 3, stdin) == NULL)
|
||||||
|
+ return 0;
|
||||||
|
+ if (strlen(buf) == 1) {
|
||||||
|
+ pr_err("assuming no.\n");
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
- pr_err("assuming 'no'\n");
|
||||||
|
+ if (buf[1] != '\n')
|
||||||
|
+ goto bad_option;
|
||||||
|
+ if (toupper(buf[0]) == 'Y')
|
||||||
|
+ return 1;
|
||||||
|
+ if (toupper(buf[0]) == 'N')
|
||||||
|
+ return 0;
|
||||||
|
+bad_option:
|
||||||
|
+ pr_err("bad option.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1868,6 +1878,7 @@ int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info)
|
||||||
|
|
||||||
|
if (st->ss->external)
|
||||||
|
return sysfs_set_array(info);
|
||||||
|
+
|
||||||
|
memset(&inf, 0, sizeof(inf));
|
||||||
|
inf.major_version = info->array.major_version;
|
||||||
|
inf.minor_version = info->array.minor_version;
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
41
0060-tests-01r5fail-enhance.patch
Normal file
41
0060-tests-01r5fail-enhance.patch
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
From d399c494c6364a6b6d0f965c08443fdc79d1e248 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiao Ni <xni@redhat.com>
|
||||||
|
Date: Thu, 18 Apr 2024 18:23:19 +0800
|
||||||
|
Subject: [PATCH 60/66] tests/01r5fail enhance
|
||||||
|
|
||||||
|
After removing dev0, the recovery starts because it already has a spare
|
||||||
|
disk. It's good to check recovery. But it's not right to check recovery
|
||||||
|
after adding dev3. Because the recovery may finish. It depends on the
|
||||||
|
recovery performance of the testing machine. If the recovery finishes,
|
||||||
|
it will fail. But dev3 is only added as a spare disk, we can't expect
|
||||||
|
there is a recovery happens.
|
||||||
|
|
||||||
|
So remove the codes about adding dev3.
|
||||||
|
|
||||||
|
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
tests/01r5fail | 6 +-----
|
||||||
|
1 file changed, 1 insertion(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tests/01r5fail b/tests/01r5fail
|
||||||
|
index 873dba58..c210d6e7 100644
|
||||||
|
--- a/tests/01r5fail
|
||||||
|
+++ b/tests/01r5fail
|
||||||
|
@@ -17,11 +17,7 @@ check wait
|
||||||
|
mdadm $md0 --fail $dev0
|
||||||
|
mdadm $md0 --remove $dev3 $dev0
|
||||||
|
check recovery
|
||||||
|
-check state _UUU
|
||||||
|
-
|
||||||
|
-mdadm $md0 -a $dev3
|
||||||
|
-check recovery
|
||||||
|
check wait
|
||||||
|
check state UUUU
|
||||||
|
|
||||||
|
-mdadm -S $md0
|
||||||
|
\ No newline at end of file
|
||||||
|
+mdadm -S $md0
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
32
0061-tests-01r5integ.broken.patch
Normal file
32
0061-tests-01r5integ.broken.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
From a20cb3872c02241e4f0f7cc26933a43bac7d1cbb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiao Ni <xni@redhat.com>
|
||||||
|
Date: Thu, 18 Apr 2024 18:23:20 +0800
|
||||||
|
Subject: [PATCH 61/66] tests/01r5integ.broken
|
||||||
|
|
||||||
|
01r5integ can be run successfully 152 times without error with
|
||||||
|
kernel 6.9.0-rc4 and mdadm - v4.3-51-g52bead95. So remove this
|
||||||
|
one broken case.
|
||||||
|
|
||||||
|
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
tests/01r5integ.broken | 7 -------
|
||||||
|
1 file changed, 7 deletions(-)
|
||||||
|
delete mode 100644 tests/01r5integ.broken
|
||||||
|
|
||||||
|
diff --git a/tests/01r5integ.broken b/tests/01r5integ.broken
|
||||||
|
deleted file mode 100644
|
||||||
|
index 20737637..00000000
|
||||||
|
--- a/tests/01r5integ.broken
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,7 +0,0 @@
|
||||||
|
-fails rarely
|
||||||
|
-
|
||||||
|
-Fails about 1 in every 30 runs with a sha mismatch error:
|
||||||
|
-
|
||||||
|
- c49ab26e1b01def7874af9b8a6d6d0c29fdfafe6 /dev/md0 does not match
|
||||||
|
- 15dc2f73262f811ada53c65e505ceec9cf025cb9 /dev/md0 with /dev/loop3
|
||||||
|
- missing
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
31
0062-tests-01raid6integ.broken-can-be-removed.patch
Normal file
31
0062-tests-01raid6integ.broken-can-be-removed.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
From 896948b14ad26f15590269dce50ac4896284dc29 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiao Ni <xni@redhat.com>
|
||||||
|
Date: Thu, 18 Apr 2024 18:23:21 +0800
|
||||||
|
Subject: [PATCH 62/66] tests/01raid6integ.broken can be removed
|
||||||
|
|
||||||
|
01raid6integ can be run successfully with kernel 6.9.0-rc3.
|
||||||
|
So remove 01raid6integ.broken.
|
||||||
|
|
||||||
|
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
tests/01raid6integ.broken | 7 -------
|
||||||
|
1 file changed, 7 deletions(-)
|
||||||
|
delete mode 100644 tests/01raid6integ.broken
|
||||||
|
|
||||||
|
diff --git a/tests/01raid6integ.broken b/tests/01raid6integ.broken
|
||||||
|
deleted file mode 100644
|
||||||
|
index 1df735f0..00000000
|
||||||
|
--- a/tests/01raid6integ.broken
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,7 +0,0 @@
|
||||||
|
-fails infrequently
|
||||||
|
-
|
||||||
|
-Fails about 1 in 5 with a sha mismatch:
|
||||||
|
-
|
||||||
|
- 8286c2bc045ae2cfe9f8b7ae3a898fa25db6926f /dev/md0 does not match
|
||||||
|
- a083a0738b58caab37fd568b91b177035ded37df /dev/md0 with /dev/loop2 and
|
||||||
|
- /dev/loop3 missing
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
38
0063-Makefile-Move-pie-to-LDFLAGS.patch
Normal file
38
0063-Makefile-Move-pie-to-LDFLAGS.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
From 893a55831e5abbcd15b171db66fa1f389fb61506 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
||||||
|
Date: Tue, 7 May 2024 19:32:16 +0200
|
||||||
|
Subject: [PATCH 63/66] Makefile: Move -pie to LDFLAGS
|
||||||
|
|
||||||
|
Move -pie from LDLIBS to LDFLAGS and make LDFLAGS configurable to allow
|
||||||
|
the user to drop it by setting their own LDFLAGS (e.g. PIE could be
|
||||||
|
enabled or disabled by the buildsystem such as buildroot).
|
||||||
|
|
||||||
|
Suggested-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Makefile | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 7c221a89..adac7905 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -132,12 +132,12 @@ CFLAGS += -DUSE_PTHREADS
|
||||||
|
MON_LDFLAGS += -pthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
-LDFLAGS = -Wl,-z,now,-z,noexecstack
|
||||||
|
+LDFLAGS ?= -pie -Wl,-z,now,-z,noexecstack
|
||||||
|
|
||||||
|
# If you want a static binary, you might uncomment these
|
||||||
|
# LDFLAGS += -static
|
||||||
|
# STRIP = -s
|
||||||
|
-LDLIBS = -ldl -pie
|
||||||
|
+LDLIBS = -ldl
|
||||||
|
|
||||||
|
# To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
|
||||||
|
ifeq (, $(findstring -DNO_LIBUDEV, $(CXFLAGS)))
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
30
0064-tests-23rdev-lifetime-fix-a-typo.patch
Normal file
30
0064-tests-23rdev-lifetime-fix-a-typo.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
From a0174749426f49a04f11ae0e728cb0a681bfa465 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yu Kuai <yukuai3@huawei.com>
|
||||||
|
Date: Thu, 9 May 2024 09:10:59 +0800
|
||||||
|
Subject: [PATCH 64/66] tests/23rdev-lifetime: fix a typo
|
||||||
|
|
||||||
|
"pill" was wrong, while it should be "kill", test will still pass while
|
||||||
|
test thread will not be cleaned up.
|
||||||
|
|
||||||
|
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
tests/23rdev-lifetime | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/tests/23rdev-lifetime b/tests/23rdev-lifetime
|
||||||
|
index 1750b0db..03b61de4 100644
|
||||||
|
--- a/tests/23rdev-lifetime
|
||||||
|
+++ b/tests/23rdev-lifetime
|
||||||
|
@@ -4,7 +4,7 @@ pid=""
|
||||||
|
runtime=2
|
||||||
|
|
||||||
|
clean_up_test() {
|
||||||
|
- pill -9 $pid
|
||||||
|
+ kill -9 $pid
|
||||||
|
echo clear > /sys/block/md0/md/array_state
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
55
0065-util.c-change-devnm-to-const-in-mdmon-functions.patch
Normal file
55
0065-util.c-change-devnm-to-const-in-mdmon-functions.patch
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
From b0f4e8e30f38d83f7e3f53d01d72d4cb3b4d42d7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Date: Tue, 7 May 2024 05:38:55 +0200
|
||||||
|
Subject: [PATCH 65/66] util.c: change devnm to const in mdmon functions
|
||||||
|
|
||||||
|
Devnm shall not be changed inside mdmon_running()
|
||||||
|
and mdmon_pid() functions, change this parameter to const.
|
||||||
|
|
||||||
|
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
mdadm.h | 4 ++--
|
||||||
|
util.c | 4 ++--
|
||||||
|
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 2ff3e463..1ba541fc 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1768,8 +1768,8 @@ extern int is_subarray_active(char *subarray, char *devname);
|
||||||
|
extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet);
|
||||||
|
extern struct superswitch *version_to_superswitch(char *vers);
|
||||||
|
|
||||||
|
-extern int mdmon_running(char *devnm);
|
||||||
|
-extern int mdmon_pid(char *devnm);
|
||||||
|
+extern int mdmon_running(const char *devnm);
|
||||||
|
+extern int mdmon_pid(const char *devnm);
|
||||||
|
extern int check_env(char *name);
|
||||||
|
extern __u32 random32(void);
|
||||||
|
extern void random_uuid(__u8 *buf);
|
||||||
|
diff --git a/util.c b/util.c
|
||||||
|
index 4fbf11c4..e2b490e1 100644
|
||||||
|
--- a/util.c
|
||||||
|
+++ b/util.c
|
||||||
|
@@ -1902,7 +1902,7 @@ unsigned long long min_recovery_start(struct mdinfo *array)
|
||||||
|
return recovery_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int mdmon_pid(char *devnm)
|
||||||
|
+int mdmon_pid(const char *devnm)
|
||||||
|
{
|
||||||
|
char path[100];
|
||||||
|
char pid[10];
|
||||||
|
@@ -1922,7 +1922,7 @@ int mdmon_pid(char *devnm)
|
||||||
|
return atoi(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
-int mdmon_running(char *devnm)
|
||||||
|
+int mdmon_running(const char *devnm)
|
||||||
|
{
|
||||||
|
int pid = mdmon_pid(devnm);
|
||||||
|
if (pid <= 0)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
121
0066-Wait-for-mdmon-when-it-is-stared-via-systemd.patch
Normal file
121
0066-Wait-for-mdmon-when-it-is-stared-via-systemd.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
From aa1cc5815d2b14a8b47add18cfaa8264e19c10ce Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Date: Tue, 7 May 2024 05:38:56 +0200
|
||||||
|
Subject: [PATCH 66/66] Wait for mdmon when it is stared via systemd
|
||||||
|
|
||||||
|
When mdmon is being started it may need few seconds to start.
|
||||||
|
For now, we didn't wait for it. Introduce wait_for_mdmon()
|
||||||
|
function, which waits up to 5 seconds for mdmon to start completely.
|
||||||
|
|
||||||
|
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Assemble.c | 4 ++--
|
||||||
|
Grow.c | 7 ++++---
|
||||||
|
mdadm.h | 2 ++
|
||||||
|
util.c | 29 +++++++++++++++++++++++++++++
|
||||||
|
4 files changed, 37 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Assemble.c b/Assemble.c
|
||||||
|
index f5e9ab1f..83dced19 100644
|
||||||
|
--- a/Assemble.c
|
||||||
|
+++ b/Assemble.c
|
||||||
|
@@ -2173,8 +2173,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
||||||
|
if (!mdmon_running(st->container_devnm))
|
||||||
|
start_mdmon(st->container_devnm);
|
||||||
|
ping_monitor(st->container_devnm);
|
||||||
|
- if (mdmon_running(st->container_devnm) &&
|
||||||
|
- st->update_tail == NULL)
|
||||||
|
+ if (wait_for_mdmon(st->container_devnm) == MDADM_STATUS_SUCCESS &&
|
||||||
|
+ !st->update_tail)
|
||||||
|
st->update_tail = &st->updates;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/Grow.c b/Grow.c
|
||||||
|
index 87ed9214..1923c27c 100644
|
||||||
|
--- a/Grow.c
|
||||||
|
+++ b/Grow.c
|
||||||
|
@@ -2134,7 +2134,7 @@ int Grow_reshape(char *devname, int fd,
|
||||||
|
if (!mdmon_running(st->container_devnm))
|
||||||
|
start_mdmon(st->container_devnm);
|
||||||
|
ping_monitor(container);
|
||||||
|
- if (mdmon_running(st->container_devnm) == false) {
|
||||||
|
+ if (wait_for_mdmon(st->container_devnm) != MDADM_STATUS_SUCCESS) {
|
||||||
|
pr_err("No mdmon found. Grow cannot continue.\n");
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
@@ -3218,7 +3218,8 @@ static int reshape_array(char *container, int fd, char *devname,
|
||||||
|
if (!mdmon_running(container))
|
||||||
|
start_mdmon(container);
|
||||||
|
ping_monitor(container);
|
||||||
|
- if (mdmon_running(container) && st->update_tail == NULL)
|
||||||
|
+ if (wait_for_mdmon(container) == MDADM_STATUS_SUCCESS &&
|
||||||
|
+ !st->update_tail)
|
||||||
|
st->update_tail = &st->updates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -5173,7 +5174,7 @@ int Grow_continue_command(char *devname, int fd, struct context *c)
|
||||||
|
start_mdmon(container);
|
||||||
|
ping_monitor(container);
|
||||||
|
|
||||||
|
- if (mdmon_running(container) == false) {
|
||||||
|
+ if (wait_for_mdmon(container) != MDADM_STATUS_SUCCESS) {
|
||||||
|
pr_err("No mdmon found. Grow cannot continue.\n");
|
||||||
|
ret_val = 1;
|
||||||
|
goto Grow_continue_command_exit;
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 1ba541fc..b71d7b32 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1770,6 +1770,8 @@ extern struct superswitch *version_to_superswitch(char *vers);
|
||||||
|
|
||||||
|
extern int mdmon_running(const char *devnm);
|
||||||
|
extern int mdmon_pid(const char *devnm);
|
||||||
|
+extern mdadm_status_t wait_for_mdmon(const char *devnm);
|
||||||
|
+
|
||||||
|
extern int check_env(char *name);
|
||||||
|
extern __u32 random32(void);
|
||||||
|
extern void random_uuid(__u8 *buf);
|
||||||
|
diff --git a/util.c b/util.c
|
||||||
|
index e2b490e1..bf79742f 100644
|
||||||
|
--- a/util.c
|
||||||
|
+++ b/util.c
|
||||||
|
@@ -1932,6 +1932,35 @@ int mdmon_running(const char *devnm)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * wait_for_mdmon() - Waits for mdmon within specified time.
|
||||||
|
+ * @devnm: Device for which mdmon should start.
|
||||||
|
+ *
|
||||||
|
+ * Function waits for mdmon to start. It may need few seconds
|
||||||
|
+ * to start, we set timeout to 5, it should be sufficient.
|
||||||
|
+ * Do not wait if mdmon has been started.
|
||||||
|
+ *
|
||||||
|
+ * Return: MDADM_STATUS_SUCCESS if mdmon is running, error code otherwise.
|
||||||
|
+ */
|
||||||
|
+mdadm_status_t wait_for_mdmon(const char *devnm)
|
||||||
|
+{
|
||||||
|
+ const time_t mdmon_timeout = 5;
|
||||||
|
+ time_t start_time = time(0);
|
||||||
|
+
|
||||||
|
+ if (mdmon_running(devnm))
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+
|
||||||
|
+ pr_info("Waiting for mdmon to start\n");
|
||||||
|
+ while (time(0) - start_time < mdmon_timeout) {
|
||||||
|
+ sleep_for(0, MSEC_TO_NSEC(200), true);
|
||||||
|
+ if (mdmon_running(devnm))
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ pr_err("Timeout waiting for mdmon\n");
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int start_mdmon(char *devnm)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
62
0069-mdadm-Fix-compilation-for-32-bit-arch.patch
Normal file
62
0069-mdadm-Fix-compilation-for-32-bit-arch.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
From c5879860eac64ddd7bec4ba50c9adbfebcbf1d2e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
Date: Wed, 15 May 2024 13:26:28 +0200
|
||||||
|
Subject: [PATCH 1/1] mdadm: Fix compilation for 32-bit arch
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Casting void pointer to __u64 works for 64-bit arch but fails to compile
|
||||||
|
on 32-bit arch like i686.
|
||||||
|
|
||||||
|
Fail on i686 platform:
|
||||||
|
drive_encryption.c: In function ‘nvme_security_recv_ioctl’:
|
||||||
|
drive_encryption.c:236:25: error: cast from pointer to integer of
|
||||||
|
different size [-Werror=pointer-to-int-cast]
|
||||||
|
236 | nvme_cmd.addr = (__u64)response_buffer;
|
||||||
|
| ^
|
||||||
|
drive_encryption.c: In function ‘nvme_identify_ioctl’:
|
||||||
|
drive_encryption.c:271:25: error: cast from pointer to integer of
|
||||||
|
different size [-Werror=pointer-to-int-cast]
|
||||||
|
271 | nvme_cmd.addr = (__u64)response_buffer;
|
||||||
|
| ^
|
||||||
|
cc1: all warnings being treated as errors
|
||||||
|
make: *** [Makefile:211: drive_encryption.o] Error 1
|
||||||
|
|
||||||
|
This change adds cast void pointer to uintptr_t first to ensure that
|
||||||
|
proper pointer size is used for casting from pointer type. Then is safe to
|
||||||
|
cast it to __u64 because it is tracked as u_int, regardless it is 32-bit
|
||||||
|
or 64-bit arch.
|
||||||
|
|
||||||
|
Reported-by: Xiao Ni <xni@redhat.com>
|
||||||
|
Fixes: cc48406887b3 ("Add reading Opal NVMe encryption information")
|
||||||
|
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||||
|
---
|
||||||
|
drive_encryption.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drive_encryption.c b/drive_encryption.c
|
||||||
|
index 27da9621..a4ad799f 100644
|
||||||
|
--- a/drive_encryption.c
|
||||||
|
+++ b/drive_encryption.c
|
||||||
|
@@ -233,7 +233,7 @@ nvme_security_recv_ioctl(int disk_fd, __u8 sec_protocol, __u16 comm_id, void *re
|
||||||
|
nvme_cmd.cdw10 = sec_protocol << 24 | comm_id << 8;
|
||||||
|
nvme_cmd.cdw11 = buf_size;
|
||||||
|
nvme_cmd.data_len = buf_size;
|
||||||
|
- nvme_cmd.addr = (__u64)response_buffer;
|
||||||
|
+ nvme_cmd.addr = (__u64)(uintptr_t)response_buffer;
|
||||||
|
|
||||||
|
status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
|
||||||
|
if (status != 0) {
|
||||||
|
@@ -268,7 +268,7 @@ nvme_identify_ioctl(int disk_fd, void *response_buffer, size_t buf_size, const i
|
||||||
|
nvme_cmd.opcode = NVME_IDENTIFY;
|
||||||
|
nvme_cmd.cdw10 = NVME_IDENTIFY_CONTROLLER_DATA;
|
||||||
|
nvme_cmd.data_len = buf_size;
|
||||||
|
- nvme_cmd.addr = (__u64)response_buffer;
|
||||||
|
+ nvme_cmd.addr = (__u64)(uintptr_t)response_buffer;
|
||||||
|
|
||||||
|
status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
|
||||||
|
if (status != 0) {
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
6
gating.yaml
Normal file
6
gating.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
--- !Policy
|
||||||
|
product_versions:
|
||||||
|
- rhel-10
|
||||||
|
decision_context: osci_compose_gate
|
||||||
|
rules:
|
||||||
|
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}
|
32
mdadm.spec
32
mdadm.spec
@ -1,7 +1,7 @@
|
|||||||
Name: mdadm
|
Name: mdadm
|
||||||
Version: 4.3
|
Version: 4.3
|
||||||
# extraversion is used to define rhel internal version
|
# extraversion is used to define rhel internal version
|
||||||
%define extraversion 1
|
%define extraversion 2
|
||||||
Release: %{extraversion}%{?dist}
|
Release: %{extraversion}%{?dist}
|
||||||
Summary: The mdadm program controls Linux md devices (software RAID arrays)
|
Summary: The mdadm program controls Linux md devices (software RAID arrays)
|
||||||
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
|
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
|
||||||
@ -60,6 +60,32 @@ Patch037: 0038-mdadm-Fix-native-detail-export.patch
|
|||||||
Patch038: 0039-sysfs-remove-vers-parameter-from-sysfs_set_array.patch
|
Patch038: 0039-sysfs-remove-vers-parameter-from-sysfs_set_array.patch
|
||||||
Patch039: 0040-mdadm-fix-grow-segfault-for-IMSM.patch
|
Patch039: 0040-mdadm-fix-grow-segfault-for-IMSM.patch
|
||||||
Patch040: 0041-Remove-all-if-zeros-pt.2.patch
|
Patch040: 0041-Remove-all-if-zeros-pt.2.patch
|
||||||
|
Patch041: 0042-mdadm-Move-pr_vrb-define-to-mdadm.h.patch
|
||||||
|
Patch042: 0043-Add-reading-Opal-NVMe-encryption-information.patch
|
||||||
|
Patch043: 0044-Add-reading-SATA-encryption-information.patch
|
||||||
|
Patch044: 0045-Add-key-ENCRYPTION_NO_VERIFY-to-conf.patch
|
||||||
|
Patch045: 0046-imsm-print-disk-encryption-information.patch
|
||||||
|
Patch046: 0047-imsm-drive-encryption-policy-implementation.patch
|
||||||
|
Patch047: 0048-mdadm-add-CHANGELOG.md.patch
|
||||||
|
Patch048: 0049-mdadm-Add-MAINTAINERS.md.patch
|
||||||
|
Patch049: 0050-mdadm-Add-README.md.patch
|
||||||
|
Patch050: 0051-Create.c-fix-uclibc-build.patch
|
||||||
|
Patch051: 0052-mdadm-pass-struct-context-for-external-reshapes.patch
|
||||||
|
Patch052: 0053-mdadm-use-struct-context-in-reshape_super.patch
|
||||||
|
Patch053: 0054-imsm-add-support-for-literal-RAID-10.patch
|
||||||
|
Patch054: 0055-imsm-refactor-RAID-level-handling.patch
|
||||||
|
Patch055: 0056-imsm-bump-minimal-version.patch
|
||||||
|
Patch056: 0057-imsm-define-RAID_10-attribute.patch
|
||||||
|
Patch057: 0058-imsm-simplify-imsm_check_attributes.patch
|
||||||
|
Patch058: 0059-imsm-support-RAID-10-with-more-than-4-drives.patch
|
||||||
|
Patch059: 0060-tests-01r5fail-enhance.patch
|
||||||
|
Patch060: 0061-tests-01r5integ.broken.patch
|
||||||
|
Patch061: 0062-tests-01raid6integ.broken-can-be-removed.patch
|
||||||
|
Patch062: 0063-Makefile-Move-pie-to-LDFLAGS.patch
|
||||||
|
Patch063: 0064-tests-23rdev-lifetime-fix-a-typo.patch
|
||||||
|
Patch064: 0065-util.c-change-devnm-to-const-in-mdmon-functions.patch
|
||||||
|
Patch065: 0066-Wait-for-mdmon-when-it-is-stared-via-systemd.patch
|
||||||
|
Patch066: 0069-mdadm-Fix-compilation-for-32-bit-arch.patch
|
||||||
|
|
||||||
# Fedora customization patches
|
# Fedora customization patches
|
||||||
Patch197: mdadm-udev.patch
|
Patch197: mdadm-udev.patch
|
||||||
@ -137,6 +163,10 @@ install -m644 %{SOURCE5} %{buildroot}/etc/libreport/events.d
|
|||||||
/usr/share/mdadm/mdcheck
|
/usr/share/mdadm/mdcheck
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed May 15 2024 Xiao Ni <xni@redhat.com> 4.3-2
|
||||||
|
- Update to latest upstream and add gating test
|
||||||
|
- Resolves RHEL-30530
|
||||||
|
|
||||||
* Fri Mar 29 2024 Xiao Ni <xni@redhat.com> 4.3-1
|
* Fri Mar 29 2024 Xiao Ni <xni@redhat.com> 4.3-1
|
||||||
- Update to 4.3 and to latest upstream
|
- Update to 4.3 and to latest upstream
|
||||||
- Resolves RHEL-30530
|
- Resolves RHEL-30530
|
||||||
|
674
tests/md_raid_module/LICENSE
Normal file
674
tests/md_raid_module/LICENSE
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
60
tests/md_raid_module/Makefile
Normal file
60
tests/md_raid_module/Makefile
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Copyright (c) 2006 Red Hat, Inc. All rights reserved. This copyrighted material
|
||||||
|
# is made available to anyone wishing to use, modify, copy, or
|
||||||
|
# redistribute it subject to the terms and conditions of the GNU General
|
||||||
|
# Public License v.2.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# Author:guazhang <guazhang@redhat.com>
|
||||||
|
|
||||||
|
# The toplevel namespace within which the test lives.
|
||||||
|
|
||||||
|
# Version of the Test. Used with make tag.
|
||||||
|
export TESTVERSION=1.0
|
||||||
|
|
||||||
|
# A phony target is one that is not really the name of a file.
|
||||||
|
# It is just a name for some commands to be executed when you
|
||||||
|
# make an explicit request. There are two reasons to use a
|
||||||
|
# phony target: to avoid a conflict with a file of the same
|
||||||
|
# name, and to improve performance.
|
||||||
|
.PHONY: all install download clean
|
||||||
|
|
||||||
|
# executables to be built should be added here,
|
||||||
|
# they will be generated on the system under test.
|
||||||
|
BUILT_FILES=
|
||||||
|
|
||||||
|
# data files, .c files, scripts anything needed to either compile the test
|
||||||
|
# and/or run it.
|
||||||
|
FILES=$(METADATA) tc.sh LICENSE main.sh Makefile PURPOSE
|
||||||
|
|
||||||
|
run: $(FILES) build
|
||||||
|
./main.sh
|
||||||
|
|
||||||
|
build: $(BUILT_FILES)
|
||||||
|
# sudo chmod a+x main.sh
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ *.rpm $(BUILT_FILES)
|
||||||
|
|
||||||
|
# You may need to add other targets e.g. to build executables from source code
|
||||||
|
# Add them here:
|
||||||
|
|
||||||
|
|
||||||
|
# Include Common Makefile
|
||||||
|
|
||||||
|
# Generate the testinfo.desc here:
|
||||||
|
$(METADATA): Makefile
|
||||||
|
@touch $(METADATA)
|
||||||
|
# Change to the test owner's name
|
||||||
|
@echo "Owner: guazhang <guazhang@redhat.com>" > $(METADATA)
|
||||||
|
@echo "Name: $(TEST)" >> $(METADATA)
|
||||||
|
@echo "Path: $(TEST_DIR)" >> $(METADATA)
|
||||||
|
@echo "License: GPLv3" >> $(METADATA)
|
||||||
|
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
|
||||||
|
@echo "Description: remove raid module">> $(METADATA)
|
7
tests/md_raid_module/PURPOSE
Normal file
7
tests/md_raid_module/PURPOSE
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
modprobe raid module
|
||||||
|
modprobe -r raid module
|
||||||
|
|
||||||
|
modprobe raid0 raid1 raid10 raid456
|
||||||
|
modprobe -r raid0 raid1 raid10 raid456
|
||||||
|
|
||||||
|
|
621
tests/md_raid_module/include.sh
Executable file
621
tests/md_raid_module/include.sh
Executable file
@ -0,0 +1,621 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Author: guazhang <guazhang@redhat.com>
|
||||||
|
|
||||||
|
source tc.sh || exit 1
|
||||||
|
|
||||||
|
rpm -q mdadm || yum install -y mdadm
|
||||||
|
JOURNAL_SUPPORT=0
|
||||||
|
info=`mdadm --create --help | grep -o "write-journal"`
|
||||||
|
if [ "$info" = "write-journal" ]; then
|
||||||
|
JOURNAL_SUPPORT=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Install fio from upstream
|
||||||
|
function install_fio() {
|
||||||
|
|
||||||
|
git_url=git://git.kernel.org/pub/scm/linux/kernel/git/axboe/fio.git
|
||||||
|
|
||||||
|
tok yum install libaio-devel zlib-devel -y
|
||||||
|
tok git clone $git_url
|
||||||
|
tlog "INFO: Installing Fio"
|
||||||
|
tok "cd fio &&./configure && make && make install"
|
||||||
|
tok which fio
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
tlog "FAIL: Fio not succesffully installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tlog "INFO: Fio succesfully installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
#Install dt
|
||||||
|
function install_dt () {
|
||||||
|
|
||||||
|
wget http://www.scsifaq.org/RMiller_Tools/ftp/dt/dt-source.tar.gz
|
||||||
|
tar xvf dt-source.tar.gz
|
||||||
|
cd dt.d-WIP/
|
||||||
|
cp -p Makefile.linux Makefile
|
||||||
|
make
|
||||||
|
cp dt /usr/bin
|
||||||
|
}
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Create_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# Create md raid.
|
||||||
|
# Parameter:
|
||||||
|
# $level # like 0, 1, 3, 5, 10, 50
|
||||||
|
# $dev_list # like 'sda sdb sdc sdd'
|
||||||
|
# $raid_dev_num # like 3
|
||||||
|
# $spar_dev_num # like 2
|
||||||
|
# $chunk # like 64
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $md_raid like '/dev/md0'
|
||||||
|
# MD_DEVS # $raid_dev_list like '/dev/sda /dev/sdb'
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Create_RAID (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo 'Usage: MD_Create_RAID $level $dev_list $raid_dev_num \
|
||||||
|
[$spar_dev_num] [$chunk]'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
# variable definitions
|
||||||
|
RETURN_STR=''
|
||||||
|
MD_DEVS=''
|
||||||
|
local level=$1
|
||||||
|
local dev_list=$2
|
||||||
|
local raid_dev_num=$3
|
||||||
|
local bitmap=$4
|
||||||
|
local spar_dev_num=${5:-0}
|
||||||
|
local chunk=${6:-512}
|
||||||
|
local bitmap_chunksize=${7:-64M}
|
||||||
|
local dev_num=0
|
||||||
|
local raid_dev=''
|
||||||
|
local spar_dev=''
|
||||||
|
local md_raid=""
|
||||||
|
local mtdata=${8:-1.2}
|
||||||
|
local ret=0
|
||||||
|
# start to create
|
||||||
|
echo "INFO: Executing MD_Create_RAID() to create raid $level"
|
||||||
|
# check if the given disks are more the needed
|
||||||
|
for i in $dev_list; do
|
||||||
|
dev_num=$((dev_num+1))
|
||||||
|
done
|
||||||
|
if [ $dev_num -lt $(($raid_dev_num+$spar_dev_num)) ]; then
|
||||||
|
echo "FAIL: Required devices are more than given."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# get free md device name, only scan /dev/md[0-15].
|
||||||
|
for i in `seq 1 30`; do
|
||||||
|
ls -l /dev/md$i > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
md_raid=/dev/md$i
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# get raid disk list.
|
||||||
|
for i in `seq 1 $raid_dev_num`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
raid_dev="$raid_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these raid devices \"$raid_dev\"."
|
||||||
|
# get spare disk list.
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
for i in `seq $((raid_dev_num+1)) $((raid_dev_num+spar_dev_num))`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
spar_dev="$spar_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these spare disks \"$spar_dev\"."
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
# create md raid
|
||||||
|
if [ $bitmap -eq 1 ]; then
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
mdadm --create --run $md_raid --level $level --metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev --chunk $chunk --bitmap=internal --bitmap-chunk=$bitmap_chunksize
|
||||||
|
else
|
||||||
|
mdadm --create --run $md_raid --level $level --metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev --chunk $chunk --bitmap=internal --bitmap-chunk=$bitmap_chunksize
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ $bitmap -eq 2 ];then
|
||||||
|
touch /home/bitmap_md_$level
|
||||||
|
echo "INFO:bitmap backup in /home/bitmap_md_$level"
|
||||||
|
bitmap_dir="/home/bitmap_md_$level"
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
mdadm --create --run $md_raid --level $level --metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev --chunk $chunk --bitmap=$bitmap_dir --force --bitmap-chunk=$bitmap_chunksize
|
||||||
|
else
|
||||||
|
mdadm --create --run $md_raid --level $level --metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev --chunk $chunk --bitmap=$bitmap_dir --force --bitmap-chunk=$bitmap_chunksize
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
mdadm --create --run $md_raid --level $level --metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev --chunk $chunk
|
||||||
|
else
|
||||||
|
mdadm --create --run $md_raid --level $level --metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev --chunk $chunk
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
ret=$?
|
||||||
|
echo "INFO:create $md_raid failed.will remove all raid disk "
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
echo "create `date +%s` mdadm -CR $md_raid -l $level -e $mtdata -n $raid_dev_num \"$raid_dev\" -x=$spar_dev_num $spar_dev bitmap=$bitmap --chunk $chunk --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
echo "INFO:cat /proc/mdstat######################"
|
||||||
|
cat /proc/mdstat
|
||||||
|
lsblk
|
||||||
|
trun "ls /dev/md* |egrep md[0-9]+"
|
||||||
|
echo "INFO:mdadm -D $md_raid #########################"
|
||||||
|
mdadm --detail $md_raid
|
||||||
|
# define global variables
|
||||||
|
MD_DEVS="$raid_dev $spar_dev"
|
||||||
|
RETURN_STR="$md_raid"
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Create_RAID
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Create_RAID_Journal ()
|
||||||
|
# Usage:
|
||||||
|
# Create md raid with journal.
|
||||||
|
# Parameter:
|
||||||
|
# $level # like 4, 5, 6
|
||||||
|
# $dev_list # like 'sda sdb sdc sdd'
|
||||||
|
# $raid_dev_num # like 3
|
||||||
|
# $spar_dev_num # like 2
|
||||||
|
# $chunk # like 64
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $md_raid like '/dev/md0'
|
||||||
|
# MD_DEVS # $raid_dev_list like '/dev/sda /dev/sdb'
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Create_RAID_Journal (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo 'Usage: MD_Create_RAID_Journal $level $dev_list $raid_dev_num \
|
||||||
|
[$spar_dev_num] [$chunk]'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
# variable definitions
|
||||||
|
RETURN_STR=''
|
||||||
|
MD_DEVS=''
|
||||||
|
local level=$1
|
||||||
|
local dev_list=$2
|
||||||
|
local raid_dev_num=$3
|
||||||
|
local bitmap=$4
|
||||||
|
local spar_dev_num=${5:-0}
|
||||||
|
local chunk=${6:-512}
|
||||||
|
local bitmap_chunksize=${7:-64M}
|
||||||
|
local mtdata=${8:-1.2}
|
||||||
|
local dev_num=0
|
||||||
|
local raid_dev=''
|
||||||
|
local spar_dev=''
|
||||||
|
local md_raid=""
|
||||||
|
local ret=0
|
||||||
|
# start to create
|
||||||
|
echo "INFO: Executing MD_Create_RAID_Journal() to create raid $level"
|
||||||
|
# check if the given disks are more the needed
|
||||||
|
for i in $dev_list; do
|
||||||
|
dev_num=$((dev_num+1))
|
||||||
|
done
|
||||||
|
if [ $dev_num -lt $(($raid_dev_num+$spar_dev_num)) ]; then
|
||||||
|
echo "FAIL: Required devices are more than given."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# get free md device name, only scan /dev/md[0-15].
|
||||||
|
for i in `seq 0 15`; do
|
||||||
|
ls -l /dev/md$i > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
md_raid=/dev/md$i
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# take the first disk as journal disk
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f 1`
|
||||||
|
journal_dev="/dev/$tmp_dev"
|
||||||
|
echo "INFO: Created md raid with write journal disk \"$journal_dev\"."
|
||||||
|
|
||||||
|
# get raid disk list.
|
||||||
|
for i in `seq 2 $raid_dev_num`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
raid_dev="$raid_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these raid devices \"$raid_dev\"."
|
||||||
|
|
||||||
|
# get spare disk list.
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
for i in `seq $((raid_dev_num+1)) $((raid_dev_num+spar_dev_num))`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
spar_dev="$spar_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these spare disks \"$spar_dev\"."
|
||||||
|
fi
|
||||||
|
|
||||||
|
#There is one write journal disk, so change the raid_dev_num--
|
||||||
|
((raid_dev_num--))
|
||||||
|
|
||||||
|
# create md raid
|
||||||
|
# prepare the parameter
|
||||||
|
BITMAP=""
|
||||||
|
SPAR_DEV=""
|
||||||
|
if [ $bitmap -eq 1 ]; then
|
||||||
|
BITMAP="--bitmap=internal --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
fi
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
SPAR_DEV="--spare-devices $spar_dev_num $spar_dev"
|
||||||
|
fi
|
||||||
|
if [ -n "$journal_dev" ]; then
|
||||||
|
WRITE_JOURNAL="--write-journal $journal_dev"
|
||||||
|
fi
|
||||||
|
tok "mdadm --create --run $md_raid --level $level --metadata $mtdata --raid-devices $raid_dev_num $raid_dev $WRITE_JOURNAL $SPAR_DEV $BITMAP --chunk $chunk"
|
||||||
|
ret=$?
|
||||||
|
echo "create raid time `date +%s` mdadm -CR $md_raid --level $level --metadata $mtdata --raid-devices $raid_dev_num $raid_dev $WRITE_JOURNAL $SPAR_DEV $BITMAP --chunk $chunk "
|
||||||
|
cat /proc/mdstat
|
||||||
|
mdadm --detail $md_raid
|
||||||
|
# define global variables
|
||||||
|
MD_DEVS="$journal_dev $raid_dev $spar_dev"
|
||||||
|
RETURN_STR="$md_raid"
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Create_RAID_Journal
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Save_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# Save md raid configuration.
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Save_RAID (){
|
||||||
|
echo "INFO: Executing MD_Save_RAID()"
|
||||||
|
echo "DEVICE $MD_DEVS" > /etc/mdadm.conf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: Failed to save md device info to /etc/mdadm.conf"
|
||||||
|
fi
|
||||||
|
mdadm --detail --scan >> /etc/mdadm.conf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: Failed to save md state info to /etc/mdadm.conf"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Save_RAID
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Clean_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# Clean md raid.
|
||||||
|
# Parameter:
|
||||||
|
# $md_name # like '/dev/md0'
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Clean_RAID (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo 'Usage: MD_Clean_RAID $md_name'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
echo "INFO: Executing MD_Clean_RAID() against this md device: $md_name"
|
||||||
|
local md_name=$1
|
||||||
|
echo "mdadm --stop $md_name"
|
||||||
|
mdadm --stop $md_name
|
||||||
|
st=$?
|
||||||
|
while [ $st -ne 0 ]; do
|
||||||
|
echo "INFO:mdadm stop failed"
|
||||||
|
sleep 10
|
||||||
|
rm -rf /etc/mdadm.conf
|
||||||
|
for i in $(cat /proc/mdstat |grep "inactive" |awk '{print $1}') ;do
|
||||||
|
mdadm --stop "/dev/$i"
|
||||||
|
done
|
||||||
|
mdadm --stop $md_name
|
||||||
|
st=$?
|
||||||
|
|
||||||
|
done
|
||||||
|
sleep 10
|
||||||
|
echo "clean devs : $MD_DEVS"
|
||||||
|
for dev in $MD_DEVS; do
|
||||||
|
echo "mdadm --zero-superblock $dev"
|
||||||
|
`mdadm --zero-superblock $dev`
|
||||||
|
done
|
||||||
|
#`mdadm --zero-superblock "$MD_DEVS"`
|
||||||
|
echo "ret is $?"
|
||||||
|
rm -rf /etc/mdadm.conf
|
||||||
|
sleep 10
|
||||||
|
echo "ls $md_name"
|
||||||
|
tnot "ls $md_name"
|
||||||
|
if [ $? = 1 ];then
|
||||||
|
tlog "mdadm --stop command can't delete md node name $md_name in /dev node"
|
||||||
|
trun "ls /dev/md*"
|
||||||
|
trun "cat /proc/mdstat"
|
||||||
|
else
|
||||||
|
tlog "mdadm --stop can delete md node name $md_name in /dev"
|
||||||
|
# rm -rf $md_name
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Clean_RAID
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Get_State_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# get md raid status
|
||||||
|
# Parameter:
|
||||||
|
# $md_name # like "/dev/md0"
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $state, like 'clean, resyncing'
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Get_State_RAID (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo 'Usage: MD_Get_State_RAID $md_name'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
RETURN_STR=''
|
||||||
|
local md_name=$1
|
||||||
|
local state=''
|
||||||
|
local start_times=0
|
||||||
|
local end_times=0
|
||||||
|
local spend_times=0
|
||||||
|
# echo "INFO: Executing MD_Get_State_RAID() against this md array: $md_name"
|
||||||
|
start_times=$(date +%s)
|
||||||
|
echo " $start_times start_time against this md array: $md_name "
|
||||||
|
# echo "mdadm --detail $md_name | grep "State :" | cut -d ":" -f 2 | cut -d " " -f 2"
|
||||||
|
state=`mdadm --detail $md_name | grep "State :" | cut -d ":" -f 2 | cut -d " " -f 2`
|
||||||
|
sta=$?
|
||||||
|
if [ -z "$state" ]; then
|
||||||
|
echo "`date +%s` first_time_failed get raid statu #############################+++++++++++++++++++++++++"
|
||||||
|
while [ $sta ];do
|
||||||
|
state=`mdadm --detail $md_name | grep "State :" | cut -d ":" -f 2 | cut -d " " -f 2`
|
||||||
|
sta=$?
|
||||||
|
end_times=$(date +%s)
|
||||||
|
spend_times=$((end_times - start_times))
|
||||||
|
if [[ $spend_times -gt 10 ]];then
|
||||||
|
echo "get raid status spend $spend_times and exit "
|
||||||
|
ls /dev/md* |egrep md[0-9]+
|
||||||
|
cat /proc/mdstat
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$spend_times spend raid statu_time #############################"
|
||||||
|
fi
|
||||||
|
echo "state is $state"
|
||||||
|
RETURN_STR="$state"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Get_State_RAID
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_IO_Test ()
|
||||||
|
# Usage:
|
||||||
|
# IO test using dt against block level
|
||||||
|
# Parameter:
|
||||||
|
# $dt_target # like "/dev/md0"
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_IO_Test (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo 'Usage: MD_IO_Test $dt_target'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
# this parameter should be change to 7200 during a real testing cycle
|
||||||
|
local dt_runtime=72
|
||||||
|
local dt_logfile=""
|
||||||
|
test -f /tmp/dt_XXXXXXXX.log || `mktemp /tmp/dt_XXXXXXXX.log`
|
||||||
|
dt_logfile="/tmp/dt_XXXXXXXX.log"
|
||||||
|
local dt_target=$1
|
||||||
|
echo -n "INFO: dt against ${dt_target} is running with "
|
||||||
|
echo "runtime: ${dt_runtime}s, log file is: ${dt_logfile}"
|
||||||
|
echo "dt slices=16 disable=eof,pstats flags=direct \
|
||||||
|
oncerr=abort min=b max=256k \
|
||||||
|
pattern=iot iodir=reverse prefix='%d@%h (pid %p)' \
|
||||||
|
of=${dt_target} log=${dt_logfile} \
|
||||||
|
runtime=${dt_runtime}"
|
||||||
|
`dt slices=16 disable=eof,pstats flags=direct \
|
||||||
|
oncerr=abort min=b max=256k \
|
||||||
|
pattern=iot iodir=reverse prefix='%d@%h (pid %p)' \
|
||||||
|
of=${dt_target} log=${dt_logfile} \
|
||||||
|
runtime=${dt_runtime}`
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: Failed to run dt testing against $dt_target"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_IO_Test
|
||||||
|
|
||||||
|
function create_loop_devices (){
|
||||||
|
Create_Loop_Devices $@
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Create_Loop_Devices ()
|
||||||
|
# Usage:
|
||||||
|
# Create loop devices. We will find out the free number
|
||||||
|
# of loop to bind on tmp file.
|
||||||
|
# Parameter:
|
||||||
|
# $count #like "12"
|
||||||
|
# $size_mib #like "1024"
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR like 'loop9 loop10'
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
|
||||||
|
function Create_Loop_Devices (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -ne 2 ]; then
|
||||||
|
echo 'Usage: Create_Loop_Devices $count $size_mib'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
RETURN_STR=''
|
||||||
|
local count="$1"
|
||||||
|
local size_mib="$2"
|
||||||
|
local loop_dev_list=''
|
||||||
|
for X in `seq 1 ${count}`;do
|
||||||
|
local loop_file_name=$(mktemp /tmp/loop.XXXXXX)
|
||||||
|
dd if=/dev/zero of=${loop_file_name} count=$size_mib bs=1M 1>/dev/null 2>&1
|
||||||
|
local loop_dev_name=$(losetup -f)
|
||||||
|
#BUG: RHEL5 only support 8 loop device and we need to check whether we are run out of it
|
||||||
|
local command="losetup ${loop_dev_name} ${loop_file_name} 1>/dev/null 2>&1"
|
||||||
|
eval "${command}"
|
||||||
|
if [ $? -eq 0 ];then
|
||||||
|
loop_dev_list="${loop_dev_list}${loop_dev_name} "
|
||||||
|
else
|
||||||
|
echo "FAIL: Failed to create loop devices with command: ${command}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
loop_dev_list=$(echo "${loop_dev_list}" | sed -e 's/ $//')
|
||||||
|
echo "${loop_dev_list}" #Back capability
|
||||||
|
loop_dev_list=$(echo "${loop_dev_list}" | sed -e 's/\/dev\///g')
|
||||||
|
RETURN_STR="${loop_dev_list}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_disks() {
|
||||||
|
|
||||||
|
disk_num=$1
|
||||||
|
disk_size=$2
|
||||||
|
|
||||||
|
LOOP_DEVICE_LIST=$(create_loop_devices $disk_num $disk_size)
|
||||||
|
for i in $(seq 1 $disk_num); do
|
||||||
|
disk_temp=$(echo $LOOP_DEVICE_LIST | cut -d " " -f $i)
|
||||||
|
disk_temp=$(echo $disk_temp | cut -d "/" -f 3)
|
||||||
|
devlist="$devlist $disk_temp"
|
||||||
|
done
|
||||||
|
|
||||||
|
RETURN_STR="$devlist"
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_disks() {
|
||||||
|
|
||||||
|
disks=$1
|
||||||
|
for disk in $disks; do
|
||||||
|
try_num=1
|
||||||
|
disk="/dev/"$disk
|
||||||
|
echo "losetup -d $disk"
|
||||||
|
losetup -d $disk
|
||||||
|
state=$?
|
||||||
|
while [ $state -ne 0 ]; do
|
||||||
|
if [ $try_num -eq 4 ]; then
|
||||||
|
echo "FAIL: After tried 3 times losetup -d $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
losetup -d $disk
|
||||||
|
state=$?
|
||||||
|
((try_num++))
|
||||||
|
done
|
||||||
|
|
||||||
|
done
|
||||||
|
rm -rf /tmp/loop.*
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local_clean(){
|
||||||
|
local md_name=""
|
||||||
|
(mdadm -E /dev/sd[b-i]1 |grep "raid") || (cat /proc/mdstat |grep "inactive") || (ls /dev/md* |egrep md[0-9]+)
|
||||||
|
if [ $? = 0 ];then
|
||||||
|
echo "have some md don't clean"
|
||||||
|
ls /dev/md* |egrep md[0-9]+
|
||||||
|
for md_name in "$(ls /dev/md* |egrep md[0-9]+)" ;do
|
||||||
|
trun "mdadm --stop $md_name"
|
||||||
|
sleep 5
|
||||||
|
tlog "$md_name have stop"
|
||||||
|
done
|
||||||
|
rm -rf /etc/mdadm.conf
|
||||||
|
trun "mdadm -Ss";sleep 5
|
||||||
|
trun "mdadm --zero-superblock /dev/sd[b-i]1"
|
||||||
|
trun "mdadm --zero-superblock /dev/sd[b-i]"
|
||||||
|
trun "cat /proc/mdstat"
|
||||||
|
lsblk
|
||||||
|
fi
|
||||||
|
echo "INFO:need to remove partition first"
|
||||||
|
for i in b c d e f g h i ;do
|
||||||
|
mdadm --zero-superblock "/dev/sd$i"
|
||||||
|
sleep 1
|
||||||
|
gdisk /dev/sd$i &> /dev/null <<EOF
|
||||||
|
d
|
||||||
|
3
|
||||||
|
d
|
||||||
|
2
|
||||||
|
d
|
||||||
|
1
|
||||||
|
w
|
||||||
|
Y
|
||||||
|
EOF
|
||||||
|
sleep 1
|
||||||
|
partprobe /dev/sd$i
|
||||||
|
done
|
||||||
|
|
||||||
|
tlog "have been remove all partition,check it"
|
||||||
|
lsblk;cat /proc/mdstat; ls /dev/md*
|
||||||
|
|
||||||
|
}
|
||||||
|
|
39
tests/md_raid_module/main.sh
Executable file
39
tests/md_raid_module/main.sh
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###this case just test raid modeule exit
|
||||||
|
source include.sh || exit 200
|
||||||
|
|
||||||
|
uname -a
|
||||||
|
|
||||||
|
for i in 0 1 456 10 ;do
|
||||||
|
tok "modprobe raid$i "
|
||||||
|
|
||||||
|
tok "lsmod |grep raid$i "
|
||||||
|
if [ $? = 0 ];then
|
||||||
|
echo "have insert raid0 to OS"
|
||||||
|
tok "modprobe -r raid$i"
|
||||||
|
sleep 5
|
||||||
|
tok "modprobe raid$i "
|
||||||
|
sleep 5
|
||||||
|
tok "modprobe -r raid$i"
|
||||||
|
sleep 5
|
||||||
|
tok "modprobe raid$i"
|
||||||
|
sleep 5
|
||||||
|
else
|
||||||
|
echo "have no inset this module"
|
||||||
|
tok "modprobe raid$i"
|
||||||
|
sleep 5
|
||||||
|
tok "modprobe -r raid$i"
|
||||||
|
sleep 5
|
||||||
|
tok "modprobe raid$i"
|
||||||
|
sleep 5
|
||||||
|
tok "modprobe -r raid$i"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
tend
|
||||||
|
|
||||||
|
|
||||||
|
|
266
tests/md_raid_module/tc.sh
Executable file
266
tests/md_raid_module/tc.sh
Executable file
@ -0,0 +1,266 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#test x$LXT_TC = x || return
|
||||||
|
#LXT_TC=1
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the current date
|
||||||
|
# usage: d=$(tdate)
|
||||||
|
#
|
||||||
|
tdate ()
|
||||||
|
{
|
||||||
|
date '+%T' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the log information
|
||||||
|
# usage: tlog "hello world" "WARNING"
|
||||||
|
#
|
||||||
|
tlog ()
|
||||||
|
{
|
||||||
|
local msg=$1
|
||||||
|
local log_level=${2:-INFO}
|
||||||
|
local cur_date=$(tdate)
|
||||||
|
|
||||||
|
echo "[$log_level][$cur_date]$msg"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# run the cmd and format the log. return the exitint status of cmd
|
||||||
|
# use the global variables: tSTDOUT and tSTDERR to return the stdout and stderr
|
||||||
|
# usage: trun "ls"
|
||||||
|
# trun "ls"; echo $?
|
||||||
|
# stdout=$tSTDOUT
|
||||||
|
# stderr=$tSTDERR
|
||||||
|
#
|
||||||
|
trun ()
|
||||||
|
{
|
||||||
|
local cmd="$*"
|
||||||
|
|
||||||
|
_trun_ "$cmd"
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, mark this checkpoint failed and return 1
|
||||||
|
# if not, mark it passed and return 0
|
||||||
|
# usage: tnot "ls /not_existing"
|
||||||
|
#
|
||||||
|
tnot () {
|
||||||
|
local cmd="$*"
|
||||||
|
_trun_ "$cmd" 1
|
||||||
|
if test $? -eq 0; then
|
||||||
|
tfail_ "$cmd" ;
|
||||||
|
else
|
||||||
|
tpass_ "$cmd" ;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, mark this checkpoint passed and return 0
|
||||||
|
# if not, mark it failed and return 1
|
||||||
|
# usage: tok "ls /"
|
||||||
|
#
|
||||||
|
tok ()
|
||||||
|
{
|
||||||
|
local cmd="$*"
|
||||||
|
_trun_ "$cmd" 0
|
||||||
|
if test $? -eq 0; then
|
||||||
|
tpass_ "$cmd" ;
|
||||||
|
else
|
||||||
|
tfail_ "$cmd" ;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, mark this checkpoint passed and return 0
|
||||||
|
# if not, mark it failes and exit
|
||||||
|
# usage: terr "ls"
|
||||||
|
#
|
||||||
|
#terr ()
|
||||||
|
#{
|
||||||
|
# tok "$*" || tend
|
||||||
|
#}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, will continue to run the script
|
||||||
|
# if not, mark it failes and exit
|
||||||
|
# usage: terr "ls"
|
||||||
|
#
|
||||||
|
terr ()
|
||||||
|
{
|
||||||
|
local cmd="$*"
|
||||||
|
_trun_ "$cmd" 0
|
||||||
|
if test $? -ne 0; then
|
||||||
|
tfail_ "$cmd" ;
|
||||||
|
tend ;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# exit the program and print the log message
|
||||||
|
# usage: texit "error message" 100
|
||||||
|
# similar to the exception
|
||||||
|
#
|
||||||
|
texit ()
|
||||||
|
{
|
||||||
|
msg=$1
|
||||||
|
err=$2
|
||||||
|
is_null $err && err=1
|
||||||
|
test $err -lt 1 || err=1
|
||||||
|
|
||||||
|
tlog "$msg" "ERROR"
|
||||||
|
exit $2
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the test report, cleanup the testing bed and close the testing.
|
||||||
|
# usage: tend
|
||||||
|
#
|
||||||
|
tend ()
|
||||||
|
{
|
||||||
|
local pcount=$(wc -l $tPASS_FILE | awk '{print $1}')
|
||||||
|
local fcount=$(wc -l $tFAIL_FILE | awk '{print $1}')
|
||||||
|
local total=$(( $pcount + $fcount ))
|
||||||
|
|
||||||
|
echo "#################################Test Report###############################"
|
||||||
|
echo "TOTAL : $total"
|
||||||
|
echo "PASSED : $pcount"
|
||||||
|
echo "FAILED : $fcount"
|
||||||
|
cat $tPASS_FILE $tFAIL_FILE
|
||||||
|
echo "###########################End of running $0########################"
|
||||||
|
|
||||||
|
#cleanup
|
||||||
|
rm -f $tPASS_FILE $tFAIL_FILE $tRETURN_FILE $tSTDERR_FILE
|
||||||
|
# rm -rf $LXT_TMP_DIR
|
||||||
|
if [[ $pcount -eq 0 ]] && [[ $total -eq 0 ]];then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
test $pcount -eq 0 && exit 1
|
||||||
|
test $pcount -eq $total && exit 0
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# private function
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the error message and call stack. return 1
|
||||||
|
#
|
||||||
|
tfail_ ()
|
||||||
|
{
|
||||||
|
local msg=$*
|
||||||
|
tlog "$msg" "ERROR" >>$tFAIL_FILE
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the sucessful message. return 0
|
||||||
|
#
|
||||||
|
tpass_ ()
|
||||||
|
{
|
||||||
|
local msg=$*
|
||||||
|
tlog "$msg" "PASS" >> $tPASS_FILE
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_trun_ ()
|
||||||
|
{
|
||||||
|
local cmd="$1"
|
||||||
|
local chk="$2"
|
||||||
|
local cur_date=$(tdate)
|
||||||
|
|
||||||
|
local stdout=$(eval "$cmd" 2>$tSTDERR_FILE; echo $? >$tRETURN_FILE 2>/dev/null)
|
||||||
|
#timeout -- how to set timeout?
|
||||||
|
local exit_status=$(< $tRETURN_FILE)
|
||||||
|
local stderr=$(< $tSTDERR_FILE)
|
||||||
|
local msg=CMD
|
||||||
|
#tnot
|
||||||
|
if test x$chk = x1; then
|
||||||
|
test $exit_status -eq 0 || msg=PASS
|
||||||
|
test $exit_status -eq 0 && msg=FAIL
|
||||||
|
#should let the tester know this is the negative testing
|
||||||
|
#if cmd return 0 we will return 1 and vice versa
|
||||||
|
cmd="[NOT] $cmd"
|
||||||
|
fi
|
||||||
|
#tok
|
||||||
|
if test x$chk = x0; then
|
||||||
|
test $exit_status -eq 0 && msg=PASS
|
||||||
|
test $exit_status -eq 0 || msg=FAIL
|
||||||
|
fi
|
||||||
|
|
||||||
|
tSTDOUT=$stdout
|
||||||
|
tSTDERR=$stderr
|
||||||
|
|
||||||
|
test $tIGNORE_STDOUT -eq 1 && stdout='redirect the stdout to /dev/null'
|
||||||
|
test $tIGNORE_STDERR -eq 1 && stderr='redirect the stderr to /dev/null'
|
||||||
|
|
||||||
|
echo "[$msg][$cur_date][$HOSTNAME]$cmd"
|
||||||
|
echo "STDOUT:"
|
||||||
|
test "x$stdout" = x || echo "$stdout"
|
||||||
|
echo "STDERR:$stderr"
|
||||||
|
echo "RETURN:$exit_status"
|
||||||
|
echo
|
||||||
|
|
||||||
|
return $exit_status
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# setup the testing environment
|
||||||
|
#
|
||||||
|
_tsetup_ ()
|
||||||
|
{
|
||||||
|
|
||||||
|
LXT_TMP_DIR="/mnt/testarea/lxt";
|
||||||
|
|
||||||
|
test -z "$HOSTNAME" && HOSTNAME=$(hostname)
|
||||||
|
test -d "$LXT_TMP_DIR" || mkdir -p "$LXT_TMP_DIR" >& /dev/null || exit 1
|
||||||
|
|
||||||
|
tSTDERR_FILE="$LXT_TMP_DIR/stderr.$$"
|
||||||
|
test -e "$tSTDERR_FILE" || > "$tSTDERR_FILE" || exit 1
|
||||||
|
tRETURN_FILE="$LXT_TMP_DIR/return.$$"
|
||||||
|
test -e "$tRETURN_FILE" || > "$tRETURN_FILE" || exit 1
|
||||||
|
tPASS_FILE="$LXT_TMP_DIR/tc.pass.$$"
|
||||||
|
test -e "$tPASS_FILE" || > "$tPASS_FILE" || exit 1
|
||||||
|
tFAIL_FILE="$LXT_TMP_DIR/tc.fail.$$"
|
||||||
|
test -e "$tFAIL_FILE" || > "$tFAIL_FILE" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# main
|
||||||
|
#
|
||||||
|
|
||||||
|
# global variables
|
||||||
|
tIGNORE_STDOUT=0
|
||||||
|
tIGNORE_STDERR=0
|
||||||
|
tSTDOUT=
|
||||||
|
tSTDERR=
|
||||||
|
#LXT_TMP_DIR
|
||||||
|
# only used in this file
|
||||||
|
tPASS_FILE=
|
||||||
|
tFAIL_FILE=
|
||||||
|
|
||||||
|
_tsetup_
|
674
tests/md_trim_support/LICENSE
Normal file
674
tests/md_trim_support/LICENSE
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
81
tests/md_trim_support/Makefile
Normal file
81
tests/md_trim_support/Makefile
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Copyright (c) 2006 Red Hat, Inc. All rights reserved. This copyrighted material
|
||||||
|
# is made available to anyone wishing to use, modify, copy, or
|
||||||
|
# redistribute it subject to the terms and conditions of the GNU General
|
||||||
|
# Public License v.2.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# Author: guazhang <guazhang@redhat.com>
|
||||||
|
|
||||||
|
# The toplevel namespace within which the test lives.
|
||||||
|
TOPLEVEL_NAMESPACE=kernel
|
||||||
|
|
||||||
|
# The name of the package under test:
|
||||||
|
PACKAGE_NAME=storage
|
||||||
|
|
||||||
|
# The path of the test below the package:
|
||||||
|
RELATIVE_PATH=mdadm/trim-support
|
||||||
|
|
||||||
|
# Version of the Test. Used with make tag.
|
||||||
|
export TESTVERSION=1.0
|
||||||
|
|
||||||
|
# The combined namespace of the test.
|
||||||
|
export TEST=/$(TOPLEVEL_NAMESPACE)/$(PACKAGE_NAME)/$(RELATIVE_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
# A phony target is one that is not really the name of a file.
|
||||||
|
# It is just a name for some commands to be executed when you
|
||||||
|
# make an explicit request. There are two reasons to use a
|
||||||
|
# phony target: to avoid a conflict with a file of the same
|
||||||
|
# name, and to improve performance.
|
||||||
|
.PHONY: all install download clean
|
||||||
|
|
||||||
|
# executables to be built should be added here,
|
||||||
|
# they will be generated on the system under test.
|
||||||
|
BUILT_FILES=
|
||||||
|
|
||||||
|
# data files, .c files, scripts anything needed to either compile the test
|
||||||
|
# and/or run it.
|
||||||
|
FILES=$(METADATA) include.sh Makefile PURPOSE main.sh tc.sh
|
||||||
|
|
||||||
|
run: $(FILES) build
|
||||||
|
./main.sh
|
||||||
|
|
||||||
|
build: $(BUILT_FILES)
|
||||||
|
# chmod a+x ./main.sh
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ *.rpm $(BUILT_FILES)
|
||||||
|
|
||||||
|
# You may need to add other targets e.g. to build executables from source code
|
||||||
|
# Add them here:
|
||||||
|
|
||||||
|
|
||||||
|
# Include Common Makefile
|
||||||
|
include /usr/share/rhts/lib/rhts-make.include
|
||||||
|
|
||||||
|
# Generate the testinfo.desc here:
|
||||||
|
$(METADATA): Makefile
|
||||||
|
@touch $(METADATA)
|
||||||
|
# Change to the test owner's name
|
||||||
|
@echo "Owner: guazhang <guazhang@redhat.com>" > $(METADATA)
|
||||||
|
@echo "Name: $(TEST)" >> $(METADATA)
|
||||||
|
@echo "Path: $(TEST_DIR)" >> $(METADATA)
|
||||||
|
@echo "License: GPLv3" >> $(METADATA)
|
||||||
|
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
|
||||||
|
@echo "Description: test the function trim support">> $(METADATA)
|
||||||
|
@echo "TestTime: 1h" >> $(METADATA)
|
||||||
|
@echo "RunFor: $(PACKAGE_NAME)" >> $(METADATA)
|
||||||
|
# add any other packages for which your test ought to run here
|
||||||
|
@echo "Requires: $(PACKAGE_NAME)" >> $(METADATA)
|
||||||
|
@echo "Requires: mdadm" >> $(METADATA)
|
||||||
|
# add any other requirements for the script to run here
|
||||||
|
|
||||||
|
# You may need other fields here; see the documentation
|
||||||
|
rhts-lint $(METADATA)
|
3
tests/md_trim_support/PURPOSE
Normal file
3
tests/md_trim_support/PURPOSE
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
PURPOSE of /tests/kernel/storage/mdadm/trim-support
|
||||||
|
Description: Test the function trim support.
|
||||||
|
Author: Xiao Ni <xni@redhat.com>
|
672
tests/md_trim_support/include.sh
Executable file
672
tests/md_trim_support/include.sh
Executable file
@ -0,0 +1,672 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Author: guazhang <guazhang@redhat.com>
|
||||||
|
|
||||||
|
source tc.sh || exit 1
|
||||||
|
|
||||||
|
rpm -q mdadm || yum install -y mdadm
|
||||||
|
JOURNAL_SUPPORT=0
|
||||||
|
info=`mdadm --create --help | grep -o "write-journal"`
|
||||||
|
if [ "$info" = "write-journal" ]; then
|
||||||
|
JOURNAL_SUPPORT=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Install fio from upstream
|
||||||
|
function install_fio() {
|
||||||
|
|
||||||
|
git_url=git://git.kernel.org/pub/scm/linux/kernel/git/axboe/fio.git
|
||||||
|
|
||||||
|
tok yum install libaio-devel zlib-devel -y
|
||||||
|
tok git clone $git_url
|
||||||
|
tlog "INFO: Installing Fio"
|
||||||
|
tok "cd fio &&./configure && make && make install"
|
||||||
|
tok which fio
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
tlog "FAIL: Fio not succesffully installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tlog "INFO: Fio succesfully installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
#Install dt
|
||||||
|
function install_dt () {
|
||||||
|
|
||||||
|
wget http://www.scsifaq.org/RMiller_Tools/ftp/dt/dt-source.tar.gz
|
||||||
|
tar xvf dt-source.tar.gz
|
||||||
|
cd dt.d-WIP/
|
||||||
|
cp -p Makefile.linux Makefile
|
||||||
|
make
|
||||||
|
cp dt /usr/bin
|
||||||
|
}
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Create_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# Create md raid.
|
||||||
|
# Parameter:
|
||||||
|
# $level # like 0, 1, 3, 5, 10, 50
|
||||||
|
# $dev_list # like 'sda sdb sdc sdd'
|
||||||
|
# $raid_dev_num # like 3
|
||||||
|
# $spar_dev_num # like 2
|
||||||
|
# $chunk # like 64
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $md_raid like '/dev/md0'
|
||||||
|
# MD_DEVS # $raid_dev_list like '/dev/sda /dev/sdb'
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Create_RAID (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo 'Usage: MD_Create_RAID $level $dev_list $raid_dev_num \
|
||||||
|
[$spar_dev_num] [$chunk]'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
# variable definitions
|
||||||
|
RETURN_STR=''
|
||||||
|
MD_DEVS=''
|
||||||
|
local level=$1
|
||||||
|
local dev_list=$2
|
||||||
|
local raid_dev_num=$3
|
||||||
|
local bitmap=$4
|
||||||
|
local spar_dev_num=${5:-0}
|
||||||
|
local chunk=${6:-512}
|
||||||
|
local bitmap_chunksize=${7:-64M}
|
||||||
|
local dev_num=0
|
||||||
|
local raid_dev=''
|
||||||
|
local spar_dev=''
|
||||||
|
local md_raid=""
|
||||||
|
local mtdata=${8:-1.2}
|
||||||
|
local ret=0
|
||||||
|
# start to create
|
||||||
|
echo "INFO: Executing MD_Create_RAID() to create raid $level"
|
||||||
|
# check if the given disks are more the needed
|
||||||
|
for i in $dev_list; do
|
||||||
|
dev_num=$((dev_num+1))
|
||||||
|
done
|
||||||
|
if [ $dev_num -lt $(($raid_dev_num+$spar_dev_num)) ]; then
|
||||||
|
echo "FAIL: Required devices are more than given."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# get free md device name, only scan /dev/md[0-15].
|
||||||
|
for i in `seq 1 30`; do
|
||||||
|
ls -l /dev/md$i > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
md_raid=/dev/md$i
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# get raid disk list.
|
||||||
|
for i in `seq 1 $raid_dev_num`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
raid_dev="$raid_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these raid devices \"$raid_dev\"."
|
||||||
|
# get spare disk list.
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
for i in `seq $((raid_dev_num+1)) $((raid_dev_num+spar_dev_num))`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
spar_dev="$spar_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these spare disks \"$spar_dev\"."
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
if [ $level -eq 1 ]; then
|
||||||
|
# create md raid1 without "--chunk"
|
||||||
|
if [ $bitmap -eq 1 ]; then
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev \
|
||||||
|
--bitmap=internal --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
else
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--bitmap=internal --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
fi
|
||||||
|
elif [ $bitmap -eq 2 ];then
|
||||||
|
touch /home/bitmap_md_$level
|
||||||
|
echo "INFO:bitmap backup in /home/bitmap_md_$level"
|
||||||
|
bitmap_dir="/home/bitmap_md_$level"
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev \
|
||||||
|
--bitmap=$bitmap_dir --force --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
else
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--bitmap=$bitmap_dir --force --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev"
|
||||||
|
else
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# create md raid
|
||||||
|
if [ $bitmap -eq 1 ]; then
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev --chunk $chunk \
|
||||||
|
--bitmap=internal --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
else
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev --chunk $chunk \
|
||||||
|
--bitmap=internal --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
fi
|
||||||
|
elif [ $bitmap -eq 2 ];then
|
||||||
|
touch /home/bitmap_md_$level
|
||||||
|
echo "INFO:bitmap backup in /home/bitmap_md_$level"
|
||||||
|
bitmap_dir="/home/bitmap_md_$level"
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev --chunk $chunk \
|
||||||
|
--bitmap=$bitmap_dir --force --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
else
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev --chunk $chunk \
|
||||||
|
--bitmap=$bitmap_dir --force --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev \
|
||||||
|
--spare-devices $spar_dev_num $spar_dev --chunk $chunk"
|
||||||
|
else
|
||||||
|
tok "mdadm --create --run $md_raid --level $level \
|
||||||
|
--metadata $mtdata \
|
||||||
|
--raid-devices $raid_dev_num $raid_dev --chunk $chunk"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
ret=$?
|
||||||
|
echo "INFO:create $md_raid failed.will remove all raid disk "
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "create `date +%s` mdadm -CR $md_raid -l $level -e $mtdata -n $raid_dev_num \"$raid_dev\" -x=$spar_dev_num $spar_dev bitmap=$bitmap --chunk $chunk --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
echo "INFO:cat /proc/mdstat######################"
|
||||||
|
cat /proc/mdstat
|
||||||
|
lsblk
|
||||||
|
trun "ls /dev/md* |egrep md[0-9]+"
|
||||||
|
echo "INFO:mdadm -D $md_raid #########################"
|
||||||
|
mdadm --detail $md_raid
|
||||||
|
# define global variables
|
||||||
|
MD_DEVS="$raid_dev $spar_dev"
|
||||||
|
RETURN_STR="$md_raid"
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Create_RAID
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Create_RAID_Journal ()
|
||||||
|
# Usage:
|
||||||
|
# Create md raid with journal.
|
||||||
|
# Parameter:
|
||||||
|
# $level # like 4, 5, 6
|
||||||
|
# $dev_list # like 'sda sdb sdc sdd'
|
||||||
|
# $raid_dev_num # like 3
|
||||||
|
# $spar_dev_num # like 2
|
||||||
|
# $chunk # like 64
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $md_raid like '/dev/md0'
|
||||||
|
# MD_DEVS # $raid_dev_list like '/dev/sda /dev/sdb'
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Create_RAID_Journal (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo 'Usage: MD_Create_RAID_Journal $level $dev_list $raid_dev_num \
|
||||||
|
[$spar_dev_num] [$chunk]'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
# variable definitions
|
||||||
|
RETURN_STR=''
|
||||||
|
MD_DEVS=''
|
||||||
|
local level=$1
|
||||||
|
local dev_list=$2
|
||||||
|
local raid_dev_num=$3
|
||||||
|
local bitmap=$4
|
||||||
|
local spar_dev_num=${5:-0}
|
||||||
|
local chunk=${6:-512}
|
||||||
|
local bitmap_chunksize=${7:-64M}
|
||||||
|
local mtdata=${8:-1.2}
|
||||||
|
local dev_num=0
|
||||||
|
local raid_dev=''
|
||||||
|
local spar_dev=''
|
||||||
|
local md_raid=""
|
||||||
|
local ret=0
|
||||||
|
# start to create
|
||||||
|
echo "INFO: Executing MD_Create_RAID_Journal() to create raid $level"
|
||||||
|
# check if the given disks are more the needed
|
||||||
|
for i in $dev_list; do
|
||||||
|
dev_num=$((dev_num+1))
|
||||||
|
done
|
||||||
|
if [ $dev_num -lt $(($raid_dev_num+$spar_dev_num)) ]; then
|
||||||
|
echo "FAIL: Required devices are more than given."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# get free md device name, only scan /dev/md[0-15].
|
||||||
|
for i in `seq 0 15`; do
|
||||||
|
ls -l /dev/md$i > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
md_raid=/dev/md$i
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# take the first disk as journal disk
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f 1`
|
||||||
|
journal_dev="/dev/$tmp_dev"
|
||||||
|
echo "INFO: Created md raid with write journal disk \"$journal_dev\"."
|
||||||
|
|
||||||
|
# get raid disk list.
|
||||||
|
for i in `seq 2 $raid_dev_num`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
raid_dev="$raid_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these raid devices \"$raid_dev\"."
|
||||||
|
|
||||||
|
# get spare disk list.
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
for i in `seq $((raid_dev_num+1)) $((raid_dev_num+spar_dev_num))`; do
|
||||||
|
tmp_dev=`echo $dev_list | cut -d " " -f $i`
|
||||||
|
spar_dev="$spar_dev /dev/$tmp_dev"
|
||||||
|
done
|
||||||
|
echo "INFO: Created md raid with these spare disks \"$spar_dev\"."
|
||||||
|
fi
|
||||||
|
|
||||||
|
#There is one write journal disk, so change the raid_dev_num--
|
||||||
|
((raid_dev_num--))
|
||||||
|
|
||||||
|
# create md raid
|
||||||
|
# prepare the parameter
|
||||||
|
BITMAP=""
|
||||||
|
SPAR_DEV=""
|
||||||
|
# if [ $bitmap -eq 1 ]; then
|
||||||
|
# BITMAP="--bitmap=internal --bitmap-chunk=$bitmap_chunksize"
|
||||||
|
# fi
|
||||||
|
if [ $spar_dev_num -ne 0 ]; then
|
||||||
|
SPAR_DEV="--spare-devices $spar_dev_num $spar_dev"
|
||||||
|
fi
|
||||||
|
if [ -n "$journal_dev" ]; then
|
||||||
|
WRITE_JOURNAL="--write-journal $journal_dev"
|
||||||
|
fi
|
||||||
|
tok "mdadm --create --run $md_raid --level $level --metadata $mtdata --raid-devices $raid_dev_num $raid_dev $WRITE_JOURNAL $SPAR_DEV $BITMAP --chunk $chunk"
|
||||||
|
ret=$?
|
||||||
|
echo "create raid time `date +%s` mdadm -CR $md_raid --level $level --metadata $mtdata --raid-devices $raid_dev_num $raid_dev $WRITE_JOURNAL $SPAR_DEV $BITMAP --chunk $chunk "
|
||||||
|
cat /proc/mdstat
|
||||||
|
mdadm --detail $md_raid
|
||||||
|
# define global variables
|
||||||
|
MD_DEVS="$journal_dev $raid_dev $spar_dev"
|
||||||
|
RETURN_STR="$md_raid"
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Create_RAID_Journal
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Save_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# Save md raid configuration.
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Save_RAID (){
|
||||||
|
echo "INFO: Executing MD_Save_RAID()"
|
||||||
|
echo "DEVICE $MD_DEVS" > /etc/mdadm.conf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: Failed to save md device info to /etc/mdadm.conf"
|
||||||
|
fi
|
||||||
|
mdadm --detail --scan >> /etc/mdadm.conf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: Failed to save md state info to /etc/mdadm.conf"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Save_RAID
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Clean_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# Clean md raid.
|
||||||
|
# Parameter:
|
||||||
|
# $md_name # like '/dev/md0'
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Clean_RAID (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo 'Usage: MD_Clean_RAID $md_name'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
echo "INFO: Executing MD_Clean_RAID() against this md device: $md_name"
|
||||||
|
local md_name=$1
|
||||||
|
echo "mdadm --stop $md_name"
|
||||||
|
mdadm --stop $md_name
|
||||||
|
st=$?
|
||||||
|
while [ $st -ne 0 ]; do
|
||||||
|
echo "INFO:mdadm stop failed"
|
||||||
|
sleep 10
|
||||||
|
rm -rf /etc/mdadm.conf
|
||||||
|
for i in $(cat /proc/mdstat |grep "inactive" |awk '{print $1}') ;do
|
||||||
|
mdadm --stop "/dev/$i"
|
||||||
|
done
|
||||||
|
mdadm --stop $md_name
|
||||||
|
st=$?
|
||||||
|
|
||||||
|
done
|
||||||
|
sleep 10
|
||||||
|
echo "clean devs : $MD_DEVS"
|
||||||
|
for dev in $MD_DEVS; do
|
||||||
|
echo "mdadm --zero-superblock $dev"
|
||||||
|
`mdadm --zero-superblock $dev`
|
||||||
|
done
|
||||||
|
#`mdadm --zero-superblock "$MD_DEVS"`
|
||||||
|
echo "ret is $?"
|
||||||
|
rm -rf /etc/mdadm.conf
|
||||||
|
sleep 10
|
||||||
|
echo "ls $md_name"
|
||||||
|
tnot "ls $md_name"
|
||||||
|
if [ $? = 1 ];then
|
||||||
|
tlog "mdadm --stop command can't delete md node name $md_name in /dev node"
|
||||||
|
trun "ls /dev/md*"
|
||||||
|
trun "cat /proc/mdstat"
|
||||||
|
else
|
||||||
|
tlog "mdadm --stop can delete md node name $md_name in /dev"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Clean_RAID
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_Get_State_RAID ()
|
||||||
|
# Usage:
|
||||||
|
# get md raid status
|
||||||
|
# Parameter:
|
||||||
|
# $md_name # like "/dev/md0"
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $state, like 'clean, resyncing'
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_Get_State_RAID (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo 'Usage: MD_Get_State_RAID $md_name'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
RETURN_STR=''
|
||||||
|
local md_name=$1
|
||||||
|
local state=''
|
||||||
|
local start_times=0
|
||||||
|
local end_times=0
|
||||||
|
local spend_times=0
|
||||||
|
# echo "INFO: Executing MD_Get_State_RAID() against this md array: $md_name"
|
||||||
|
start_times=$(date +%s)
|
||||||
|
echo " $start_times start_time against this md array: $md_name "
|
||||||
|
# echo "mdadm --detail $md_name | grep "State :" | cut -d ":" -f 2 | cut -d " " -f 2"
|
||||||
|
state=`mdadm --detail $md_name | grep "State :" | cut -d ":" -f 2 | cut -d " " -f 2`
|
||||||
|
sta=$?
|
||||||
|
if [ -z "$state" ]; then
|
||||||
|
echo "`date +%s` first_time_failed get raid statu #############################+++++++++++++++++++++++++"
|
||||||
|
while [ $sta ];do
|
||||||
|
state=`mdadm --detail $md_name | grep "State :" | cut -d ":" -f 2 | cut -d " " -f 2`
|
||||||
|
sta=$?
|
||||||
|
end_times=$(date +%s)
|
||||||
|
spend_times=$((end_times - start_times))
|
||||||
|
if [[ $spend_times -gt 10 ]];then
|
||||||
|
echo "get raid status spend $spend_times and exit "
|
||||||
|
ls /dev/md* |egrep md[0-9]+
|
||||||
|
cat /proc/mdstat
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$spend_times spend raid statu_time #############################"
|
||||||
|
fi
|
||||||
|
echo "state is $state"
|
||||||
|
RETURN_STR="$state"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_Get_State_RAID
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# MD_IO_Test ()
|
||||||
|
# Usage:
|
||||||
|
# IO test using dt against block level
|
||||||
|
# Parameter:
|
||||||
|
# $dt_target # like "/dev/md0"
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function MD_IO_Test (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo 'Usage: MD_IO_Test $dt_target'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
# this parameter should be change to 7200 during a real testing cycle
|
||||||
|
local dt_runtime=72
|
||||||
|
local dt_logfile=""
|
||||||
|
test -f /tmp/dt_XXXXXXXX.log || `mktemp /tmp/dt_XXXXXXXX.log`
|
||||||
|
dt_logfile="/tmp/dt_XXXXXXXX.log"
|
||||||
|
local dt_target=$1
|
||||||
|
echo -n "INFO: dt against ${dt_target} is running with "
|
||||||
|
echo "runtime: ${dt_runtime}s, log file is: ${dt_logfile}"
|
||||||
|
echo "dt slices=16 disable=eof,pstats flags=direct \
|
||||||
|
oncerr=abort min=b max=256k \
|
||||||
|
pattern=iot iodir=reverse prefix='%d@%h (pid %p)' \
|
||||||
|
of=${dt_target} log=${dt_logfile} \
|
||||||
|
runtime=${dt_runtime}"
|
||||||
|
`dt slices=16 disable=eof,pstats flags=direct \
|
||||||
|
oncerr=abort min=b max=256k \
|
||||||
|
pattern=iot iodir=reverse prefix='%d@%h (pid %p)' \
|
||||||
|
of=${dt_target} log=${dt_logfile} \
|
||||||
|
runtime=${dt_runtime}`
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: Failed to run dt testing against $dt_target"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
####################### End of functoin MD_IO_Test
|
||||||
|
|
||||||
|
function create_loop_devices (){
|
||||||
|
Create_Loop_Devices $@
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Create_Loop_Devices ()
|
||||||
|
# Usage:
|
||||||
|
# Create loop devices. We will find out the free number
|
||||||
|
# of loop to bind on tmp file.
|
||||||
|
# Parameter:
|
||||||
|
# $count #like "12"
|
||||||
|
# $size_mib #like "1024"
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR like 'loop9 loop10'
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
|
||||||
|
function Create_Loop_Devices (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -ne 2 ]; then
|
||||||
|
echo 'Usage: Create_Loop_Devices $count $size_mib'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
RETURN_STR=''
|
||||||
|
local count="$1"
|
||||||
|
local size_mib="$2"
|
||||||
|
local loop_dev_list=''
|
||||||
|
for X in `seq 1 ${count}`;do
|
||||||
|
local loop_file_name=$(mktemp /root/loop.XXXXXX)
|
||||||
|
dd if=/dev/zero of=${loop_file_name} count=$size_mib bs=1M 1>/dev/null 2>&1
|
||||||
|
local loop_dev_name=$(losetup -f)
|
||||||
|
#BUG: RHEL5 only support 8 loop device and we need to check whether we are run out of it
|
||||||
|
local command="losetup ${loop_dev_name} ${loop_file_name} 1>/dev/null 2>&1"
|
||||||
|
eval "${command}"
|
||||||
|
if [ $? -eq 0 ];then
|
||||||
|
loop_dev_list="${loop_dev_list}${loop_dev_name} "
|
||||||
|
else
|
||||||
|
echo "FAIL: Failed to create loop devices with command: ${command}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
loop_dev_list=$(echo "${loop_dev_list}" | sed -e 's/ $//')
|
||||||
|
echo "${loop_dev_list}" #Back capability
|
||||||
|
loop_dev_list=$(echo "${loop_dev_list}" | sed -e 's/\/dev\///g')
|
||||||
|
RETURN_STR="${loop_dev_list}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_disks() {
|
||||||
|
|
||||||
|
disk_num=$1
|
||||||
|
disk_size=$2
|
||||||
|
|
||||||
|
LOOP_DEVICE_LIST=$(create_loop_devices $disk_num $disk_size)
|
||||||
|
for i in $(seq 1 $disk_num); do
|
||||||
|
disk_temp=$(echo $LOOP_DEVICE_LIST | cut -d " " -f $i)
|
||||||
|
disk_temp=$(echo $disk_temp | cut -d "/" -f 3)
|
||||||
|
devlist="$devlist $disk_temp"
|
||||||
|
done
|
||||||
|
|
||||||
|
RETURN_STR="$devlist"
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_disks() {
|
||||||
|
|
||||||
|
disks=$1
|
||||||
|
for disk in $disks; do
|
||||||
|
try_num=1
|
||||||
|
disk="/dev/"$disk
|
||||||
|
echo "losetup -d $disk"
|
||||||
|
losetup -d $disk
|
||||||
|
state=$?
|
||||||
|
while [ $state -ne 0 ]; do
|
||||||
|
if [ $try_num -eq 4 ]; then
|
||||||
|
echo "FAIL: After tried 3 times losetup -d $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
losetup -d $disk
|
||||||
|
state=$?
|
||||||
|
((try_num++))
|
||||||
|
done
|
||||||
|
done
|
||||||
|
rm -rf /root/loop.*
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local_clean(){
|
||||||
|
local md_name=""
|
||||||
|
(mdadm -E /dev/sd[b-i]1 |grep "raid") || (cat /proc/mdstat |grep "inactive") || (ls /dev/md* |egrep md[0-9]+)
|
||||||
|
if [ $? = 0 ];then
|
||||||
|
echo "have some md don't clean"
|
||||||
|
ls /dev/md* |egrep md[0-9]+
|
||||||
|
for md_name in "$(ls /dev/md* |egrep md[0-9]+)" ;do
|
||||||
|
trun "mdadm --stop $md_name"
|
||||||
|
sleep 5
|
||||||
|
tlog "$md_name have stop"
|
||||||
|
done
|
||||||
|
rm -rf /etc/mdadm.conf
|
||||||
|
trun "mdadm -Ss";sleep 5
|
||||||
|
trun "mdadm --zero-superblock /dev/sd[b-i]1"
|
||||||
|
trun "mdadm --zero-superblock /dev/sd[b-i]"
|
||||||
|
trun "cat /proc/mdstat"
|
||||||
|
lsblk
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "INFO:need to remove partition first"
|
||||||
|
for i in b c d e f g h i ;do
|
||||||
|
mdadm --zero-superblock "/dev/sd$i"
|
||||||
|
sleep 1
|
||||||
|
gdisk /dev/sd$i &> /dev/null <<EOF
|
||||||
|
d
|
||||||
|
3
|
||||||
|
d
|
||||||
|
2
|
||||||
|
d
|
||||||
|
1
|
||||||
|
w
|
||||||
|
Y
|
||||||
|
EOF
|
||||||
|
sleep 1
|
||||||
|
partprobe /dev/sd$i
|
||||||
|
done
|
||||||
|
|
||||||
|
tlog "have been remove all partition,check it"
|
||||||
|
lsblk;cat /proc/mdstat; ls /dev/md*
|
||||||
|
|
||||||
|
}
|
||||||
|
|
140
tests/md_trim_support/main.sh
Executable file
140
tests/md_trim_support/main.sh
Executable file
@ -0,0 +1,140 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#
|
||||||
|
# runtest.sh of /tests/kernel/storage/mdadm/trim-support
|
||||||
|
# Description: test the function trim support.
|
||||||
|
# Author: Xiao Ni <xni@redhat.com>
|
||||||
|
#
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#
|
||||||
|
# Copyright (c) 2011 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This copyrighted material is made available to anyone wishing
|
||||||
|
# to use, modify, copy, or redistribute it subject to the terms
|
||||||
|
# and conditions of the GNU General Public License version 2.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be
|
||||||
|
# useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE. See the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public
|
||||||
|
# License along with this program; if not, write to the Free
|
||||||
|
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#set -x
|
||||||
|
# Include Beaker environment
|
||||||
|
. /usr/bin/rhts-environment.sh
|
||||||
|
. /usr/lib/beakerlib/beakerlib.sh
|
||||||
|
|
||||||
|
# Include Storage related environment
|
||||||
|
. include.sh || exit 200
|
||||||
|
|
||||||
|
function Stop_Raid (){
|
||||||
|
tok mdadm --stop "$MD_RAID"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
tlog "FAIL: fail to stop md raid $MD_RAID."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function runtest (){
|
||||||
|
|
||||||
|
# tok rmmod raid456
|
||||||
|
tok modprobe raid456 devices_handle_discard_safely=Y
|
||||||
|
tok "echo Y >/sys/module/raid456/parameters/devices_handle_discard_safely"
|
||||||
|
# info=`cat /etc/redhat-release | grep -oE "7.2|7.3"`
|
||||||
|
# if [ -n "$info" ]; then
|
||||||
|
trun "modprobe raid0 devices_discard_performance=Y"
|
||||||
|
trun "echo Y >/sys/module/raid0/parameters/devices_discard_performance"
|
||||||
|
# fi
|
||||||
|
devlist=''
|
||||||
|
|
||||||
|
which mkfs.xfs
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
FILESYS="xfs"
|
||||||
|
else
|
||||||
|
FILESYS="ext4"
|
||||||
|
fi
|
||||||
|
|
||||||
|
disk_num=6
|
||||||
|
#disk size M
|
||||||
|
disk_size=500
|
||||||
|
get_disks $disk_num $disk_size
|
||||||
|
devlist=$RETURN_STR
|
||||||
|
|
||||||
|
if [ $JOURNAL_SUPPORT -eq 1 ]; then
|
||||||
|
RAID_LIST="0 1 4 5 6 4-j 5-j 6-j 10"
|
||||||
|
else
|
||||||
|
RAID_LIST="0 1 4 5 6 10"
|
||||||
|
fi
|
||||||
|
for level in $RAID_LIST; do
|
||||||
|
|
||||||
|
RETURN_STR=''
|
||||||
|
MD_RAID=''
|
||||||
|
MD_DEV_LIST=''
|
||||||
|
raid_num=5
|
||||||
|
if [ "$level" = "0" ];then
|
||||||
|
spare_num=0
|
||||||
|
bitmap=0
|
||||||
|
else
|
||||||
|
spare_num=1
|
||||||
|
bitmap=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $level =~ "j" ]]; then
|
||||||
|
MD_Create_RAID_Journal ${level:0:1} "$devlist" $raid_num $bitmap $spare_num
|
||||||
|
else
|
||||||
|
MD_Create_RAID $level "$devlist" $raid_num $bitmap $spare_num
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -ne 0 ];then
|
||||||
|
tlog "FAIL: Failed to create md raid $RETURN_STR"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
tlog "INFO: Successfully created md raid $RETURN_STR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MD_RAID=$RETURN_STR
|
||||||
|
|
||||||
|
MD_Get_State_RAID $MD_RAID
|
||||||
|
state=$RETURN_STR
|
||||||
|
|
||||||
|
while [[ $state != "active" && $state != "clean" ]]; do
|
||||||
|
sleep 5
|
||||||
|
MD_Get_State_RAID $MD_RAID
|
||||||
|
state=$RETURN_STR
|
||||||
|
done
|
||||||
|
|
||||||
|
tlog "mkfs -t $FILESYS $MD_RAID"
|
||||||
|
(mkfs -t $FILESYS $MD_RAID) || (mkfs -t $FILESYS -f $MD_RAID)
|
||||||
|
if [ ! -d /mnt/md_test ]; then
|
||||||
|
mkdir /mnt/md_test
|
||||||
|
fi
|
||||||
|
tok mount -t $FILESYS $MD_RAID /mnt/md_test
|
||||||
|
tok fstrim -v /mnt/md_test
|
||||||
|
if [ $? -ne 0 ];then
|
||||||
|
tlog "fstrim -v /mnt/md_test failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tok umount $MD_RAID
|
||||||
|
MD_Clean_RAID $MD_RAID
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
remove_disks "$devlist"
|
||||||
|
if [ $? -ne 0 ];then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tlog "running $0"
|
||||||
|
trun "rpm -q mdadm || yum install -y mdadm"
|
||||||
|
trun "uname -a"
|
||||||
|
runtest
|
||||||
|
|
||||||
|
tend
|
266
tests/md_trim_support/tc.sh
Executable file
266
tests/md_trim_support/tc.sh
Executable file
@ -0,0 +1,266 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#test x$LXT_TC = x || return
|
||||||
|
#LXT_TC=1
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the current date
|
||||||
|
# usage: d=$(tdate)
|
||||||
|
#
|
||||||
|
tdate ()
|
||||||
|
{
|
||||||
|
date '+%T' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the log information
|
||||||
|
# usage: tlog "hello world" "WARNING"
|
||||||
|
#
|
||||||
|
tlog ()
|
||||||
|
{
|
||||||
|
local msg=$1
|
||||||
|
local log_level=${2:-INFO}
|
||||||
|
local cur_date=$(tdate)
|
||||||
|
|
||||||
|
echo "[$log_level][$cur_date]$msg"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# run the cmd and format the log. return the exitint status of cmd
|
||||||
|
# use the global variables: tSTDOUT and tSTDERR to return the stdout and stderr
|
||||||
|
# usage: trun "ls"
|
||||||
|
# trun "ls"; echo $?
|
||||||
|
# stdout=$tSTDOUT
|
||||||
|
# stderr=$tSTDERR
|
||||||
|
#
|
||||||
|
trun ()
|
||||||
|
{
|
||||||
|
local cmd="$*"
|
||||||
|
|
||||||
|
_trun_ "$cmd"
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, mark this checkpoint failed and return 1
|
||||||
|
# if not, mark it passed and return 0
|
||||||
|
# usage: tnot "ls /not_existing"
|
||||||
|
#
|
||||||
|
tnot () {
|
||||||
|
local cmd="$*"
|
||||||
|
_trun_ "$cmd" 1
|
||||||
|
if test $? -eq 0; then
|
||||||
|
tfail_ "$cmd" ;
|
||||||
|
else
|
||||||
|
tpass_ "$cmd" ;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, mark this checkpoint passed and return 0
|
||||||
|
# if not, mark it failed and return 1
|
||||||
|
# usage: tok "ls /"
|
||||||
|
#
|
||||||
|
tok ()
|
||||||
|
{
|
||||||
|
local cmd="$*"
|
||||||
|
_trun_ "$cmd" 0
|
||||||
|
if test $? -eq 0; then
|
||||||
|
tpass_ "$cmd" ;
|
||||||
|
else
|
||||||
|
tfail_ "$cmd" ;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, mark this checkpoint passed and return 0
|
||||||
|
# if not, mark it failes and exit
|
||||||
|
# usage: terr "ls"
|
||||||
|
#
|
||||||
|
#terr ()
|
||||||
|
#{
|
||||||
|
# tok "$*" || tend
|
||||||
|
#}
|
||||||
|
|
||||||
|
#
|
||||||
|
# verify the execution of command
|
||||||
|
# if the cmd return 0, will continue to run the script
|
||||||
|
# if not, mark it failes and exit
|
||||||
|
# usage: terr "ls"
|
||||||
|
#
|
||||||
|
terr ()
|
||||||
|
{
|
||||||
|
local cmd="$*"
|
||||||
|
_trun_ "$cmd" 0
|
||||||
|
if test $? -ne 0; then
|
||||||
|
tfail_ "$cmd" ;
|
||||||
|
tend ;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# exit the program and print the log message
|
||||||
|
# usage: texit "error message" 100
|
||||||
|
# similar to the exception
|
||||||
|
#
|
||||||
|
texit ()
|
||||||
|
{
|
||||||
|
msg=$1
|
||||||
|
err=$2
|
||||||
|
is_null $err && err=1
|
||||||
|
test $err -lt 1 || err=1
|
||||||
|
|
||||||
|
tlog "$msg" "ERROR"
|
||||||
|
exit $2
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the test report, cleanup the testing bed and close the testing.
|
||||||
|
# usage: tend
|
||||||
|
#
|
||||||
|
tend ()
|
||||||
|
{
|
||||||
|
local pcount=$(wc -l $tPASS_FILE | awk '{print $1}')
|
||||||
|
local fcount=$(wc -l $tFAIL_FILE | awk '{print $1}')
|
||||||
|
local total=$(( $pcount + $fcount ))
|
||||||
|
|
||||||
|
echo "#################################Test Report###############################"
|
||||||
|
echo "TOTAL : $total"
|
||||||
|
echo "PASSED : $pcount"
|
||||||
|
echo "FAILED : $fcount"
|
||||||
|
cat $tPASS_FILE $tFAIL_FILE
|
||||||
|
echo "###########################End of running $0########################"
|
||||||
|
|
||||||
|
#cleanup
|
||||||
|
rm -f $tPASS_FILE $tFAIL_FILE $tRETURN_FILE $tSTDERR_FILE
|
||||||
|
# rm -rf $LXT_TMP_DIR
|
||||||
|
if [[ $pcount -eq 0 ]] && [[ $total -eq 0 ]];then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
test $pcount -eq 0 && exit 1
|
||||||
|
test $pcount -eq $total && exit 0
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# private function
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the error message and call stack. return 1
|
||||||
|
#
|
||||||
|
tfail_ ()
|
||||||
|
{
|
||||||
|
local msg=$*
|
||||||
|
tlog "$msg" "ERROR" >>$tFAIL_FILE
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# print the sucessful message. return 0
|
||||||
|
#
|
||||||
|
tpass_ ()
|
||||||
|
{
|
||||||
|
local msg=$*
|
||||||
|
tlog "$msg" "PASS" >> $tPASS_FILE
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_trun_ ()
|
||||||
|
{
|
||||||
|
local cmd="$1"
|
||||||
|
local chk="$2"
|
||||||
|
local cur_date=$(tdate)
|
||||||
|
|
||||||
|
local stdout=$(eval "$cmd" 2>$tSTDERR_FILE; echo $? >$tRETURN_FILE 2>/dev/null)
|
||||||
|
#timeout -- how to set timeout?
|
||||||
|
local exit_status=$(< $tRETURN_FILE)
|
||||||
|
local stderr=$(< $tSTDERR_FILE)
|
||||||
|
local msg=CMD
|
||||||
|
#tnot
|
||||||
|
if test x$chk = x1; then
|
||||||
|
test $exit_status -eq 0 || msg=PASS
|
||||||
|
test $exit_status -eq 0 && msg=FAIL
|
||||||
|
#should let the tester know this is the negative testing
|
||||||
|
#if cmd return 0 we will return 1 and vice versa
|
||||||
|
cmd="[NOT] $cmd"
|
||||||
|
fi
|
||||||
|
#tok
|
||||||
|
if test x$chk = x0; then
|
||||||
|
test $exit_status -eq 0 && msg=PASS
|
||||||
|
test $exit_status -eq 0 || msg=FAIL
|
||||||
|
fi
|
||||||
|
|
||||||
|
tSTDOUT=$stdout
|
||||||
|
tSTDERR=$stderr
|
||||||
|
|
||||||
|
test $tIGNORE_STDOUT -eq 1 && stdout='redirect the stdout to /dev/null'
|
||||||
|
test $tIGNORE_STDERR -eq 1 && stderr='redirect the stderr to /dev/null'
|
||||||
|
|
||||||
|
echo "[$msg][$cur_date][$HOSTNAME]$cmd"
|
||||||
|
echo "STDOUT:"
|
||||||
|
test "x$stdout" = x || echo "$stdout"
|
||||||
|
echo "STDERR:$stderr"
|
||||||
|
echo "RETURN:$exit_status"
|
||||||
|
echo
|
||||||
|
|
||||||
|
return $exit_status
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# setup the testing environment
|
||||||
|
#
|
||||||
|
_tsetup_ ()
|
||||||
|
{
|
||||||
|
|
||||||
|
LXT_TMP_DIR="/mnt/testarea/lxt";
|
||||||
|
|
||||||
|
test -z "$HOSTNAME" && HOSTNAME=$(hostname)
|
||||||
|
test -d "$LXT_TMP_DIR" || mkdir -p "$LXT_TMP_DIR" >& /dev/null || exit 1
|
||||||
|
|
||||||
|
tSTDERR_FILE="$LXT_TMP_DIR/stderr.$$"
|
||||||
|
test -e "$tSTDERR_FILE" || > "$tSTDERR_FILE" || exit 1
|
||||||
|
tRETURN_FILE="$LXT_TMP_DIR/return.$$"
|
||||||
|
test -e "$tRETURN_FILE" || > "$tRETURN_FILE" || exit 1
|
||||||
|
tPASS_FILE="$LXT_TMP_DIR/tc.pass.$$"
|
||||||
|
test -e "$tPASS_FILE" || > "$tPASS_FILE" || exit 1
|
||||||
|
tFAIL_FILE="$LXT_TMP_DIR/tc.fail.$$"
|
||||||
|
test -e "$tFAIL_FILE" || > "$tFAIL_FILE" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# main
|
||||||
|
#
|
||||||
|
|
||||||
|
# global variables
|
||||||
|
tIGNORE_STDOUT=0
|
||||||
|
tIGNORE_STDERR=0
|
||||||
|
tSTDOUT=
|
||||||
|
tSTDERR=
|
||||||
|
#LXT_TMP_DIR
|
||||||
|
# only used in this file
|
||||||
|
tPASS_FILE=
|
||||||
|
tFAIL_FILE=
|
||||||
|
|
||||||
|
_tsetup_
|
21
tests/tests.yml
Normal file
21
tests/tests.yml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
# No tests suitable for container environment
|
||||||
|
# No tests suitable for atomic environment
|
||||||
|
#
|
||||||
|
# Tests suitable for classic environment
|
||||||
|
- hosts: localhost
|
||||||
|
roles:
|
||||||
|
- role: standard-test-basic
|
||||||
|
tags:
|
||||||
|
- classic
|
||||||
|
tests:
|
||||||
|
- md_raid_module:
|
||||||
|
run: ./main.sh
|
||||||
|
- md_trim_support:
|
||||||
|
run: ./main.sh
|
||||||
|
required_packages:
|
||||||
|
- mdadm
|
||||||
|
- make
|
||||||
|
- which
|
||||||
|
- kmod
|
||||||
|
- e2fsprogs
|
Loading…
Reference in New Issue
Block a user