From: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
To: linux-raid@vger.kernel.org
Cc: Jes.Sorensen@redhat.com, Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Subject: [PATCH v3 1/9] imsm: parse bad block log in metadata on startup
Date: Tue, 29 Nov 2016 16:40:11 +0100 [thread overview]
Message-ID: <1480434011-4866-1-git-send-email-tomasz.majchrzak@intel.com> (raw)
In-Reply-To: <1480424555-31509-2-git-send-email-tomasz.majchrzak@intel.com>
Always allocate memory for all log entries to avoid a need for memory
allocation when monitor requests to record a bad block.
Also some extra checks added to make static code analyzer happy.
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
---
super-intel.c | 140 +++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 94 insertions(+), 46 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 5740088..eeeca24 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -218,22 +218,24 @@ struct imsm_super {
} __attribute__ ((packed));
#define BBM_LOG_MAX_ENTRIES 254
+#define BBM_LOG_MAX_LBA_ENTRY_VAL 256 /* Represents 256 LBAs */
+#define BBM_LOG_SIGNATURE 0xabadb10c
+
+struct bbm_log_block_addr {
+ __u16 w1;
+ __u32 dw1;
+} __attribute__ ((__packed__));
struct bbm_log_entry {
- __u64 defective_block_start;
-#define UNREADABLE 0xFFFFFFFF
- __u32 spare_block_offset;
- __u16 remapped_marked_count;
- __u16 disk_ordinal;
+ __u8 marked_count; /* Number of blocks marked - 1 */
+ __u8 disk_ordinal; /* Disk entry within the imsm_super */
+ struct bbm_log_block_addr defective_block_start;
} __attribute__ ((__packed__));
struct bbm_log {
__u32 signature; /* 0xABADB10C */
__u32 entry_count;
- __u32 reserved_spare_block_count; /* 0 */
- __u32 reserved; /* 0xFFFF */
- __u64 first_spare_lba;
- struct bbm_log_entry mapped_block_entries[BBM_LOG_MAX_ENTRIES];
+ struct bbm_log_entry marked_block_entries[BBM_LOG_MAX_ENTRIES];
} __attribute__ ((__packed__));
#ifndef MDASSEMBLE
@@ -788,6 +790,74 @@ static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index)
return NULL;
}
+static inline unsigned long long __le48_to_cpu(const struct bbm_log_block_addr
+ *addr)
+{
+ return ((((__u64)__le32_to_cpu(addr->dw1)) << 16) |
+ __le16_to_cpu(addr->w1));
+}
+
+static inline struct bbm_log_block_addr __cpu_to_le48(unsigned long long sec)
+{
+ struct bbm_log_block_addr addr;
+
+ addr.w1 = __cpu_to_le16((__u16)(sec & 0xffff));
+ addr.dw1 = __cpu_to_le32((__u32)(sec >> 16) & 0xffffffff);
+ return addr;
+}
+
+#ifndef MDASSEMBLE
+/* get size of the bbm log */
+static __u32 get_imsm_bbm_log_size(struct bbm_log *log)
+{
+ if (!log || log->entry_count == 0)
+ return 0;
+
+ return sizeof(log->signature) +
+ sizeof(log->entry_count) +
+ log->entry_count * sizeof(struct bbm_log_entry);
+}
+#endif /* MDASSEMBLE */
+
+/* allocate and load BBM log from metadata */
+static int load_bbm_log(struct intel_super *super)
+{
+ struct imsm_super *mpb = super->anchor;
+ __u32 bbm_log_size = __le32_to_cpu(mpb->bbm_log_size);
+
+ super->bbm_log = xcalloc(1, sizeof(struct bbm_log));
+ if (!super->bbm_log)
+ return 1;
+
+ if (bbm_log_size) {
+ struct bbm_log *log = (void *)mpb +
+ __le32_to_cpu(mpb->mpb_size) - bbm_log_size;
+
+ __u32 entry_count;
+
+ if (bbm_log_size < sizeof(log->signature) +
+ sizeof(log->entry_count))
+ return 2;
+
+ entry_count = __le32_to_cpu(log->entry_count);
+ if ((__le32_to_cpu(log->signature) != BBM_LOG_SIGNATURE) ||
+ (entry_count > BBM_LOG_MAX_ENTRIES))
+ return 3;
+
+ if (bbm_log_size !=
+ sizeof(log->signature) + sizeof(log->entry_count) +
+ entry_count * sizeof(struct bbm_log_entry))
+ return 4;
+
+ memcpy(super->bbm_log, log, bbm_log_size);
+ } else {
+ super->bbm_log->signature = __cpu_to_le32(BBM_LOG_SIGNATURE);
+ super->bbm_log->entry_count = 0;
+ }
+
+ return 0;
+}
+
/*
* for second_map:
* == MAP_0 get first map
@@ -1546,7 +1616,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
printf(" Disks : %d\n", mpb->num_disks);
printf(" RAID Devices : %d\n", mpb->num_raid_devs);
print_imsm_disk(__get_imsm_disk(mpb, super->disks->index), super->disks->index, reserved);
- if (super->bbm_log) {
+ if (get_imsm_bbm_log_size(super->bbm_log)) {
struct bbm_log *log = super->bbm_log;
printf("\n");
@@ -1554,9 +1624,6 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
printf(" Log Size : %d\n", __le32_to_cpu(mpb->bbm_log_size));
printf(" Signature : %x\n", __le32_to_cpu(log->signature));
printf(" Entry Count : %d\n", __le32_to_cpu(log->entry_count));
- printf(" Spare Blocks : %d\n", __le32_to_cpu(log->reserved_spare_block_count));
- printf(" First Spare : %llx\n",
- (unsigned long long) __le64_to_cpu(log->first_spare_lba));
}
for (i = 0; i < mpb->num_raid_devs; i++) {
struct mdinfo info;
@@ -3757,19 +3824,6 @@ static int parse_raid_devices(struct intel_super *super)
return 0;
}
-/* retrieve a pointer to the bbm log which starts after all raid devices */
-struct bbm_log *__get_imsm_bbm_log(struct imsm_super *mpb)
-{
- void *ptr = NULL;
-
- if (__le32_to_cpu(mpb->bbm_log_size)) {
- ptr = mpb;
- ptr += mpb->mpb_size - __le32_to_cpu(mpb->bbm_log_size);
- }
-
- return ptr;
-}
-
/*******************************************************************************
* Function: check_mpb_migr_compatibility
* Description: Function checks for unsupported migration features:
@@ -3922,12 +3976,6 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
return 3;
}
- /* FIXME the BBM log is disk specific so we cannot use this global
- * buffer for all disks. Ok for now since we only look at the global
- * bbm_log_size parameter to gate assembly
- */
- super->bbm_log = __get_imsm_bbm_log(super->anchor);
-
return 0;
}
@@ -3973,6 +4021,9 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd
if (err)
return err;
err = parse_raid_devices(super);
+ if (err)
+ return err;
+ err = load_bbm_log(super);
clear_hi(super);
return err;
}
@@ -4037,6 +4088,8 @@ static void __free_imsm(struct intel_super *super, int free_disks)
free(elem);
elem = next;
}
+ if (super->bbm_log)
+ free(super->bbm_log);
super->hba = NULL;
}
@@ -4643,7 +4696,7 @@ static int get_super_block(struct intel_super **super_list, char *devnm, char *d
*super_list = s;
} else {
if (s)
- free(s);
+ free_imsm(s);
if (dfd >= 0)
close(dfd);
}
@@ -4706,6 +4759,8 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
super = alloc_super();
get_dev_sector_size(fd, NULL, &super->sector_size);
+ if (!super)
+ return 1;
/* Load hba and capabilities if they exist.
* But do not preclude loading metadata in case capabilities or hba are
* non-compliant and ignore_hw_compat is set.
@@ -5050,7 +5105,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
super = alloc_super();
if (super &&
posix_memalign(&super->buf, MAX_SECTOR_SIZE, mpb_size) != 0) {
- free(super);
+ free_imsm(super);
super = NULL;
}
if (!super) {
@@ -5061,7 +5116,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE) != 0) {
pr_err("could not allocate migr_rec buffer\n");
free(super->buf);
- free(super);
+ free_imsm(super);
return 0;
}
memset(super->buf, 0, mpb_size);
@@ -5656,11 +5711,6 @@ static int store_super_imsm(struct supertype *st, int fd)
#endif
}
-static int imsm_bbm_log_size(struct imsm_super *mpb)
-{
- return __le32_to_cpu(mpb->bbm_log_size);
-}
-
#ifndef MDASSEMBLE
static int validate_geometry_imsm_container(struct supertype *st, int level,
int layout, int raiddisks, int chunk,
@@ -5696,6 +5746,10 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
* note that there is no fd for the disks in array.
*/
super = alloc_super();
+ if (!super) {
+ close(fd);
+ return 0;
+ }
if (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
close(fd);
free_imsm(super);
@@ -6933,12 +6987,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n");
}
- /* check for bad blocks */
- if (imsm_bbm_log_size(super->anchor)) {
- pr_err("BBM log found in IMSM metadata.Arrays activation is blocked.\n");
- sb_errors = 1;
- }
-
/* count spare devices, not used in maps
*/
for (d = super->disks; d; d = d->next)
--
1.8.3.1
next prev parent reply other threads:[~2016-11-29 15:40 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-29 13:02 [PATCH v2 0/9] Bad block support for IMSM metadata Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 1/9] imsm: parse bad block log in metadata on startup Tomasz Majchrzak
2016-11-29 15:40 ` Tomasz Majchrzak [this message]
2016-11-29 13:02 ` [PATCH v2 2/9] imsm: write bad block log on metadata sync Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 3/9] imsm: give md list of known bad blocks on startup Tomasz Majchrzak
2016-11-29 22:27 ` Jes Sorensen
2016-11-30 8:41 ` [PATCH v3 " Tomasz Majchrzak
2016-11-30 8:51 ` [PATCH v2 " Tomasz Majchrzak
2016-12-01 22:33 ` Jes Sorensen
2016-11-29 13:02 ` [PATCH v2 4/9] imsm: record new bad block in bad block log Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 5/9] imsm: clear bad block from " Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 6/9] imsm: clear bad blocks if disk becomes unavailable Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 7/9] imsm: provide list of bad blocks for an array Tomasz Majchrzak
2016-12-01 22:34 ` Jes Sorensen
2016-12-02 12:54 ` [PATCH v3 " Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 8/9] imsm: implement "--examine-badblocks" command Tomasz Majchrzak
2016-11-29 13:02 ` [PATCH v2 9/9] imsm: 4kn support for bad block log Tomasz Majchrzak
2016-12-02 16:04 ` [PATCH v2 0/9] Bad block support for IMSM metadata Jes Sorensen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1480434011-4866-1-git-send-email-tomasz.majchrzak@intel.com \
--to=tomasz.majchrzak@intel.com \
--cc=Jes.Sorensen@redhat.com \
--cc=linux-raid@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).