summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-07-12 20:28:33 +1000
committerNeil Brown <neilb@suse.de>2008-07-12 20:28:33 +1000
commit6416d5275d65be25a6cd63583bb2b92e6fba95a5 (patch)
tree23757b31666774c05c405dfd720dc92b3bb03b90
parent908ef18519f7d5780ebf00b19b913f8282eb4175 (diff)
downloadmdadm-6416d5275d65be25a6cd63583bb2b92e6fba95a5.tar.gz
mdadm-6416d5275d65be25a6cd63583bb2b92e6fba95a5.tar.xz
mdadm-6416d5275d65be25a6cd63583bb2b92e6fba95a5.zip
Use O_DIRECT for all IO to devices.
Using buffered IO risks non-atomic updates to parts of the device that we don't actually want to write to. This isn't in general safe. So switch to O_DIRECT for all that IO and make sure we have properly aligned buffers.
-rw-r--r--Grow.c2
-rw-r--r--Kill.c2
-rw-r--r--Manage.c4
-rw-r--r--bitmap.c6
-rw-r--r--mdadm.h5
-rw-r--r--super-ddf.c106
-rw-r--r--super-intel.c37
-rw-r--r--super0.c33
-rw-r--r--super1.c43
-rw-r--r--util.c4
10 files changed, 136 insertions, 106 deletions
diff --git a/Grow.c b/Grow.c
index b24e958..fc007d6 100644
--- a/Grow.c
+++ b/Grow.c
@@ -69,7 +69,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
return 1;
}
- nfd = open(newdev, O_RDWR|O_EXCL);
+ nfd = open(newdev, O_RDWR|O_EXCL|O_DIRECT);
if (nfd < 0) {
fprintf(stderr, Name ": cannot open %s\n", newdev);
return 1;
diff --git a/Kill.c b/Kill.c
index eb74754..d5c1e36 100644
--- a/Kill.c
+++ b/Kill.c
@@ -44,7 +44,7 @@ int Kill(char *dev, int force, int quiet, int noexcl)
int fd, rv = 0;
struct supertype *st;
- fd = open(dev, noexcl ? O_RDWR : (O_RDWR|O_EXCL));
+ fd = open(dev, O_DIRECT | (noexcl ? O_RDWR : (O_RDWR|O_EXCL)));
if (fd < 0) {
if (!quiet)
fprintf(stderr, Name ": Couldn't open %s for write - not zeroing\n",
diff --git a/Manage.c b/Manage.c
index efc7c7a..90b5889 100644
--- a/Manage.c
+++ b/Manage.c
@@ -315,7 +315,7 @@ int Manage_subdevs(char *devname, int fd,
return 1;
}
/* Make sure it isn't in use (in 2.6 or later) */
- tfd = open(dv->devname, O_RDONLY|O_EXCL);
+ tfd = open(dv->devname, O_RDONLY|O_EXCL|O_DIRECT);
if (tfd < 0) {
fprintf(stderr, Name ": Cannot open %s: %s\n",
dv->devname, strerror(errno));
@@ -458,7 +458,7 @@ int Manage_subdevs(char *devname, int fd,
int dfd;
if (dv->writemostly)
disc.state |= 1 << MD_DISK_WRITEMOSTLY;
- dfd = open(dv->devname, O_RDWR | O_EXCL);
+ dfd = open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
tst->ss->add_to_super(tst, &disc, dfd,
dv->devname);
/* write_init_super will close 'dfd' */
diff --git a/bitmap.c b/bitmap.c
index fdf8884..8617669 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -122,11 +122,10 @@ bitmap_info_t *bitmap_fd_read(int fd, int brief)
*/
unsigned long long total_bits = 0, read_bits = 0, dirty_bits = 0;
bitmap_info_t *info;
- char *buf, *unaligned;
+ void *buf;
int n, skip;
- unaligned = malloc(8192*2);
- buf = (char*) ((unsigned long)unaligned | 8191)+1;
+ posix_memalign(&buf, 512, 8192);
n = read(fd, buf, 8192);
info = malloc(sizeof(*info));
@@ -145,7 +144,6 @@ bitmap_info_t *bitmap_fd_read(int fd, int brief)
fprintf(stderr, Name ": failed to read superblock of bitmap "
"file: %s\n", strerror(errno));
free(info);
- free(unaligned);
return NULL;
}
memcpy(&info->sb, buf, sizeof(info->sb));
diff --git a/mdadm.h b/mdadm.h
index 5e2cfe4..8a94035 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -791,6 +791,11 @@ static inline int dev2minor(int d)
return (-1-d) << MdpMinorShift;
}
+static inline int ROUND_UP(int a, int base)
+{
+ return ((a+base-1)/base)*base;
+}
+
#define LEVEL_MULTIPATH (-4)
#define LEVEL_LINEAR (-1)
#define LEVEL_FAULTY (-5)
diff --git a/super-ddf.c b/super-ddf.c
index b16001e..f29b8bf 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -31,11 +31,6 @@
#include "sha1.h"
#include <values.h>
-static inline int ROUND_UP(int a, int base)
-{
- return ((a+base-1)/base)*base;
-}
-
/* a non-official T10 name for creation GUIDs */
static char T10[] = "Linux-MD";
@@ -395,8 +390,9 @@ struct bad_block_log {
* built in Create or Assemble to describe the whole array.
*/
struct ddf_super {
- struct ddf_header anchor, primary, secondary, *active;
+ struct ddf_header anchor, primary, secondary;
struct ddf_controller_data controller;
+ struct ddf_header *active;
struct phys_disk *phys;
struct virtual_disk *virt;
int pdsize, vdsize;
@@ -404,22 +400,32 @@ struct ddf_super {
int currentdev;
int updates_pending;
struct vcl {
- struct vcl *next;
- __u64 *lba_offset; /* location in 'conf' of
- * the lba table */
- int vcnum; /* index into ->virt */
- __u64 *block_sizes; /* NULL if all the same */
+ union {
+ char space[512];
+ struct {
+ struct vcl *next;
+ __u64 *lba_offset; /* location in 'conf' of
+ * the lba table */
+ int vcnum; /* index into ->virt */
+ __u64 *block_sizes; /* NULL if all the same */
+ };
+ };
struct vd_config conf;
} *conflist, *currentconf;
struct dl {
- struct dl *next;
+ union {
+ char space[512];
+ struct {
+ struct dl *next;
+ int major, minor;
+ char *devname;
+ int fd;
+ unsigned long long size; /* sectors */
+ int pdnum; /* index in ->phys */
+ struct spare_assign *spare;
+ };
+ };
struct disk_data disk;
- int major, minor;
- char *devname;
- int fd;
- unsigned long long size; /* sectors */
- int pdnum; /* index in ->phys */
- struct spare_assign *spare;
struct vcl *vlist[0]; /* max_part in size */
} *dlist;
};
@@ -497,8 +503,10 @@ static void *load_section(int fd, struct ddf_super *super, void *buf,
/* All pre-allocated sections are a single block */
if (len != 1)
return NULL;
- } else
- buf = malloc(len<<9);
+ } else {
+ posix_memalign(&buf, 512, len<<9);
+ }
+
if (!buf)
return NULL;
@@ -633,8 +641,9 @@ static int load_ddf_local(int fd, struct ddf_super *super,
unsigned long long dsize;
/* First the local disk info */
- dl = malloc(sizeof(*dl) +
- (super->max_part) * sizeof(dl->vlist[0]));
+ posix_memalign((void**)&dl, 512,
+ sizeof(*dl) +
+ (super->max_part) * sizeof(dl->vlist[0]));
load_section(fd, super, &dl->disk,
super->active->data_section_offset,
@@ -683,7 +692,8 @@ static int load_ddf_local(int fd, struct ddf_super *super,
if (vd->magic == DDF_SPARE_ASSIGN_MAGIC) {
if (dl->spare)
continue;
- dl->spare = malloc(super->conf_rec_len*512);
+ posix_memalign((void**)&dl->spare, 512,
+ super->conf_rec_len*512);
memcpy(dl->spare, vd, super->conf_rec_len*512);
continue;
}
@@ -701,8 +711,9 @@ static int load_ddf_local(int fd, struct ddf_super *super,
__be32_to_cpu(vcl->conf.seqnum))
continue;
} else {
- vcl = malloc(super->conf_rec_len*512 +
- offsetof(struct vcl, conf));
+ posix_memalign((void**)&vcl, 512,
+ (super->conf_rec_len*512 +
+ offsetof(struct vcl, conf)));
vcl->next = super->conflist;
vcl->block_sizes = NULL; /* FIXME not for CONCAT */
super->conflist = vcl;
@@ -766,8 +777,7 @@ static int load_super_ddf(struct supertype *st, int fd,
}
}
- super = malloc(sizeof(*super));
- if (!super) {
+ if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) {
fprintf(stderr, Name ": malloc of %zu failed.\n",
sizeof(*super));
return 1;
@@ -1443,7 +1453,7 @@ static int init_super_ddf(struct supertype *st,
return init_super_ddf_bvd(st, info, size, name, homehost,
uuid);
- ddf = malloc(sizeof(*ddf));
+ posix_memalign((void**)&ddf, 512, sizeof(*ddf));
memset(ddf, 0, sizeof(*ddf));
ddf->dlist = NULL; /* no physical disks yet */
ddf->conflist = NULL; /* No virtual disks yet */
@@ -1570,7 +1580,8 @@ static int init_super_ddf(struct supertype *st,
memset(ddf->controller.pad, 0xff, 8);
memset(ddf->controller.vendor_data, 0xff, 448);
- pd = ddf->phys = malloc(pdsize);
+ posix_memalign((void**)&pd, 512, pdsize);
+ ddf->phys = pd;
ddf->pdsize = pdsize;
memset(pd, 0xff, pdsize);
@@ -1580,7 +1591,8 @@ static int init_super_ddf(struct supertype *st,
pd->max_pdes = __cpu_to_be16(max_phys_disks);
memset(pd->pad, 0xff, 52);
- vd = ddf->virt = malloc(vdsize);
+ posix_memalign((void**)&vd, 512, vdsize);
+ ddf->virt = vd;
ddf->vdsize = vdsize;
memset(vd, 0, vdsize);
vd->magic = DDF_VIRT_RECORDS_MAGIC;
@@ -1805,7 +1817,8 @@ static int init_super_ddf_bvd(struct supertype *st,
__cpu_to_be16(__be16_to_cpu(ddf->virt->populated_vdes)+1);
/* Now create a new vd_config */
- vcl = malloc(offsetof(struct vcl, conf) + ddf->conf_rec_len * 512);
+ posix_memalign((void**)&vcl, 512,
+ (offsetof(struct vcl, conf) + ddf->conf_rec_len * 512));
vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe];
vcl->vcnum = venum;
sprintf(st->subarray, "%d", venum);
@@ -1974,7 +1987,8 @@ static void add_to_super_ddf(struct supertype *st,
* a phys_disk entry and a more detailed disk_data entry.
*/
fstat(fd, &stb);
- dd = malloc(sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part);
+ posix_memalign((void**)&dd, 512,
+ sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part);
dd->major = major(stb.st_rdev);
dd->minor = minor(stb.st_rdev);
dd->devname = devname;
@@ -2037,7 +2051,7 @@ static void add_to_super_ddf(struct supertype *st,
#ifndef MDASSEMBLE
-static unsigned char null_conf[4096];
+static unsigned char null_conf[4096+512];
static int __write_init_super_ddf(struct supertype *st, int do_close)
{
@@ -2109,14 +2123,15 @@ static int __write_init_super_ddf(struct supertype *st, int do_close)
c->conf.crc = calc_crc(&c->conf, conf_size);
write(fd, &c->conf, conf_size);
} else {
+ char *null_aligned = (char*)((((unsigned long)null_conf)+511)&~511UL);
if (null_conf[0] != 0xff)
memset(null_conf, 0xff, sizeof(null_conf));
int togo = conf_size;
- while (togo > sizeof(null_conf)) {
- write(fd, null_conf, sizeof(null_conf));
- togo -= sizeof(null_conf);
+ while (togo > sizeof(null_conf)-512) {
+ write(fd, null_aligned, sizeof(null_conf)-512);
+ togo -= sizeof(null_conf)-512;
}
- write(fd, null_conf, togo);
+ write(fd, null_aligned, togo);
}
}
d->disk.crc = calc_crc(&d->disk, 512);
@@ -2425,8 +2440,7 @@ static int load_super_ddf_all(struct supertype *st, int fd,
strcmp(sra->text_version, "ddf") != 0)
return 1;
- super = malloc(sizeof(*super));
- if (!super)
+ if (posix_memalign((void**)&super, 512, sizeof(*super)) != 0)
return 1;
memset(super, 0, sizeof(*super));
@@ -2584,14 +2598,17 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
static int store_zero_ddf(struct supertype *st, int fd)
{
unsigned long long dsize;
- char buf[512];
- memset(buf, 0, 512);
+ void *buf;
if (!get_dev_size(fd, NULL, &dsize))
return 1;
+ posix_memalign(&buf, 512, 512);
+ memset(buf, 0, 512);
+
lseek64(fd, dsize-512, 0);
write(fd, buf, 512);
+ free(buf);
return 0;
}
@@ -2948,8 +2965,9 @@ static void ddf_prepare_update(struct supertype *st,
struct ddf_super *ddf = st->sb;
__u32 *magic = (__u32*)update->buf;
if (*magic == DDF_VD_CONF_MAGIC)
- update->space = malloc(offsetof(struct vcl, conf)
- + ddf->conf_rec_len * 512);
+ posix_memalign(&update->space, 512,
+ offsetof(struct vcl, conf)
+ + ddf->conf_rec_len * 512);
}
/*
@@ -3131,7 +3149,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
*/
mu = malloc(sizeof(*mu));
mu->buf = malloc(ddf->conf_rec_len * 512);
- mu->space = malloc(sizeof(struct vcl));
+ posix_memalign(&mu->space, 512, sizeof(struct vcl));
mu->len = ddf->conf_rec_len;
mu->next = *updates;
vc = find_vdcr(ddf, a->info.container_member);
diff --git a/super-intel.c b/super-intel.c
index dee107c..359b6fe 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -762,7 +762,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
size_t len, mpb_size;
unsigned long long sectors;
struct stat;
- struct imsm_super anchor;
+ struct imsm_super *anchor;
__u32 check_sum;
memset(super, 0, sizeof(*super));
@@ -776,44 +776,40 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
return 1;
}
- len = sizeof(anchor);
- if (read(fd, &anchor, len) != len) {
+ len = 512;
+ posix_memalign((void**)&anchor, 512, len);
+ if (read(fd, anchor, len) != len) {
if (devname)
fprintf(stderr,
Name ": Cannot read anchor block on %s: %s\n",
devname, strerror(errno));
+ free(anchor);
return 1;
}
- if (strncmp((char *) anchor.sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0) {
+ if (strncmp((char *) anchor->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0) {
if (devname)
fprintf(stderr,
Name ": no IMSM anchor on %s\n", devname);
+ free(anchor);
return 2;
}
- mpb_size = __le32_to_cpu(anchor.mpb_size);
- super->mpb = malloc(mpb_size < 512 ? 512 : mpb_size);
+ mpb_size = __le32_to_cpu(anchor->mpb_size);
+ mpb_size = ROUND_UP(mpb_size, 512);
+ posix_memalign((void**)&super->mpb, 512, mpb_size);
if (!super->mpb) {
if (devname)
fprintf(stderr,
Name ": unable to allocate %zu byte mpb buffer\n",
mpb_size);
+ free(anchor);
return 2;
}
- memcpy(super->buf, &anchor, sizeof(anchor));
+ memcpy(super->buf, anchor, len);
- /* read the rest of the first block */
- len = 512 - sizeof(anchor);
- if (read(fd, super->buf + sizeof(anchor), len) != len) {
- if (devname)
- fprintf(stderr,
- Name ": Cannot read anchor remainder on %s: %s\n",
- devname, strerror(errno));
- return 2;
- }
-
- sectors = mpb_sectors(&anchor) - 1;
+ sectors = mpb_sectors(anchor) - 1;
+ free(anchor);
if (!sectors)
return load_imsm_disk(fd, super, devname, 0);
@@ -1067,7 +1063,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
if (!super)
return 0;
mpb_size = disks_to_mpb_size(info->nr_disks);
- mpb = malloc(mpb_size);
+ posix_memalign((void**)&mpb, 512, mpb_size);
if (!mpb) {
free(super);
return 0;
@@ -1281,7 +1277,7 @@ static int write_init_super_imsm(struct supertype *st)
static int store_zero_imsm(struct supertype *st, int fd)
{
unsigned long long dsize;
- char buf[512];
+ void *buf;
get_dev_size(fd, NULL, &dsize);
@@ -1289,6 +1285,7 @@ static int store_zero_imsm(struct supertype *st, int fd)
if (lseek64(fd, dsize - (512 * 2), SEEK_SET) < 0)
return 1;
+ posix_memalign(&buf, 512, 512);
memset(buf, 0, sizeof(buf));
if (write(fd, buf, sizeof(buf)) != sizeof(buf))
return 1;
diff --git a/super0.c b/super0.c
index dc8af8f..ae9e662 100644
--- a/super0.c
+++ b/super0.c
@@ -554,8 +554,10 @@ static int init_super0(struct supertype *st, mdu_array_info_t *info,
unsigned long long size, char *ignored_name, char *homehost,
int *uuid)
{
- mdp_super_t *sb = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
+ mdp_super_t *sb;
int spares;
+
+ posix_memalign((void**)&sb, 512, MD_SB_BYTES + sizeof(bitmap_super_t));
memset(sb, 0, MD_SB_BYTES + sizeof(bitmap_super_t));
st->sb = sb;
@@ -684,7 +686,8 @@ static int store_super0(struct supertype *st, int fd)
if (super->state & (1<<MD_SB_BITMAP_PRESENT)) {
struct bitmap_super_s * bm = (struct bitmap_super_s*)(super+1);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC)
- if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
+ if (write(fd, bm, ROUND_UP(sizeof(*bm),512)) !=
+ ROUND_UP(sizeof(*bm),512))
return 5;
}
@@ -744,7 +747,8 @@ static int compare_super0(struct supertype *st, struct supertype *tst)
if (second->md_magic != MD_SB_MAGIC)
return 1;
if (!first) {
- first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s));
+ posix_memalign((void**)&first, 512,
+ MD_SB_BYTES + sizeof(struct bitmap_super_s));
memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s));
st->sb = first;
return 0;
@@ -813,7 +817,7 @@ static int load_super0(struct supertype *st, int fd, char *devname)
return 1;
}
- super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
+ posix_memalign((void**)&super, 512, MD_SB_BYTES + sizeof(bitmap_super_t)+512);
if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
if (devname)
@@ -857,8 +861,8 @@ static int load_super0(struct supertype *st, int fd, char *devname)
* valid. If it doesn't clear the bit. An --assemble --force
* should get that written out.
*/
- if (read(fd, super+1, sizeof(struct bitmap_super_s))
- != sizeof(struct bitmap_super_s))
+ if (read(fd, super+1, ROUND_UP(sizeof(struct bitmap_super_s),512))
+ != ROUND_UP(sizeof(struct bitmap_super_s),512))
goto no_bitmap;
uuid_from_super0(st, uuid);
@@ -986,7 +990,8 @@ static int write_bitmap0(struct supertype *st, int fd)
int rv = 0;
int towrite, n;
- char buf[4096];
+ char abuf[4096+512];
+ char *buf = (char*)(((long)(abuf+512))&~511UL);
if (!get_dev_size(fd, NULL, &dsize))
return 1;
@@ -1002,21 +1007,19 @@ static int write_bitmap0(struct supertype *st, int fd)
if (lseek64(fd, offset + 4096, 0)< 0LL)
return 3;
-
- if (write(fd, ((char*)sb)+MD_SB_BYTES, sizeof(bitmap_super_t)) !=
- sizeof(bitmap_super_t))
- return -2;
- towrite = 64*1024 - MD_SB_BYTES - sizeof(bitmap_super_t);
- memset(buf, 0xff, sizeof(buf));
+ memset(buf, 0xff, 4096);
+ memcpy(buf, ((char*)sb)+MD_SB_BYTES, sizeof(bitmap_super_t));
+ towrite = 64*1024;
while (towrite > 0) {
n = towrite;
- if (n > sizeof(buf))
- n = sizeof(buf);
+ if (n > 4096)
+ n = 4096;
n = write(fd, buf, n);
if (n > 0)
towrite -= n;
else
break;
+ memset(buf, 0xff, 4096);
}
fsync(fd);
if (towrite)
diff --git a/super1.c b/super1.c
index 9c712fc..507e418 100644
--- a/super1.c
+++ b/super1.c
@@ -671,7 +671,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
__le64_to_cpu(sb->data_offset)) {
/* set data_size to device size less data_offset */
struct misc_dev_info *misc = (struct misc_dev_info*)
- (st->sb + 1024 + sizeof(struct bitmap_super_s));
+ (st->sb + 1024 + 512);
printf("Size was %llu\n", (unsigned long long)
__le64_to_cpu(sb->data_size));
sb->data_size = __cpu_to_le64(
@@ -689,11 +689,13 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
static int init_super1(struct supertype *st, mdu_array_info_t *info,
unsigned long long size, char *name, char *homehost, int *uuid)
{
- struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t) +
- sizeof(struct misc_dev_info));
+ struct mdp_superblock_1 *sb;
int spares;
int rfd;
char defname[10];
+
+ posix_memalign((void**)&sb, 512, (1024 + 512 +
+ sizeof(struct misc_dev_info)));
memset(sb, 0, 1024);
st->sb = sb;
@@ -857,6 +859,7 @@ static int store_super1(struct supertype *st, int fd)
return 3;
sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
+ sbsize = (sbsize+511)&(~511UL);
if (write(fd, sb, sbsize) != sbsize)
return 4;
@@ -866,7 +869,8 @@ static int store_super1(struct supertype *st, int fd)
(((char*)sb)+1024);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
locate_bitmap1(st, fd);
- if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
+ if (write(fd, bm, ROUND_UP(sizeof(*bm),512)) !=
+ ROUND_UP(sizeof(*bm),512))
return 5;
}
}
@@ -1035,9 +1039,10 @@ static int compare_super1(struct supertype *st, struct supertype *tst)
return 1;
if (!first) {
- first = malloc(1024+sizeof(bitmap_super_t) +
+ posix_memalign((void**)&first, 512,
+ 1024 + 512 +
sizeof(struct misc_dev_info));
- memcpy(first, second, 1024+sizeof(bitmap_super_t) +
+ memcpy(first, second, 1024 + 512 +
sizeof(struct misc_dev_info));
st->sb = first;
return 0;
@@ -1150,7 +1155,8 @@ static int load_super1(struct supertype *st, int fd, char *devname)
return 1;
}
- super = malloc(1024 + sizeof(bitmap_super_t) +
+ posix_memalign((void**)&super, 512,
+ 1024 + 512 +
sizeof(struct misc_dev_info));
if (read(fd, super, 1024) != 1024) {
@@ -1187,7 +1193,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
bsb = (struct bitmap_super_s *)(((char*)super)+1024);
- misc = (struct misc_dev_info*) (bsb+1);
+ misc = (struct misc_dev_info*) (((char*)super)+1024+512);
misc->device_size = dsize;
/* Now check on the bitmap superblock */
@@ -1198,8 +1204,8 @@ static int load_super1(struct supertype *st, int fd, char *devname)
* should get that written out.
*/
locate_bitmap1(st, fd);
- if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
- != sizeof(struct bitmap_super_s))
+ if (read(fd, ((char*)super)+1024, 512)
+ != 512)
goto no_bitmap;
uuid_from_super1(st, uuid);
@@ -1419,25 +1425,28 @@ static int write_bitmap1(struct supertype *st, int fd)
int rv = 0;
int towrite, n;
- char buf[4096];
+ char abuf[4096+512];
+ char *buf = (char*)(((long)(abuf+512))&~511UL);
locate_bitmap1(st, fd);
- if (write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t)) !=
- sizeof(bitmap_super_t))
- return -2;
+ memset(buf, 0xff, 4096);
+ memcpy(buf, ((char*)sb)+1024, sizeof(bitmap_super_t));
+
towrite = __le64_to_cpu(bms->sync_size) / (__le32_to_cpu(bms->chunksize)>>9);
towrite = (towrite+7) >> 3; /* bits to bytes */
- memset(buf, 0xff, sizeof(buf));
+ towrite += sizeof(bitmap_super_t);
+ towrite = ROUND_UP(towrite, 512);
while (towrite > 0) {
n = towrite;
- if (n > sizeof(buf))
- n = sizeof(buf);
+ if (n > 4096)
+ n = 4096;
n = write(fd, buf, n);
if (n > 0)
towrite -= n;
else
break;
+ memset(buf, 0xff, 4096);
}
fsync(fd);
if (towrite)
diff --git a/util.c b/util.c
index 49c36a0..5534266 100644
--- a/util.c
+++ b/util.c
@@ -761,11 +761,11 @@ int dev_open(char *dev, int flags)
snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d:%d",
(int)getpid(), major, minor);
if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
- fd = open(devname, flags);
+ fd = open(devname, flags|O_DIRECT);
unlink(devname);
}
} else
- fd = open(dev, flags);
+ fd = open(dev, flags|O_DIRECT);
return fd;
}