]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Merge branch 'master' of git://github.com/djbw/mdadm into devel-3.0
authorNeilBrown <neilb@suse.de>
Tue, 14 Apr 2009 01:11:14 +0000 (11:11 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 14 Apr 2009 01:11:14 +0000 (11:11 +1000)
Conflicts:
Grow.c
mdadm.h
sysfs.c
Due to independent fixes for the "mdadm hangs if reshape finishes too quickly"
problem.

1  2 
Grow.c
mapfile.c
mdadm.h
super-ddf.c
sysfs.c

diff --combined Grow.c
index fc809c63a68d03d8121a97d9a601fc88ca2cf22d,7083c184c51456b24255cfea9a8af7f5cdc14758..15cec5f103bf874bdb4669a97086dce333089bee
--- 1/Grow.c
--- 2/Grow.c
+++ b/Grow.c
@@@ -809,20 -809,20 +809,21 @@@ int Grow_reshape(char *devname, int fd
                /* wait for reshape to pass the critical region */
                while(1) {
                        unsigned long long comp;
 -                      char a[20];
                        if (sysfs_get_ll(sra, NULL, "sync_completed", &comp)<0) {
                                sleep(5);
                                break;
                        }
                        if (comp >= nstripe)
                                break;
 -
 -                      /* perhaps the entire reshape has completed */
 -                      if (comp == 0 &&
 -                          sysfs_get_str(sra, NULL, "sync_action", a, sizeof(a)) == 0 &&
 -                          strncmp(a, "idle", 4) == 0)
 -                              break;
 +                      if (comp == 0) {
 +                              /* Maybe it finished already */
 +                              char action[20];
 +                              if (sysfs_get_str(sra, NULL, "sync_action",
 +                                                action, 20) > 0 &&
 +                                  strncmp(action, "reshape", 7) != 0)
 +                                      break;
 +                      }
                        sleep(1);
                }
  
diff --combined mapfile.c
index 9e973ef2743264ac32fb4d9e524149260c4c847d,f27623221ce9e706cec05d29d0140447bcc7e3fa..01185e6dbf5eb6b7870f3bca8a9a01688d06bbf8
+++ b/mapfile.c
@@@ -2,7 -2,7 +2,7 @@@
   * mapfile - manage /var/run/mdadm.map. Part of:
   * mdadm - manage Linux "md" devices aka RAID arrays.
   *
 - * Copyright (C) 2006 Neil Brown <neilb@suse.de>
 + * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
   *
   *
   *    This program is free software; you can redistribute it and/or modify
   *  UUID       -  uuid of the array
   *  path       -  path where device created: /dev/md/home
   *
 + * The preferred location for the map file is /var/run/mdadm.map.
 + * However /var/run may not exist or be writable in early boot.  And if
 + * no-one has created /var/run/mdadm, we still want to survive.
 + * So possible locations are:
 + *   /var/run/mdadm/map  /var/run/mdadm.map  /dev/.mdadm.map
 + * the last, because udev requires a writable /dev very early.
 + * We read from the first one that exists and write to the first
 + * one that we can.
   */
 +#include "mdadm.h"
  
 +#define mapnames(base) { #base, #base ".new", #base ".lock"}
 +char *mapname[3][3] = {
 +      mapnames(/var/run/mdadm/map),
 +      mapnames(/var/run/mdadm.map),
 +      mapnames(/dev/.mdadm.map)
 +};
  
 -#include "mdadm.h"
 +int mapmode[3] = { O_RDONLY, O_RDWR|O_CREAT, O_RDWR|O_CREAT | O_TRUNC };
 +char *mapsmode[3] = { "r", "w", "w"};
  
 +FILE *open_map(int modenum, int *choice)
 +{
 +      int i;
 +      for (i = 0 ; i < 3 ; i++) {
 +              int fd = open(mapname[i][modenum], mapmode[modenum], 0600);
 +              if (fd >= 0) {
 +                      *choice = i;
 +                      return fdopen(fd, mapsmode[modenum]);
 +              }
 +      }
 +      return NULL;
 +}
  
  int map_write(struct map_ent *mel)
  {
        FILE *f;
        int err;
 -      int subdir = 1;
 +      int which;
 +
 +      f = open_map(1, &which);
  
 -      f = fopen("/var/run/mdadm/map.new", "w");
 -      if (!f) {
 -              f = fopen("/var/run/mdadm.map.new", "w");
 -              subdir = 0;
 -      }
        if (!f)
                return 0;
        for (; mel; mel = mel->next) {
        err = ferror(f);
        fclose(f);
        if (err) {
 -              if (subdir)
 -                      unlink("/var/run/mdadm/map.new");
 -              else
 -                      unlink("/var/run/mdadm.map.new");
 +              unlink(mapname[which][1]);
                return 0;
        }
 -      if (subdir)
 -              return rename("/var/run/mdadm/map.new",
 -                            "/var/run/mdadm/map") == 0;
 -      else
 -              return rename("/var/run/mdadm.map.new",
 -                            "/var/run/mdadm.map") == 0;
 +      return rename(mapname[which][1],
 +                    mapname[which][0]) == 0;
  }
  
  
 -static int lfd = -1;
 -static int lsubdir = 0;
 +static FILE *lf = NULL;
 +static int lwhich = 0;
  int map_lock(struct map_ent **melp)
  {
 -      if (lfd < 0) {
 -              lfd = open("/var/run/mdadm/map.lock", O_CREAT|O_RDWR, 0600);
 -              if (lfd < 0) {
 -                      lfd = open("/var/run/mdadm.map.lock", O_CREAT|O_RDWR, 0600);
 -                      lsubdir = 0;
 -              } else
 -                      lsubdir = 1;
 -              if (lfd < 0)
 +      if (lf == NULL) {
 +              lf = open_map(2, &lwhich);
 +              if (lf == NULL)
                        return -1;
 -              if (lockf(lfd, F_LOCK, 0) != 0) {
 -                      close(lfd);
 -                      lfd = -1;
 +              if (lockf(fileno(lf), F_LOCK, 0) != 0) {
 +                      fclose(lf);
 +                      lf = NULL;
                        return -1;
                }
        }
  
  void map_unlock(struct map_ent **melp)
  {
 -      if (lfd >= 0)
 -              close(lfd);
 -      if (lsubdir)
 -              unlink("/var/run/mdadm/map.lock");
 -      else
 -              unlink("/var/run/mdadm.map.lock");
 -      lfd = -1;
 +      if (lf)
 +              fclose(lf);
 +      unlink(mapname[lwhich][2]);
 +      lf = NULL;
  }
  
  void map_add(struct map_ent **melp,
@@@ -156,15 -146,18 +156,15 @@@ void map_read(struct map_ent **melp
        int devnum, uuid[4];
        char metadata[30];
        char nam[4];
 +      int which;
  
        *melp = NULL;
  
 -      f = fopen("/var/run/mdadm/map", "r");
 -      if (!f)
 -              f = fopen("/var/run/mdadm.map", "r");
 +      f = open_map(0, &which);
        if (!f) {
                RebuildMap();
 -              f = fopen("/var/run/mdadm/map", "r");
 +              f = open_map(0, &which);
        }
 -      if (!f)
 -              f = fopen("/var/run/mdadm.map", "r");
        if (!f)
                return;
  
@@@ -301,9 -294,12 +301,12 @@@ void RebuildMap(void
        int mdp = get_mdp_major();
  
        for (md = mdstat ; md ; md = md->next) {
-               struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_DEVS);
+               struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_DEVS|SKIP_GONE_DEVS);
                struct mdinfo *sd;
  
+               if (!sra)
+                       continue;
                for (sd = sra->devs ; sd ; sd = sd->next) {
                        char dn[30];
                        int dfd;
diff --combined mdadm.h
index 357dc43313d93e52525d5609edcb72ac40a53740,82c7dedffd641a1c51d2611ac791bc4ef09d85b3..251f9a130436e3e360d9d436829c79167d774b8c
+++ b/mdadm.h
@@@ -146,6 -146,9 +146,9 @@@ struct mdinfo 
        unsigned long long      component_size; /* same as array.size, except in
                                                 * sectors and up to 64bits.
                                                 */
+       unsigned long long      custom_array_size; /* size for non-default sized
+                                                   * arrays (in sectors)
+                                                   */
        int                     reshape_active;
        unsigned long long      reshape_progress;
        unsigned long long      resync_start;
@@@ -370,11 -373,10 +373,11 @@@ extern int sysfs_uevent(struct mdinfo *
  extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev,
                        char *name, unsigned long long *val);
  extern int sysfs_get_str(struct mdinfo *sra, struct mdinfo *dev,
 -                       char *name, char *buf, int buf_len);
 +                       char *name, char *val, int size);
  extern int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms);
  extern int sysfs_set_array(struct mdinfo *info, int vers);
 -extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd);
 +extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd,
 +                        int in_sync);
  extern int sysfs_disk_to_scsi_id(int fd, __u32 *id);
  extern int sysfs_unique_holder(int devnum, long rdev);
  extern int load_sys(char *path, char *buf);
@@@ -658,7 -660,7 +661,7 @@@ extern struct supertype *dup_super(stru
  extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
  extern void get_one_disk(int mdfd, mdu_array_info_t *ainf,
                         mdu_disk_info_t *disk);
 -void wait_for(char *dev);
 +void wait_for(char *dev, int fd);
  
  #if __GNUC__ < 3
  struct stat64;
diff --combined super-ddf.c
index d22c88c7e1fffba8830b56c4b8ddd1d5798318bf,6a8705567957a645ae1195bd59fa755021790327..fa4d351cf2ed35d08f121e67e10d4fec64134aae
@@@ -643,7 -643,6 +643,7 @@@ static int load_ddf_local(int fd, struc
        struct stat stb;
        char *conf;
        int i;
 +      int confsec;
        int vnum;
        int max_virt_disks = __be16_to_cpu(super->active->max_vd_entries);
        unsigned long long dsize;
                            0);
  
        vnum = 0;
 -      for (i = 0;
 -           i < __be32_to_cpu(super->active->config_section_length);
 -           i += super->conf_rec_len) {
 +      for (confsec = 0;
 +           confsec < __be32_to_cpu(super->active->config_section_length);
 +           confsec += super->conf_rec_len) {
                struct vd_config *vd =
 -                      (struct vd_config *)((char*)conf + i*512);
 +                      (struct vd_config *)((char*)conf + confsec*512);
                struct vcl *vcl;
  
                if (vd->magic == DDF_SPARE_ASSIGN_MAGIC) {
@@@ -782,20 -781,22 +782,20 @@@ static int load_super_ddf(struct supert
  
        /* 32M is a lower bound */
        if (dsize <= 32*1024*1024) {
 -              if (devname) {
 +              if (devname)
                        fprintf(stderr,
                                Name ": %s is too small for ddf: "
                                "size is %llu sectors.\n",
                                devname, dsize>>9);
 -                      return 1;
 -              }
 +              return 1;
        }
        if (dsize & 511) {
 -              if (devname) {
 +              if (devname)
                        fprintf(stderr,
                                Name ": %s is an odd size for ddf: "
                                "size is %llu bytes.\n",
                                devname, dsize);
 -                      return 1;
 -              }
 +              return 1;
        }
  
        if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) {
@@@ -1061,9 -1062,9 +1061,9 @@@ static void examine_vd(int n, struct dd
                               map_num(ddf_sec_level, vc->srl) ?: "-unknown-");
                }
                printf("  Device Size[%d] : %llu\n", n,
 -                     __be64_to_cpu(vc->blocks)/2);
 +                     (unsigned long long)__be64_to_cpu(vc->blocks)/2);
                printf("   Array Size[%d] : %llu\n", n,
 -                     __be64_to_cpu(vc->array_blocks)/2);
 +                     (unsigned long long)__be64_to_cpu(vc->array_blocks)/2);
        }
  }
  
@@@ -1099,7 -1100,7 +1099,7 @@@ static void examine_pds(struct ddf_supe
        int i;
        struct dl *dl;
        printf(" Physical Disks : %d\n", cnt);
 -      printf("      Number    RefNo    Size       Device    Type/State\n");
 +      printf("      Number    RefNo      Size       Device      Type/State\n");
  
        for (i=0 ; i<cnt ; i++) {
                struct phys_disk_entry *pd = &sb->phys->entries[i];
                //printf("\n");
                printf("       %3d    %08x  ", i,
                       __be32_to_cpu(pd->refnum));
 -              printf("%lluK ",  __be64_to_cpu(pd->config_size)>>1);
 +              printf("%8lluK ", 
 +                     (unsigned long long)__be64_to_cpu(pd->config_size)>>1);
                for (dl = sb->dlist; dl ; dl = dl->next) {
                        if (dl->disk.refnum == pd->refnum) {
                                char *dv = map_dev(dl->major, dl->minor, 0);
                                if (dv) {
 -                                      printf("%-10s", dv);
 +                                      printf("%-15s", dv);
                                        break;
                                }
                        }
                }
                if (!dl)
 -                      printf("%10s","");
 +                      printf("%15s","");
                printf(" %s%s%s%s%s",
                       (type&2) ? "active":"",
                       (type&4) ? "Global-Spare":"",
@@@ -1374,6 -1374,7 +1374,7 @@@ static void getinfo_super_ddf_bvd(struc
                __be32_to_cpu(*(__u32*)(vc->conf.guid+16));
        info->array.utime         = DECADE + __be32_to_cpu(vc->conf.timestamp);
        info->array.chunk_size    = 512 << vc->conf.chunk_shift;
+       info->custom_array_size   = 0;
  
        if (cd >= 0 && cd < ddf->mppe) {
                info->data_offset         = __be64_to_cpu(vc->lba_offset[cd]);
@@@ -2653,8 -2654,6 +2654,8 @@@ validate_geometry_ddf_container(struct 
        close(fd);
  
        *freesize = avail_size_ddf(st, ldsize >> 9);
 +      if (*freesize == 0)
 +              return 0;
  
        return 1;
  }
@@@ -2919,8 -2918,6 +2920,8 @@@ static struct mdinfo *container_content
                        if (vc->conf.phys_refnum[i] == 0xFFFFFFFF)
                                continue;
  
 +                      this->array.working_disks++;
 +
                        for (d = ddf->dlist; d ; d=d->next)
                                if (d->disk.refnum == vc->conf.phys_refnum[i])
                                        break;
                                /* Haven't found that one yet, maybe there are others */
                                continue;
  
 -                      this->array.working_disks++;
 -
                        dev = malloc(sizeof(*dev));
                        memset(dev, 0, sizeof(*dev));
                        dev->next = this->devs;
diff --combined sysfs.c
index 711dce13e876d4befb41f0092c79422878776806,31c92f78b79b91c8472ae079c118b670de2a2cf7..b6156636f9811c1df344f484e126ac60e3ccae2f
+++ b/sysfs.c
@@@ -467,22 -467,23 +467,22 @@@ int sysfs_get_ll(struct mdinfo *sra, st
  }
  
  int sysfs_get_str(struct mdinfo *sra, struct mdinfo *dev,
 -                char *name, char *buf, int buf_len)
 +                     char *name, char *val, int size)
  {
        char fname[50];
        int n;
        int fd;
 -
        sprintf(fname, "/sys/block/%s/md/%s/%s",
                sra->sys_name, dev?dev->sys_name:"", name);
        fd = open(fname, O_RDONLY);
        if (fd < 0)
                return -1;
 -      n = read(fd, buf, buf_len);
 +      n = read(fd, val, size);
        close(fd);
        if (n <= 0)
                return -1;
 -      buf[n] = 0;
 -      return 0;
 +      val[n] = 0;
 +      return n;
  }
  
  int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms)
@@@ -525,12 -526,26 +525,26 @@@ int sysfs_set_array(struct mdinfo *info
        rv |= sysfs_set_num(info, NULL, "chunk_size", info->array.chunk_size);
        rv |= sysfs_set_num(info, NULL, "layout", info->array.layout);
        rv |= sysfs_set_num(info, NULL, "component_size", info->component_size/2);
+       if (info->custom_array_size) {
+               int rc;
+               rc = sysfs_set_num(info, NULL, "array_size",
+                                  info->custom_array_size/2);
+               if (rc && errno == ENOENT) {
+                       fprintf(stderr, Name ": This kernel does not "
+                               "have the md/array_size attribute, "
+                               "the array may be larger than expected\n");
+                       rc = 0;
+               }
+               rv |= rc;
+       }
        if (info->array.level > 0)
                rv |= sysfs_set_num(info, NULL, "resync_start", info->resync_start);
        return rv;
  }
  
 -int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd)
 +int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int in_sync)
  {
        char dv[100];
        char nm[100];
        rv = sysfs_set_num(sra, sd, "offset", sd->data_offset);
        rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2);
        if (sra->array.level != LEVEL_CONTAINER) {
 +              if (in_sync)
 +                      /* This can correctly fail if array isn't started,
 +                       * yet, so just ignore status for now.
 +                       */
 +                      sysfs_set_str(sra, sd, "state", "in_sync");
                rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk);
 -//            rv |= sysfs_set_str(sra, sd, "state", "in_sync");
        }
        return rv;
  }