* [PATCH 0/4] IMSM: Add support for 4Kn sector size drives
@ 2016-11-10 14:28 Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 1/4] Add function for getting member drive sector size Pawel Baldysiak
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Pawel Baldysiak @ 2016-11-10 14:28 UTC (permalink / raw)
To: jes.sorensen; +Cc: linux-raid, Pawel Baldysiak
This patch set adds support for IMSM with 4Kn sector size drives
First patch adds the generic function for receiving sector size,
rest are IMSM specific.
Internal calculation are still based on 512-bytes sector,
variables are converted during read/write from/to member drive.
Mixing of devices with different sector size is not allowed.
Pawel Baldysiak (4):
Add function for getting member drive sector size
IMSM: Read and store device sector size
IMSM: Add support for 4Kn sector size drives
IMSM: 4Kn drives support - adapt general migration record
mdadm.h | 1 +
super-intel.c | 315 +++++++++++++++++++++++++++++++++++++++++++++-------------
super1.c | 3 +-
util.c | 16 +++
4 files changed, 265 insertions(+), 70 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] Add function for getting member drive sector size
2016-11-10 14:28 [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
@ 2016-11-10 14:28 ` Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 2/4] IMSM: Read and store device " Pawel Baldysiak
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pawel Baldysiak @ 2016-11-10 14:28 UTC (permalink / raw)
To: jes.sorensen; +Cc: linux-raid, Pawel Baldysiak
This patch introduces the function for getting sector size of
given device (fd).
Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com>
---
mdadm.h | 1 +
super1.c | 3 +--
util.c | 16 ++++++++++++++++
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index 0516c82..1aeb232 100755
--- a/mdadm.h
+++ b/mdadm.h
@@ -1112,6 +1112,7 @@ static inline struct supertype *guess_super(int fd) {
}
extern struct supertype *dup_super(struct supertype *st);
extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
+extern int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep);
extern int must_be_container(int fd);
extern int dev_size_from_id(dev_t id, unsigned long long *size);
void wait_for(char *dev, int fd);
diff --git a/super1.c b/super1.c
index 4fef378..8f800b5 100644
--- a/super1.c
+++ b/super1.c
@@ -212,8 +212,7 @@ struct align_fd {
static void init_afd(struct align_fd *afd, int fd)
{
afd->fd = fd;
-
- if (ioctl(afd->fd, BLKSSZGET, &afd->blk_sz) != 0)
+ if (!get_dev_sector_size(afd->fd, NULL, (unsigned int *)&afd->blk_sz))
afd->blk_sz = 512;
}
diff --git a/util.c b/util.c
index 9e4718f..092854a 100644
--- a/util.c
+++ b/util.c
@@ -1333,6 +1333,22 @@ int get_dev_size(int fd, char *dname, unsigned long long *sizep)
return 1;
}
+/* Return sector size of device in bytes */
+int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep)
+{
+ unsigned int sectsize;
+
+ if (ioctl(fd, BLKSSZGET, §size) != 0) {
+ if (dname)
+ pr_err("Cannot get sector size of %s: %s\b",
+ dname, strerror(errno));
+ return 0;
+ }
+
+ *sectsizep = sectsize;
+ return 1;
+}
+
/* Return true if this can only be a container, not a member device.
* i.e. is and md device and size is zero
*/
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/4] IMSM: Read and store device sector size
2016-11-10 14:28 [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 1/4] Add function for getting member drive sector size Pawel Baldysiak
@ 2016-11-10 14:28 ` Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 3/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pawel Baldysiak @ 2016-11-10 14:28 UTC (permalink / raw)
To: jes.sorensen; +Cc: linux-raid, Pawel Baldysiak
This patch adds retriving device sector size at startup
and set it in intel_super, so it can be used in other places.
Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com>
---
super-intel.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/super-intel.c b/super-intel.c
index 21e8532..8a2d993 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -366,6 +366,7 @@ struct intel_super {
unsigned long long create_offset; /* common start for 'current_vol' */
__u32 random; /* random data for seeding new family numbers */
struct intel_dev *devlist;
+ unsigned int sector_size; /* sector size of used member drives */
struct dl {
struct dl *next;
int index;
@@ -4491,6 +4492,7 @@ static int get_super_block(struct intel_super **super_list, char *devnm, char *d
goto error;
}
+ get_dev_sector_size(dfd, NULL, &s->sector_size);
find_intel_hba_capability(dfd, s, devname);
err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
@@ -4570,6 +4572,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
free_super_imsm(st);
super = alloc_super();
+ get_dev_sector_size(fd, NULL, &super->sector_size);
/* 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.
@@ -5102,6 +5105,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
struct intel_super *super = st->sb;
struct dl *dd;
unsigned long long size;
+ unsigned int member_sector_size;
__u32 id;
int rv;
struct stat stb;
@@ -5182,6 +5186,19 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
}
get_dev_size(fd, NULL, &size);
+ get_dev_sector_size(fd, NULL, &member_sector_size);
+
+ if (super->sector_size == 0) {
+ /* this a first device, so sector_size is not set yet */
+ super->sector_size = member_sector_size;
+ } else if (member_sector_size != super->sector_size) {
+ pr_err("Mixing between different sector size is forbidden, aborting...");
+ if (dd->devname)
+ free(dd->devname);
+ free(dd);
+ return 1;
+ }
+
/* clear migr_rec when adding disk to container */
memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
if (lseek64(fd, size - MIGR_REC_POSITION, SEEK_SET) >= 0) {
@@ -5529,6 +5546,12 @@ 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 (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
+ close(fd);
+ free_imsm(super);
+ return 0;
+ }
+
rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL);
if (rv != 0) {
#if DEBUG
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/4] IMSM: Add support for 4Kn sector size drives
2016-11-10 14:28 [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 1/4] Add function for getting member drive sector size Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 2/4] IMSM: Read and store device " Pawel Baldysiak
@ 2016-11-10 14:28 ` Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 4/4] IMSM: 4Kn drives support - adapt general migration record Pawel Baldysiak
2016-11-16 15:14 ` [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Jes Sorensen
4 siblings, 0 replies; 6+ messages in thread
From: Pawel Baldysiak @ 2016-11-10 14:28 UTC (permalink / raw)
To: jes.sorensen; +Cc: linux-raid, Pawel Baldysiak, Tomasz Majchrzak
This patch adds support for drives with 4Kn sector size
for IMSM metadata. Mixing member drives with 4Kn and 512
is not allowed. Some offsets were aligned with sector size.
Internal metadata representation and all calculations
are still based on 512-byte sector sizes. This
implementation converts only sector based values
when reading/writing to drive, because they needs to be
stored in metadata according to accual member drive sector size.
Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com>
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
---
super-intel.c | 199 +++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 154 insertions(+), 45 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 8a2d993..fa3e96d 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -318,14 +318,15 @@ static void set_migr_type(struct imsm_dev *dev, __u8 migr_type)
}
}
-static unsigned int sector_count(__u32 bytes)
+static unsigned int sector_count(__u32 bytes, unsigned int sector_size)
{
- return ROUND_UP(bytes, 512) / 512;
+ return ROUND_UP(bytes, sector_size) / sector_size;
}
-static unsigned int mpb_sectors(struct imsm_super *mpb)
+static unsigned int mpb_sectors(struct imsm_super *mpb,
+ unsigned int sector_size)
{
- return sector_count(__le32_to_cpu(mpb->mpb_size));
+ return sector_count(__le32_to_cpu(mpb->mpb_size), sector_size);
}
struct intel_dev {
@@ -915,12 +916,12 @@ static unsigned long long num_data_stripes(struct imsm_map *map)
return 0;
return join_u32(map->num_data_stripes_lo, map->num_data_stripes_hi);
}
+#endif
static void set_total_blocks(struct imsm_disk *disk, unsigned long long n)
{
split_ull(n, &disk->total_blocks_lo, &disk->total_blocks_hi);
}
-#endif
static void set_pba_of_lba0(struct imsm_map *map, unsigned long long n)
{
@@ -1122,6 +1123,8 @@ static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
static int is_gen_migration(struct imsm_dev *dev);
+#define IMSM_4K_DIV 8
+
#ifndef MDASSEMBLE
static __u64 blocks_per_migr_unit(struct intel_super *super,
struct imsm_dev *dev);
@@ -1253,6 +1256,48 @@ static void print_imsm_disk(struct imsm_disk *disk, int index, __u32 reserved)
human_size(sz * 512));
}
+void convert_to_4k_imsm_disk(struct imsm_disk *disk)
+{
+ set_total_blocks(disk, (total_blocks(disk)/IMSM_4K_DIV));
+}
+
+void convert_to_4k(struct intel_super *super)
+{
+ struct imsm_super *mpb = super->anchor;
+ struct imsm_disk *disk;
+ int i;
+
+ for (i = 0; i < mpb->num_disks ; i++) {
+ disk = __get_imsm_disk(mpb, i);
+ /* disk */
+ convert_to_4k_imsm_disk(disk);
+ }
+ for (i = 0; i < mpb->num_raid_devs; i++) {
+ struct imsm_dev *dev = __get_imsm_dev(mpb, i);
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
+ /* dev */
+ split_ull((join_u32(dev->size_low, dev->size_high)/IMSM_4K_DIV),
+ &dev->size_low, &dev->size_high);
+ dev->vol.curr_migr_unit /= IMSM_4K_DIV;
+
+ /* map0 */
+ set_blocks_per_member(map, blocks_per_member(map)/IMSM_4K_DIV);
+ map->blocks_per_strip /= IMSM_4K_DIV;
+ set_pba_of_lba0(map, pba_of_lba0(map)/IMSM_4K_DIV);
+
+ if (dev->vol.migr_state) {
+ /* map1 */
+ map = get_imsm_map(dev, MAP_1);
+ set_blocks_per_member(map,
+ blocks_per_member(map)/IMSM_4K_DIV);
+ map->blocks_per_strip /= IMSM_4K_DIV;
+ set_pba_of_lba0(map, pba_of_lba0(map)/IMSM_4K_DIV);
+ }
+ }
+
+ mpb->check_sum = __gen_imsm_checksum(mpb);
+}
+
void examine_migr_rec_imsm(struct intel_super *super)
{
struct migr_record *migr_rec = super->migr_rec;
@@ -1310,6 +1355,45 @@ void examine_migr_rec_imsm(struct intel_super *super)
}
}
#endif /* MDASSEMBLE */
+
+void convert_from_4k(struct intel_super *super)
+{
+ struct imsm_super *mpb = super->anchor;
+ struct imsm_disk *disk;
+ int i;
+
+ for (i = 0; i < mpb->num_disks ; i++) {
+ disk = __get_imsm_disk(mpb, i);
+ /* disk */
+ set_total_blocks(disk, (total_blocks(disk)*IMSM_4K_DIV));
+ }
+
+ for (i = 0; i < mpb->num_raid_devs; i++) {
+ struct imsm_dev *dev = __get_imsm_dev(mpb, i);
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
+ /* dev */
+ split_ull((join_u32(dev->size_low, dev->size_high)*IMSM_4K_DIV),
+ &dev->size_low, &dev->size_high);
+ dev->vol.curr_migr_unit *= IMSM_4K_DIV;
+
+ /* map0 */
+ set_blocks_per_member(map, blocks_per_member(map)*IMSM_4K_DIV);
+ map->blocks_per_strip *= IMSM_4K_DIV;
+ set_pba_of_lba0(map, pba_of_lba0(map)*IMSM_4K_DIV);
+
+ if (dev->vol.migr_state) {
+ /* map1 */
+ map = get_imsm_map(dev, MAP_1);
+ set_blocks_per_member(map,
+ blocks_per_member(map)*IMSM_4K_DIV);
+ map->blocks_per_strip *= IMSM_4K_DIV;
+ set_pba_of_lba0(map, pba_of_lba0(map)*IMSM_4K_DIV);
+ }
+ }
+
+ mpb->check_sum = __gen_imsm_checksum(mpb);
+}
+
/*******************************************************************************
* function: imsm_check_attributes
* Description: Function checks if features represented by attributes flags
@@ -1430,7 +1514,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
sum = __le32_to_cpu(mpb->check_sum);
printf(" Checksum : %08x %s\n", sum,
__gen_imsm_checksum(mpb) == sum ? "correct" : "incorrect");
- printf(" MPB Sectors : %d\n", mpb_sectors(mpb));
+ printf(" MPB Sectors : %d\n", mpb_sectors(mpb, super->sector_size));
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);
@@ -1527,7 +1611,7 @@ static void export_examine_super_imsm(struct supertype *st)
static int copy_metadata_imsm(struct supertype *st, int from, int to)
{
- /* The second last 512byte sector of the device contains
+ /* The second last sector of the device contains
* the "struct imsm_super" metadata.
* This contains mpb_size which is the size in bytes of the
* extended metadata. This is located immediately before
@@ -1540,7 +1624,9 @@ static int copy_metadata_imsm(struct supertype *st, int from, int to)
unsigned long long dsize, offset;
int sectors;
struct imsm_super *sb;
- int written = 0;
+ struct intel_super *super = st->sb;
+ unsigned int sector_size = super->sector_size;
+ unsigned int written = 0;
if (posix_memalign(&buf, 4096, 4096) != 0)
return 1;
@@ -1548,21 +1634,21 @@ static int copy_metadata_imsm(struct supertype *st, int from, int to)
if (!get_dev_size(from, NULL, &dsize))
goto err;
- if (lseek64(from, dsize-1024, 0) < 0)
+ if (lseek64(from, dsize-(2*sector_size), 0) < 0)
goto err;
- if (read(from, buf, 512) != 512)
+ if (read(from, buf, sector_size) != sector_size)
goto err;
sb = buf;
if (strncmp((char*)sb->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0)
goto err;
- sectors = mpb_sectors(sb) + 2;
- offset = dsize - sectors * 512;
+ sectors = mpb_sectors(sb, sector_size) + 2;
+ offset = dsize - sectors * sector_size;
if (lseek64(from, offset, 0) < 0 ||
lseek64(to, offset, 0) < 0)
goto err;
- while (written < sectors * 512) {
- int n = sectors*512 - written;
+ while (written < sectors * sector_size) {
+ int n = sectors*sector_size - written;
if (n > 4096)
n = 4096;
if (read(from, buf, n) != n)
@@ -2678,13 +2764,14 @@ int imsm_reshape_blocks_arrays_changes(struct intel_super *super)
}
static unsigned long long imsm_component_size_aligment_check(int level,
int chunk_size,
+ unsigned int sector_size,
unsigned long long component_size)
{
unsigned int component_size_alligment;
/* check component size aligment
*/
- component_size_alligment = component_size % (chunk_size/512);
+ component_size_alligment = component_size % (chunk_size/sector_size);
dprintf("(Level: %i, chunk_size = %i, component_size = %llu), component_size_alligment = %u\n",
level, chunk_size, component_size,
@@ -2795,6 +2882,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
info->component_size = imsm_component_size_aligment_check(
info->array.level,
info->array.chunk_size,
+ super->sector_size,
info->component_size);
memset(info->uuid, 0, sizeof(info->uuid));
@@ -3615,8 +3703,9 @@ static int parse_raid_devices(struct intel_super *super)
if (__le32_to_cpu(mpb->mpb_size) + space_needed > super->len) {
void *buf;
- len = ROUND_UP(__le32_to_cpu(mpb->mpb_size) + space_needed, 512);
- if (posix_memalign(&buf, 512, len) != 0)
+ len = ROUND_UP(__le32_to_cpu(mpb->mpb_size) + space_needed,
+ super->sector_size);
+ if (posix_memalign(&buf, 4096, len) != 0)
return 1;
memcpy(buf, super->buf, super->len);
@@ -3689,31 +3778,32 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
{
unsigned long long dsize;
unsigned long long sectors;
+ unsigned int sector_size = super->sector_size;
struct stat;
struct imsm_super *anchor;
__u32 check_sum;
get_dev_size(fd, NULL, &dsize);
- if (dsize < 1024) {
+ if (dsize < 2*sector_size) {
if (devname)
pr_err("%s: device to small for imsm\n",
devname);
return 1;
}
- if (lseek64(fd, dsize - (512 * 2), SEEK_SET) < 0) {
+ if (lseek64(fd, dsize - (sector_size * 2), SEEK_SET) < 0) {
if (devname)
pr_err("Cannot seek to anchor block on %s: %s\n",
devname, strerror(errno));
return 1;
}
- if (posix_memalign((void**)&anchor, 512, 512) != 0) {
+ if (posix_memalign((void **)&anchor, sector_size, sector_size) != 0) {
if (devname)
pr_err("Failed to allocate imsm anchor buffer on %s\n", devname);
return 1;
}
- if (read(fd, anchor, 512) != 512) {
+ if (read(fd, anchor, sector_size) != sector_size) {
if (devname)
pr_err("Cannot read anchor block on %s: %s\n",
devname, strerror(errno));
@@ -3733,17 +3823,17 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
/* capability and hba must be updated with new super allocation */
find_intel_hba_capability(fd, super, devname);
- super->len = ROUND_UP(anchor->mpb_size, 512);
- if (posix_memalign(&super->buf, 512, super->len) != 0) {
+ super->len = ROUND_UP(anchor->mpb_size, sector_size);
+ if (posix_memalign(&super->buf, 4096, super->len) != 0) {
if (devname)
pr_err("unable to allocate %zu byte mpb buffer\n",
super->len);
free(anchor);
return 2;
}
- memcpy(super->buf, anchor, 512);
+ memcpy(super->buf, anchor, sector_size);
- sectors = mpb_sectors(anchor) - 1;
+ sectors = mpb_sectors(anchor, sector_size) - 1;
free(anchor);
if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
@@ -3768,14 +3858,15 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
}
/* read the extended mpb */
- if (lseek64(fd, dsize - (512 * (2 + sectors)), SEEK_SET) < 0) {
+ if (lseek64(fd, dsize - (sector_size * (2 + sectors)), SEEK_SET) < 0) {
if (devname)
pr_err("Cannot seek to extended mpb on %s: %s\n",
devname, strerror(errno));
return 1;
}
- if ((unsigned)read(fd, super->buf + 512, super->len - 512) != super->len - 512) {
+ if ((unsigned int)read(fd, super->buf + sector_size,
+ super->len - sector_size) != super->len - sector_size) {
if (devname)
pr_err("Cannot read extended mpb on %s: %s\n",
devname, strerror(errno));
@@ -3836,6 +3927,8 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd
err = load_imsm_mpb(fd, super, devname);
if (err)
return err;
+ if (super->sector_size == 4096)
+ convert_from_4k(super);
err = load_imsm_disk(fd, super, devname, keep_fd);
if (err)
return err;
@@ -4733,6 +4826,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
* so st->sb is already set.
*/
struct intel_super *super = st->sb;
+ unsigned int sector_size = super->sector_size;
struct imsm_super *mpb = super->anchor;
struct intel_dev *dv;
struct imsm_dev *dev;
@@ -4754,9 +4848,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
size_new = disks_to_mpb_size(info->nr_disks);
if (size_new > size_old) {
void *mpb_new;
- size_t size_round = ROUND_UP(size_new, 512);
+ size_t size_round = ROUND_UP(size_new, sector_size);
- if (posix_memalign(&mpb_new, 512, size_round) != 0) {
+ if (posix_memalign(&mpb_new, sector_size, size_round) != 0) {
pr_err("could not allocate new mpb\n");
return 0;
}
@@ -4911,10 +5005,10 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
if (info)
mpb_size = disks_to_mpb_size(info->nr_disks);
else
- mpb_size = 512;
+ mpb_size = 4096;
super = alloc_super();
- if (super && posix_memalign(&super->buf, 512, mpb_size) != 0) {
+ if (super && posix_memalign(&super->buf, 4096, mpb_size) != 0) {
free(super);
super = NULL;
}
@@ -5261,9 +5355,9 @@ static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk)
static int store_imsm_mpb(int fd, struct imsm_super *mpb);
static union {
- char buf[512];
+ char buf[4096];
struct imsm_super anchor;
-} spare_record __attribute__ ((aligned(512)));
+} spare_record __attribute__ ((aligned(4096)));
/* spare records have their own family number and do not have any defined raid
* devices
@@ -5294,6 +5388,9 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
spare->attributes |= MPB_ATTRIB_2TB_DISK;
+ if (super->sector_size == 4096)
+ convert_to_4k_imsm_disk(&spare->disk[0]);
+
sum = __gen_imsm_checksum(spare);
spare->family_num = __cpu_to_le32(sum);
spare->orig_family_num = 0;
@@ -5317,6 +5414,7 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
static int write_super_imsm(struct supertype *st, int doclose)
{
struct intel_super *super = st->sb;
+ unsigned int sector_size = super->sector_size;
struct imsm_super *mpb = super->anchor;
struct dl *d;
__u32 generation;
@@ -5377,6 +5475,9 @@ static int write_super_imsm(struct supertype *st, int doclose)
if (clear_migration_record)
memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
+ if (sector_size == 4096)
+ convert_to_4k(super);
+
/* write the mpb for disks that compose raid devices */
for (d = super->disks; d ; d = d->next) {
if (d->index < 0 || is_failed(&d->disk))
@@ -5500,6 +5601,8 @@ static int store_super_imsm(struct supertype *st, int fd)
return 1;
#ifndef MDASSEMBLE
+ if (super->sector_size == 4096)
+ convert_to_4k(super);
return store_imsm_mpb(fd, mpb);
#else
return 1;
@@ -7574,27 +7677,30 @@ static int store_imsm_mpb(int fd, struct imsm_super *mpb)
__u32 mpb_size = __le32_to_cpu(mpb->mpb_size);
unsigned long long dsize;
unsigned long long sectors;
+ unsigned int sector_size;
+ get_dev_sector_size(fd, NULL, §or_size);
get_dev_size(fd, NULL, &dsize);
- if (mpb_size > 512) {
+ if (mpb_size > sector_size) {
/* -1 to account for anchor */
- sectors = mpb_sectors(mpb) - 1;
+ sectors = mpb_sectors(mpb, sector_size) - 1;
/* write the extended mpb to the sectors preceeding the anchor */
- if (lseek64(fd, dsize - (512 * (2 + sectors)), SEEK_SET) < 0)
+ if (lseek64(fd, dsize - (sector_size * (2 + sectors)),
+ SEEK_SET) < 0)
return 1;
- if ((unsigned long long)write(fd, buf + 512, 512 * sectors)
- != 512 * sectors)
+ if ((unsigned long long)write(fd, buf + sector_size,
+ sector_size * sectors) != sector_size * sectors)
return 1;
}
/* first block is stored on second to last sector of the disk */
- if (lseek64(fd, dsize - (512 * 2), SEEK_SET) < 0)
+ if (lseek64(fd, dsize - (sector_size * 2), SEEK_SET) < 0)
return 1;
- if (write(fd, buf, 512) != 512)
+ if (write(fd, buf, sector_size) != sector_size)
return 1;
return 0;
@@ -8830,6 +8936,7 @@ static int imsm_prepare_update(struct supertype *st,
*/
enum imsm_update_type type;
struct intel_super *super = st->sb;
+ unsigned int sector_size = super->sector_size;
struct imsm_super *mpb = super->anchor;
size_t buf_len;
size_t len = 0;
@@ -9066,12 +9173,13 @@ static int imsm_prepare_update(struct supertype *st,
* if this allocation fails process_update will notice that
* ->next_len is set and ->next_buf is NULL
*/
- buf_len = ROUND_UP(__le32_to_cpu(mpb->mpb_size) + len, 512);
+ buf_len = ROUND_UP(__le32_to_cpu(mpb->mpb_size) + len,
+ sector_size);
if (super->next_buf)
free(super->next_buf);
super->next_len = buf_len;
- if (posix_memalign(&super->next_buf, 512, buf_len) == 0)
+ if (posix_memalign(&super->next_buf, sector_size, buf_len) == 0)
memset(super->next_buf, 0, buf_len);
else
super->next_buf = NULL;
@@ -9566,6 +9674,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
int new_disks, i, err;
char *buf = NULL;
int retval = 1;
+ unsigned int sector_size = super->sector_size;
unsigned long curr_migr_unit = __le32_to_cpu(migr_rec->curr_migr_unit);
unsigned long num_migr_units = __le32_to_cpu(migr_rec->num_migr_units);
char buffer[20];
@@ -9602,7 +9711,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
pba_of_lba0(map_dest)) * 512;
unit_len = __le32_to_cpu(migr_rec->dest_depth_per_unit) * 512;
- if (posix_memalign((void **)&buf, 512, unit_len) != 0)
+ if (posix_memalign((void **)&buf, sector_size, unit_len) != 0)
goto abort;
targets = xcalloc(new_disks, sizeof(int));
@@ -10148,7 +10257,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
*/
geo->size = imsm_component_size_aligment_check(
get_imsm_raid_level(dev->vol.map),
- chunk * 1024,
+ chunk * 1024, super->sector_size,
geo->size * 2);
if (geo->size == 0) {
pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is 0).\n",
@@ -10182,7 +10291,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
*/
max_size = imsm_component_size_aligment_check(
get_imsm_raid_level(dev->vol.map),
- chunk * 1024,
+ chunk * 1024, super->sector_size,
max_size);
}
if (geo->size == MAX_SIZE) {
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4] IMSM: 4Kn drives support - adapt general migration record
2016-11-10 14:28 [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
` (2 preceding siblings ...)
2016-11-10 14:28 ` [PATCH 3/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
@ 2016-11-10 14:28 ` Pawel Baldysiak
2016-11-16 15:14 ` [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Jes Sorensen
4 siblings, 0 replies; 6+ messages in thread
From: Pawel Baldysiak @ 2016-11-10 14:28 UTC (permalink / raw)
To: jes.sorensen; +Cc: linux-raid, Pawel Baldysiak, Tomasz Majchrzak
Convert general migration record for 4Kn drives prior to write and post
read. Calculate record location based on sector size, don't just assume
it's 512. Assure buffer address is aligned to 4096 so write operation
avoids caching.
Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com>
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
---
super-intel.c | 93 ++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 70 insertions(+), 23 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index fa3e96d..81bec16 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -243,9 +243,9 @@ static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed"
#define GEN_MIGR_AREA_SIZE 2048 /* General Migration Copy Area size in blocks */
-#define MIGR_REC_BUF_SIZE 512 /* size of migr_record i/o buffer */
-#define MIGR_REC_POSITION 512 /* migr_record position offset on disk,
- * MIGR_REC_BUF_SIZE <= MIGR_REC_POSITION
+#define MIGR_REC_BUF_SECTORS 1 /* size of migr_record i/o buffer in sectors */
+#define MIGR_REC_SECTOR_POSITION 1 /* migr_record position offset on disk,
+ * MIGR_REC_BUF_SECTORS <= MIGR_REC_SECTOR_POS
*/
#define UNIT_SRC_NORMAL 0 /* Source data for curr_migr_unit must
@@ -1256,6 +1256,19 @@ static void print_imsm_disk(struct imsm_disk *disk, int index, __u32 reserved)
human_size(sz * 512));
}
+void convert_to_4k_imsm_migr_rec(struct intel_super *super)
+{
+ struct migr_record *migr_rec = super->migr_rec;
+
+ migr_rec->blocks_per_unit /= IMSM_4K_DIV;
+ migr_rec->ckpt_area_pba /= IMSM_4K_DIV;
+ migr_rec->dest_1st_member_lba /= IMSM_4K_DIV;
+ migr_rec->dest_depth_per_unit /= IMSM_4K_DIV;
+ split_ull((join_u32(migr_rec->post_migr_vol_cap,
+ migr_rec->post_migr_vol_cap_hi) / IMSM_4K_DIV),
+ &migr_rec->post_migr_vol_cap, &migr_rec->post_migr_vol_cap_hi);
+}
+
void convert_to_4k_imsm_disk(struct imsm_disk *disk)
{
set_total_blocks(disk, (total_blocks(disk)/IMSM_4K_DIV));
@@ -1356,6 +1369,20 @@ void examine_migr_rec_imsm(struct intel_super *super)
}
#endif /* MDASSEMBLE */
+void convert_from_4k_imsm_migr_rec(struct intel_super *super)
+{
+ struct migr_record *migr_rec = super->migr_rec;
+
+ migr_rec->blocks_per_unit *= IMSM_4K_DIV;
+ migr_rec->ckpt_area_pba *= IMSM_4K_DIV;
+ migr_rec->dest_1st_member_lba *= IMSM_4K_DIV;
+ migr_rec->dest_depth_per_unit *= IMSM_4K_DIV;
+ split_ull((join_u32(migr_rec->post_migr_vol_cap,
+ migr_rec->post_migr_vol_cap_hi) * IMSM_4K_DIV),
+ &migr_rec->post_migr_vol_cap,
+ &migr_rec->post_migr_vol_cap_hi);
+}
+
void convert_from_4k(struct intel_super *super)
{
struct imsm_super *mpb = super->anchor;
@@ -2498,21 +2525,26 @@ static int imsm_level_to_layout(int level)
static int read_imsm_migr_rec(int fd, struct intel_super *super)
{
int ret_val = -1;
+ unsigned int sector_size = super->sector_size;
unsigned long long dsize;
get_dev_size(fd, NULL, &dsize);
- if (lseek64(fd, dsize - MIGR_REC_POSITION, SEEK_SET) < 0) {
+ if (lseek64(fd, dsize - (sector_size*MIGR_REC_SECTOR_POSITION),
+ SEEK_SET) < 0) {
pr_err("Cannot seek to anchor block: %s\n",
strerror(errno));
goto out;
}
- if (read(fd, super->migr_rec_buf, MIGR_REC_BUF_SIZE) !=
- MIGR_REC_BUF_SIZE) {
+ if (read(fd, super->migr_rec_buf,
+ MIGR_REC_BUF_SECTORS*sector_size) !=
+ MIGR_REC_BUF_SECTORS*sector_size) {
pr_err("Cannot read migr record block: %s\n",
strerror(errno));
goto out;
}
ret_val = 0;
+ if (sector_size == 4096)
+ convert_from_4k_imsm_migr_rec(super);
out:
return ret_val;
@@ -2658,6 +2690,7 @@ static void imsm_update_metadata_locally(struct supertype *st,
static int write_imsm_migr_rec(struct supertype *st)
{
struct intel_super *super = st->sb;
+ unsigned int sector_size = super->sector_size;
unsigned long long dsize;
char nm[30];
int fd = -1;
@@ -2679,6 +2712,8 @@ static int write_imsm_migr_rec(struct supertype *st)
map = get_imsm_map(dev, MAP_0);
+ if (sector_size == 4096)
+ convert_to_4k_imsm_migr_rec(super);
for (sd = super->disks ; sd ; sd = sd->next) {
int slot = -1;
@@ -2696,13 +2731,15 @@ static int write_imsm_migr_rec(struct supertype *st)
if (fd < 0)
continue;
get_dev_size(fd, NULL, &dsize);
- if (lseek64(fd, dsize - MIGR_REC_POSITION, SEEK_SET) < 0) {
+ if (lseek64(fd, dsize - (MIGR_REC_SECTOR_POSITION*sector_size),
+ SEEK_SET) < 0) {
pr_err("Cannot seek to anchor block: %s\n",
strerror(errno));
goto out;
}
- if (write(fd, super->migr_rec_buf, MIGR_REC_BUF_SIZE) !=
- MIGR_REC_BUF_SIZE) {
+ if (write(fd, super->migr_rec_buf,
+ MIGR_REC_BUF_SECTORS*sector_size) !=
+ MIGR_REC_BUF_SECTORS*sector_size) {
pr_err("Cannot write migr record block: %s\n",
strerror(errno));
goto out;
@@ -2710,9 +2747,10 @@ static int write_imsm_migr_rec(struct supertype *st)
close(fd);
fd = -1;
}
+ if (sector_size == 4096)
+ convert_from_4k_imsm_migr_rec(super);
/* update checkpoint information in metadata */
len = imsm_create_metadata_checkpoint_update(super, &u);
-
if (len <= 0) {
dprintf("imsm: Cannot prepare update\n");
goto out;
@@ -3836,7 +3874,8 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
sectors = mpb_sectors(anchor, sector_size) - 1;
free(anchor);
- if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
+ if (posix_memalign(&super->migr_rec_buf, sector_size,
+ MIGR_REC_BUF_SECTORS*sector_size) != 0) {
pr_err("could not allocate migr_rec buffer\n");
free(super->buf);
return 2;
@@ -4854,8 +4893,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
pr_err("could not allocate new mpb\n");
return 0;
}
- if (posix_memalign(&super->migr_rec_buf, 512,
- MIGR_REC_BUF_SIZE) != 0) {
+ if (posix_memalign(&super->migr_rec_buf, sector_size,
+ MIGR_REC_BUF_SECTORS*sector_size) != 0) {
pr_err("could not allocate migr_rec buffer\n");
free(super->buf);
free(super);
@@ -5016,7 +5055,8 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
pr_err("could not allocate superblock\n");
return 0;
}
- if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
+ if (posix_memalign(&super->migr_rec_buf, 4096,
+ MIGR_REC_BUF_SECTORS*4096) != 0) {
pr_err("could not allocate migr_rec buffer\n");
free(super->buf);
free(super);
@@ -5294,10 +5334,12 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
}
/* clear migr_rec when adding disk to container */
- memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
- if (lseek64(fd, size - MIGR_REC_POSITION, SEEK_SET) >= 0) {
+ memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*super->sector_size);
+ if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*super->sector_size,
+ SEEK_SET) >= 0) {
if (write(fd, super->migr_rec_buf,
- MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE)
+ MIGR_REC_BUF_SECTORS*super->sector_size) !=
+ MIGR_REC_BUF_SECTORS*super->sector_size)
perror("Write migr_rec failed");
}
@@ -5473,7 +5515,8 @@ static int write_super_imsm(struct supertype *st, int doclose)
super->clean_migration_record_by_mdmon = 0;
}
if (clear_migration_record)
- memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
+ memset(super->migr_rec_buf, 0,
+ MIGR_REC_BUF_SECTORS*sector_size);
if (sector_size == 4096)
convert_to_4k(super);
@@ -5487,9 +5530,11 @@ static int write_super_imsm(struct supertype *st, int doclose)
unsigned long long dsize;
get_dev_size(d->fd, NULL, &dsize);
- if (lseek64(d->fd, dsize - 512, SEEK_SET) >= 0) {
+ if (lseek64(d->fd, dsize - sector_size,
+ SEEK_SET) >= 0) {
if (write(d->fd, super->migr_rec_buf,
- MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE)
+ MIGR_REC_BUF_SECTORS*sector_size) !=
+ MIGR_REC_BUF_SECTORS*sector_size)
perror("Write migr_rec failed");
}
}
@@ -10713,6 +10758,7 @@ static int imsm_manage_reshape(
int ret_val = 0;
struct intel_super *super = st->sb;
struct intel_dev *dv;
+ unsigned int sector_size = super->sector_size;
struct imsm_dev *dev = NULL;
struct imsm_map *map_src;
int migr_vol_qan = 0;
@@ -10907,17 +10953,18 @@ static int imsm_manage_reshape(
/* clear migr_rec on disks after successful migration */
struct dl *d;
- memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
+ memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*sector_size);
for (d = super->disks; d; d = d->next) {
if (d->index < 0 || is_failed(&d->disk))
continue;
unsigned long long dsize;
get_dev_size(d->fd, NULL, &dsize);
- if (lseek64(d->fd, dsize - MIGR_REC_POSITION,
+ if (lseek64(d->fd, dsize - MIGR_REC_SECTOR_POSITION*sector_size,
SEEK_SET) >= 0) {
if (write(d->fd, super->migr_rec_buf,
- MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE)
+ MIGR_REC_BUF_SECTORS*sector_size) !=
+ MIGR_REC_BUF_SECTORS*sector_size)
perror("Write migr_rec failed");
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/4] IMSM: Add support for 4Kn sector size drives
2016-11-10 14:28 [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
` (3 preceding siblings ...)
2016-11-10 14:28 ` [PATCH 4/4] IMSM: 4Kn drives support - adapt general migration record Pawel Baldysiak
@ 2016-11-16 15:14 ` Jes Sorensen
4 siblings, 0 replies; 6+ messages in thread
From: Jes Sorensen @ 2016-11-16 15:14 UTC (permalink / raw)
To: Pawel Baldysiak; +Cc: linux-raid
Pawel Baldysiak <pawel.baldysiak@intel.com> writes:
> This patch set adds support for IMSM with 4Kn sector size drives
> First patch adds the generic function for receiving sector size,
> rest are IMSM specific.
> Internal calculation are still based on 512-bytes sector,
> variables are converted during read/write from/to member drive.
> Mixing of devices with different sector size is not allowed.
>
> Pawel Baldysiak (4):
> Add function for getting member drive sector size
> IMSM: Read and store device sector size
> IMSM: Add support for 4Kn sector size drives
> IMSM: 4Kn drives support - adapt general migration record
>
> mdadm.h | 1 +
> super-intel.c | 315 +++++++++++++++++++++++++++++++++++++++++++++-------------
> super1.c | 3 +-
> util.c | 16 +++
> 4 files changed, 265 insertions(+), 70 deletions(-)
Hi Pawel,
This set mostly looks good - a couple of comments:
+int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep)
This introduces a *dname but nowhere in your code is it actually used. I
am not necessarily against this, and it looks like we do it in some
places, but not others. However do you anticipate using it in future
changes you have lined up?
I noticed you changed hard coded 512 byte limits to hard coded 4096
when rounding up sizes for posix_memalign() etc. Wouldn't it be cleaner
to introduce a MAX_SECTOR_SIZE or similar?
Cheers,
Jes
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-11-16 15:14 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-10 14:28 [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 1/4] Add function for getting member drive sector size Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 2/4] IMSM: Read and store device " Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 3/4] IMSM: Add support for 4Kn sector size drives Pawel Baldysiak
2016-11-10 14:28 ` [PATCH 4/4] IMSM: 4Kn drives support - adapt general migration record Pawel Baldysiak
2016-11-16 15:14 ` [PATCH 0/4] IMSM: Add support for 4Kn sector size drives Jes Sorensen
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).