__u32 blocks_num;
};
+struct MBR {
+ __u8 pad[446];
+ struct MBR_part_record parts[4];
+ __u16 magic;
+} __attribute__((packed));
+
struct GPT_part_entry {
unsigned char type_guid[16];
unsigned char partition_guid[16];
- unsigned char starting_lba[8];
- unsigned char ending_lba[8];
+ __u64 starting_lba;
+ __u64 ending_lba;
unsigned char attr_bits[8];
unsigned char name[72];
-};
+} __attribute__((packed));
+
+struct GPT {
+ __u64 magic;
+ __u32 revision;
+ __u32 header_size;
+ __u32 crc;
+ __u32 pad1;
+ __u64 current_lba;
+ __u64 backup_lba;
+ __u64 first_lba;
+ __u64 last_lba;
+ __u8 guid[16];
+ __u64 part_start;
+ __u32 part_cnt;
+ __u32 part_size;
+ __u32 part_crc;
+ __u8 pad2[420];
+} __attribute__((packed));
+
+/* Force a compilation error if condition is true */
+#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
+
+/* Force a compilation error if condition is true, but also produce a
+ result (of value 0 and type size_t), so the expression can be used
+ e.g. in a structure initializer (or where-ever else comma expressions
+ aren't permitted). */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
/* MBR/GPT magic numbers */
#define MBR_SIGNATURE_MAGIC __cpu_to_le16(0xAA55)
#define GPT_SIGNATURE_MAGIC __cpu_to_le64(0x5452415020494645ULL)
-#define MBR_SIGNATURE_OFFSET 510
-#define MBR_PARTITION_TABLE_OFFSET 446
#define MBR_PARTITIONS 4
#define MBR_GPT_PARTITION_TYPE 0xEE
-#define GPT_ALL_PARTITIONS_OFFSET 80
-#define GPT_ENTRY_SIZE_OFFSET 84
/*
* Parse a 128 bit uuid in 4 integers
#endif
}
+int test_partition(int fd)
+{
+ /* Check if fd is a whole-disk or a partition.
+ * BLKPG will return EINVAL on a partition, and BLKPG_DEL_PARTITION
+ * will return ENXIO on an invalid partition number.
+ */
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+ a.op = BLKPG_DEL_PARTITION;
+ a.data = (void*)&p;
+ a.datalen = sizeof(p);
+ a.flags = 0;
+ memset(a.data, 0, a.datalen);
+ p.pno = 1<<30;
+ if (ioctl(fd, BLKPG, &a) == 0)
+ /* Very unlikely, but not a partition */
+ return 0;
+ if (errno == ENXIO)
+ /* not a partition */
+ return 0;
+
+ return 1;
+}
+
+
int enough(int level, int raid_disks, int layout, int clean,
char *avail, int avail_disks)
{
char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep)
{
- return __fname_from_uuid(info->uuid, st->ss->swapuuid, buf, sep);
+ // dirty hack to work around an issue with super1 superblocks...
+ // super1 superblocks need swapuuid set in order for assembly to
+ // work, but can't have it set if we want this printout to match
+ // all the other uuid printouts in super1.c, so we force swapuuid
+ // to 1 to make our printout match the rest of super1
+ return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 : st->ss->swapuuid, buf, sep);
}
#ifndef MDASSEMBLE
*/
static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
{
+ struct GPT gpt;
unsigned char buf[512];
unsigned char empty_gpt_entry[16]= {0};
struct GPT_part_entry *part;
*endofpart = 0;
+ BUILD_BUG_ON(sizeof(gpt) != 512);
/* read GPT header */
lseek(fd, 512, SEEK_SET);
- if (read(fd, buf, 512) != 512)
+ if (read(fd, &gpt, 512) != 512)
return 0;
/* get the number of partition entries and the entry size */
- all_partitions = __le32_to_cpu(buf[GPT_ALL_PARTITIONS_OFFSET]);
- entry_size = __le32_to_cpu(buf[GPT_ENTRY_SIZE_OFFSET]);
+ all_partitions = __le32_to_cpu(gpt.part_cnt);
+ entry_size = __le32_to_cpu(gpt.part_size);
/* Check GPT signature*/
- if (*((__u64*)buf) != GPT_SIGNATURE_MAGIC)
+ if (gpt.magic != GPT_SIGNATURE_MAGIC)
return -1;
/* sanity checks */
/* is this valid partition? */
if (memcmp(part->type_guid, empty_gpt_entry, 16) != 0) {
/* check the last lba for the current partition */
- curr_part_end = __le64_to_cpu(*(__u64*)part->ending_lba);
+ curr_part_end = __le64_to_cpu(part->ending_lba);
if (curr_part_end > *endofpart)
*endofpart = curr_part_end;
}
*/
static int get_last_partition_end(int fd, unsigned long long *endofpart)
{
- unsigned char boot_sect[512];
+ struct MBR boot_sect;
struct MBR_part_record *part;
unsigned long long curr_part_end;
int part_nr;
*endofpart = 0;
+ BUILD_BUG_ON(sizeof(boot_sect) != 512);
/* read MBR */
lseek(fd, 0, 0);
- if (read(fd, boot_sect, 512) != 512)
+ if (read(fd, &boot_sect, 512) != 512)
goto abort;
/* check MBP signature */
- if (*((__u16*)(boot_sect + MBR_SIGNATURE_OFFSET))
- == MBR_SIGNATURE_MAGIC) {
+ if (boot_sect.magic == MBR_SIGNATURE_MAGIC) {
retval = 1;
/* found the correct signature */
- part = (struct MBR_part_record*)
- (boot_sect + MBR_PARTITION_TABLE_OFFSET);
+ part = boot_sect.parts;
for (part_nr=0; part_nr < MBR_PARTITIONS; part_nr++) {
/* check for GPT type */
int rv;
#ifndef MDASSEMBLE
if (st->ss->external) {
- rv = sysfs_add_disk(sra, info,
- info->disk.state & (1<<MD_DISK_SYNC));
+ if (info->disk.state & (1<<MD_DISK_SYNC))
+ info->recovery_start = MaxSector;
+ else
+ info->recovery_start = 0;
+ rv = sysfs_add_disk(sra, info, 0);
if (! rv) {
struct mdinfo *sd2;
for (sd2 = sra->devs; sd2; sd2=sd2->next)
return rv;
}
+unsigned long long min_recovery_start(struct mdinfo *array)
+{
+ /* find the minimum recovery_start in an array for metadata
+ * formats that only record per-array recovery progress instead
+ * of per-device
+ */
+ unsigned long long recovery_start = MaxSector;
+ struct mdinfo *d;
+
+ for (d = array->devs; d; d = d->next)
+ recovery_start = min(recovery_start, d->recovery_start);
+
+ return recovery_start;
+}
+
char *devnum2devname(int num)
{
char name[100];
- if (num > 0)
+ if (num >= 0)
sprintf(name, "md%d", num);
else
sprintf(name, "md_d%d", -1-num);
return NoMdDev;
}
-int mdmon_running(int devnum)
+char *pid_dir = VAR_RUN;
+
+int mdmon_pid(int devnum)
{
char path[100];
char pid[10];
int fd;
int n;
- sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum));
- fd = open(path, O_RDONLY, 0);
+ sprintf(path, "%s/%s.pid", pid_dir, devnum2devname(devnum));
+ fd = open(path, O_RDONLY | O_NOATIME, 0);
if (fd < 0)
- return 0;
+ return -1;
n = read(fd, pid, 9);
close(fd);
if (n <= 0)
- return 0;
- if (kill(atoi(pid), 0) == 0)
- return 1;
- return 0;
+ return -1;
+ return atoi(pid);
}
-int signal_mdmon(int devnum)
+int mdmon_running(int devnum)
{
- char path[100];
- char pid[10];
- int fd;
- int n;
- sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum));
- fd = open(path, O_RDONLY, 0);
-
- if (fd < 0)
- return 0;
- n = read(fd, pid, 9);
- close(fd);
- if (n <= 0)
+ int pid = mdmon_pid(devnum);
+ if (pid <= 0)
return 0;
- if (kill(atoi(pid), SIGUSR1) == 0)
+ if (kill(pid, 0) == 0)
return 1;
return 0;
}