]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
mdadm-1.0.0
[thirdparty/mdadm.git] / Manage.c
index 302a425b27110147bb40720e5634a9692dfe6f89..34076cbfe63e0d7d13b64b984950902d72e1a2a5 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -1,7 +1,7 @@
 /*
- * mdctl - manage Linux "md" devices aka RAID arrays.
+ * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *           Australia
  */
 
-#include "mdctl.h"
+#include "mdadm.h"
+#include "md_u.h"
+#include "md_p.h"
+
+#define REGISTER_DEV           _IO (MD_MAJOR, 1)
+#define START_MD               _IO (MD_MAJOR, 2)
+#define STOP_MD                _IO (MD_MAJOR, 3)
 
 int Manage_ro(char *devname, int fd, int readonly)
 {
+       /* switch to readonly or rw
+        *
+        * requires >= 0.90.0
+        * first check that array is runing
+        * use RESTART_ARRAY_RW or STOP_ARRAY_RO
+        *
+        */
+       mdu_array_info_t array;
+       
+       if (md_get_version(fd) < 9000) {
+               fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
+               return 1;
+       }
+       if (ioctl(fd, GET_ARRAY_INFO, &array)) {
+               fprintf(stderr, Name ": %s does not appear to be active.\n",
+                       devname);
+               return 1;
+       }
+       
+       if (readonly>0) {
+               if (ioctl(fd, STOP_ARRAY_RO, NULL)) {
+                       fprintf(stderr, Name ": failed to set readonly for %s: %s\n",
+                               devname, strerror(errno));
+                       return 1;
+               }
+       } else if (readonly < 0) {
+               if (ioctl(fd, RESTART_ARRAY_RW, NULL)) {
+                       fprintf(stderr, Name ": failed to set writable for %s: %s\n",
+                               devname, strerror(errno));
+                       return 1;
+               }
+       }
+       return 0;                       
 }
 
 int Manage_runstop(char *devname, int fd, int runstop)
 {
+       /* Run or stop the array. array must already be configured
+        * required >= 0.90.0
+        */
+       mdu_param_t param; /* unused */
+
+       if (runstop == -1 && md_get_version(fd) < 9000) {
+               if (ioctl(fd, STOP_MD, 0)) {
+                       fprintf(stderr, Name ": stopping device %s failed: %s\n",
+                               devname, strerror(errno));
+                       return 1;
+               }
+       }
+       
+       if (md_get_version(fd) < 9000) {
+               fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
+               return 1;
+       }
+       /*
+       if (ioctl(fd, GET_ARRAY_INFO, &array)) {
+               fprintf(stderr, Name ": %s does not appear to be active.\n",
+                       devname);
+               return 1;
+       }
+       */
+       if (runstop>0) {
+               if (ioctl(fd, RUN_ARRAY, &param)) {
+                       fprintf(stderr, Name ": failed to run array %s: %s\n",
+                               devname, strerror(errno));
+                       return 1;
+               }
+       } else if (runstop < 0){
+               if (ioctl(fd, STOP_ARRAY, NULL)) {
+                       fprintf(stderr, Name ": fail to stop array %s: %s\n",
+                               devname, strerror(errno));
+                       return 1;
+               }
+       }
+       return 0;
 }
 
 int Manage_subdevs(char *devname, int fd,
-                  int devcnt, char *devnames[], int devmodes[])
+                  mddev_dev_t devlist)
 {
+       /* do something to each dev.
+        * devmode can be
+        *  'a' - add the device
+        *         try HOT_ADD_DISK
+        *         If that fails EINVAL, try ADD_NEW_DISK
+        *  'r' - remove the device HOT_REMOVE_DISK
+        *  'f' - set the device faulty SET_DISK_FAULTY
+        */
+       mdu_array_info_t array;
+       mdu_disk_info_t disc;
+       mddev_dev_t dv;
+       struct stat stb;
+       int j;
+       int save_errno;
+       static char buf[4096];
+
+       if (ioctl(fd, GET_ARRAY_INFO, &array)) {
+               fprintf(stderr, Name ": cannot get array info for %s\n",
+                       devname);
+               return 1;
+       }
+       for (dv = devlist ; dv; dv=dv->next) {
+               if (stat(dv->devname, &stb)) {
+                       fprintf(stderr, Name ": cannot find %s: %s\n",
+                               dv->devname, strerror(errno));
+                       return 1;
+               }
+               if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+                       fprintf(stderr, Name ": %s is not a block device.\n",
+                               dv->devname);
+                       return 1;
+               }
+               switch(dv->disposition){
+               default:
+                       fprintf(stderr, Name ": internal error - devmode[%s]=%d\n",
+                               dv->devname, dv->disposition);
+                       return 1;
+               case 'a':
+                       /* add the device - hot or cold */
+                       if (ioctl(fd, HOT_ADD_DISK, (unsigned long)stb.st_rdev)==0) {
+                               fprintf(stderr, Name ": hot added %s\n",
+                                       dv->devname);
+                               continue;
+                       }
+                       save_errno = errno;
+                       if (read(fd, buf, sizeof(buf)) > 0) {
+                               /* array is active, so don't try to add.
+                                * i.e. something is wrong 
+                                */
+                               fprintf(stderr, Name ": hot add failed for %s: %s\n",
+                                       dv->devname, strerror(save_errno));
+                               return 1;
+                       }
+                       /* try ADD_NEW_DISK.
+                        * we might be creating, we might be assembling,
+                        * it is hard to tell.
+                        * set up number/raid_disk/state just
+                        * in case
+                        */
+                       for (j=0; j<array.nr_disks; j++) {
+                               if (ioctl(fd, GET_DISK_INFO, &disc))
+                                       break;
+                               if (disc.major==0 && disc.minor==0)
+                                       break;
+                               if (disc.state & 8) /* removed */
+                                       break;
+                       }
+                       disc.number =j;
+                       disc.raid_disk = j;
+                       disc.state = 0;
+                       disc.major = MAJOR(stb.st_rdev);
+                       disc.minor = MINOR(stb.st_rdev);
+                       if (ioctl(fd,ADD_NEW_DISK, &disc)) {
+                               fprintf(stderr, Name ": add new device failed for %s: %s\n",
+                                       dv->devname, strerror(errno));
+                               return 1;
+                       }
+                       fprintf(stderr, Name ": added %s\n", dv->devname);
+                       break;
+
+               case 'r':
+                       /* hot remove */
+                       /* FIXME check that it is a current member */
+                       if (ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev)) {
+                               fprintf(stderr, Name ": hot remove failed for %s: %s\n",
+                                       dv->devname, strerror(errno));
+                               return 1;
+                       }
+                       fprintf(stderr, Name ": hot removed %s\n", dv->devname);
+                       break;
+
+               case 'f': /* set faulty */
+                       /* FIXME check current member */
+                       if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) {
+                               fprintf(stderr, Name ": set device faulty failed for %s:  %s\n",
+                                       dv->devname, strerror(errno));
+                               return 1;
+                       }
+                       fprintf(stderr, Name ": set %s faulty in %s\n",
+                               dv->devname, devname);
+                       break;
+               }
+       }
+       return 0;
+       
 }