]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Use O_DIRECT for all IO to devices.
authorNeil Brown <neilb@suse.de>
Sat, 12 Jul 2008 10:28:33 +0000 (20:28 +1000)
committerNeil Brown <neilb@suse.de>
Sat, 12 Jul 2008 10:28:33 +0000 (20:28 +1000)
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.

Grow.c
Kill.c
Manage.c
bitmap.c
mdadm.h
super-ddf.c
super-intel.c
super0.c
super1.c
util.c

diff --git a/Grow.c b/Grow.c
index b24e9587c192c8a1e96b42e46d2c167ee87290f8..fc007d6bbe27892edae0a395455c946a44a003e6 100644 (file)
--- 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 eb7475416322b94862115314012f960c79421731..d5c1e36df4d3724e6cf060238902cb897e01bfed 100644 (file)
--- 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",
index efc7c7a8e71d60be942924f61237620601190a3a..90b58897cf4e88f16c13355afa31dc234c011647 100644 (file)
--- 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' */
index fdf8884ddfe3d31524d6e583594adfa278425c82..86176696f957edef9d88955e869612ba6c47de85 100644 (file)
--- 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 5e2cfe41c1fc3eeb493c7c65c642dba000f5a3fe..8a94035310db12332e65bcce63739f0f531ef655 100644 (file)
--- 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)
index b16001e9fc1c75c0bbcf0046203364a67f6fef60..f29b8bf2ac9c67a8880fe70eda6de0649cc65e53 100644 (file)
 #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);
index dee107cd65d2721e8db37d82c33bd423b58274b6..359b6fe1f141240715296d283f1bcca77802fc38 100644 (file)
@@ -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;
index dc8af8fc033a0df4dd030a0248f8b5335af946d3..ae9e662afc525a37fc76167891765d68f7e1e520 100644 (file)
--- 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)
index 9c712fc4af515ec50831a7831d334b086d2afe77..507e418ceebd73955a2a2a44baf586415631abfd 100644 (file)
--- 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 49c36a06cafb43127e5be0214db8f87c4e6c6038..553426647aede5ad69063e694640d6a052fb8328 100644 (file)
--- 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;
 }