[PATCH 20/33] Added disk util functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Czarnowska, Anna 
Sent: Monday, July 05, 2010 11:34 AM
To: Neil Brown
Cc: linux-raid@xxxxxxxxxxxxxxx; Czarnowska, Anna; Hawrylewicz Czarnowski, Przemyslaw; Labun, Marcin; Neubauer, Wojciech; Williams, Dan J; Ciechanowski, Ed; dledford@xxxxxxxxxx
Subject: [PATCH 20/33] Added disk util functions

Needed for checking suitability of a disk to use for rebuild.

Signed-off-by: Anna Czarnowska <anna.czarnowska@xxxxxxxxx>
---
 mdadm.h       |   11 +++++++++++
 super-ddf.c   |   36 ++++++++++++++++++++++++++++++++++++
 super-intel.c |   31 +++++++++++++++++++++++++++++++
 util.c        |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/mdadm.h b/mdadm.h
index b6d7933..86f5370 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -277,6 +277,12 @@ enum special_options {
      DetailPlatform,
 };
 
+enum disk_status {
+     unknown,
+     spare_disk,
+     failed_disk,
+};
+
 enum domain_actions {
      ignore,
      incremental,
@@ -656,6 +662,8 @@ extern struct superswitch {
      int (*load_super)(struct supertype *st, int fd, char *devname);
      struct supertype * (*match_metadata_desc)(char *arg);
      __u64 (*avail_size)(struct supertype *st, __u64 size);
+
+     enum disk_status (*get_disk_status)(struct supertype *st, int major, 
+int minor);
      int (*add_internal_bitmap)(struct supertype *st, int *chunkp,
                           int delay, int write_behind,
                           unsigned long long size, int may_change, int major); @@ -795,6 +803,7 @@ extern struct supertype *super_by_fd(int fd);  extern 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 dev_size_from_id(int id, unsigned long long *ssize);
 extern void get_one_disk(int mdfd, mdu_array_info_t *ainf,
                   mdu_disk_info_t *disk);
 void wait_for(char *dev, int fd);
@@ -1023,6 +1032,8 @@ extern int get_active_array_domain(char *array_name, int fd,
                           struct domain_ent **domain,
                           struct subset **subset);
 extern int is_external(char *metadata_verison);
+extern int disk_faulty(struct supertype *sty, int major, int minor); 
+extern int disk_faulty_from_id(int devid);
 
 static inline int dev2major(int d)
 {
diff --git a/super-ddf.c b/super-ddf.c
index b01c68d..aa5dc89 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -2436,6 +2436,41 @@ static __u64 avail_size_ddf(struct supertype *st, __u64 devsize)
      return devsize - 32*1024*2;
 }
 
+/* Get the disk status from metadata. 1 for spare, 2 for failed disk, 0 
+otherwise */ static enum disk_status get_disk_status_ddf(struct 
+supertype *st, int major, int minor) {
+     if (!st)
+           return unknown;
+
+     struct ddf_super *super = st->sb;
+     struct phys_disk_entry disk;
+     struct dl *list;
+     int i;
+
+     if (!super)
+           return unknown;
+     list = super->dlist;
+
+     i = -1;
+     while (list) {
+           if (list->major == major && list->minor == minor) {
+                 i = list->pdnum;
+                 break;
+           }
+           list = list->next;
+     }
+     if (i == -1)
+           return unknown;
+
+     disk = super->phys->entries[i];
+     if (__be16_to_cpu(disk.state) & DDF_Failed)
+           return failed_disk;
+     if ((__be16_to_cpu(disk.type) & DDF_Global_Spare) ||
+         (__be16_to_cpu(disk.type) & DDF_Spare))
+           return spare_disk;
+     return unknown;
+}
+
 #ifndef MDASSEMBLE
 
 static int reserve_space(struct supertype *st, int raiddisks, @@ -3658,6 +3693,7 @@ struct superswitch super_ddf = {
      .update_super     = update_super_ddf,
 
      .avail_size = avail_size_ddf,
+     .get_disk_status = get_disk_status_ddf,
 
      .compare_super    = compare_super_ddf,
 
diff --git a/super-intel.c b/super-intel.c index 4dcc654..6762129 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1710,6 +1710,36 @@ static __u64 avail_size_imsm(struct supertype *st, __u64 devsize)
      return devsize - (MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS);  }
 
+static int serialcmp(__u8 *s1, __u8 *s2);
+
+/* Get the disk status from metadata. 1 for spare, 2 for failed disk, 0 
+otherwise */ static enum disk_status get_disk_status_imsm(struct 
+supertype *st, int major, int minor) {
+     if (!st)
+           return unknown;
+
+     struct intel_super *super = st->sb;
+     struct imsm_disk *disk;
+     struct dl *dlist;
+
+     if (!super)
+           return unknown;
+     dlist = super->disks;
+
+     while (dlist) {
+           disk = &dlist->disk;
+           if (major == dlist->major && minor == dlist->minor) {
+                 if (disk->status & FAILED_DISK)
+                       return failed_disk;
+                 if (disk->status & SPARE_DISK)
+                       return spare_disk;
+                 return unknown;
+           }
+           dlist = dlist->next;
+     }
+     return unknown;
+}
+
 static void free_devlist(struct intel_super *super)  {
      struct intel_dev *dv;
@@ -5336,6 +5366,7 @@ struct superswitch super_imsm = {
      .update_super     = update_super_imsm,
 
      .avail_size = avail_size_imsm,
+     .get_disk_status = get_disk_status_imsm,
 
      .compare_super    = compare_super_imsm,
 
diff --git a/util.c b/util.c
index a746b83..fcc9e69 100644
--- a/util.c
+++ b/util.c
@@ -1246,6 +1246,24 @@ int get_dev_size(int fd, char *dname, unsigned long long *sizep)
      return 1;
 }
 
+int dev_size_from_id(int id, unsigned long long *ssize) {
+     char *dv;
+     int fd;
+
+     dv = map_dev(major(id), minor(id), 1);
+     if (!dv)
+           return 0;
+     fd = open(dv, O_RDONLY);
+     if (fd < 0)
+           return 0;
+     if (get_dev_size(fd, dv, ssize)) {
+           close(fd);
+           return 1;
+     }
+     close(fd);
+     return 0;
+}
 
 /* Sets endofpart parameter to the last block used by the last GPT partition on the device.
  * Returns: 1 if successful
@@ -1776,6 +1794,43 @@ char *get_devpath_from_devname(char *devname)
      return NULL;
 }
 
+/* Check if disk has failed status in metadata*/ int disk_faulty(struct 
+supertype *sty, int major, int minor) {
+     enum disk_status status;
+     if (!sty)
+           return 1;
+     status = sty->ss->get_disk_status(sty, major, minor);
+     return status == failed_disk;
+}
+
+int disk_faulty_from_id(int devid)
+{
+     struct supertype *sty;
+     int fd, rv = 1;
+     char *devname;
+     if (devid <= 0)
+           return rv;
+     devname = map_dev(major(devid), minor(devid), 1);
+     if (!devname)
+           return rv;
+     fd = open(devname, O_RDONLY);
+     if (fd < 0)
+           return rv;
+     sty = guess_super(fd);
+     if (!sty) {
+           close(fd);
+           return rv;
+     }
+     rv = sty->ss->load_super(sty, fd, devname);
+     if (!rv)
+           rv = disk_faulty(sty, major(devid), minor(devid));
+     close(fd);
+     sty->ss->free_super(sty);
+     free(sty);
+     return rv;
+}
+
 static int sfdisk_validate(struct domain_ent *domain)  {
      return 0;
--
1.6.4.2


--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux