X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Finstaller%2Fhw.c;h=e453e23cbe14debf38ff89e312cf67e45aa839a2;hb=d6f003e1e969a353de52bdf1c466e6774cd78250;hp=0025e7d7562680f0f3e5dfbda69640c0b85c180c;hpb=e9cf574d50b5cce21ee9e03f0ba24dbfeed031a7;p=ipfire-2.x.git diff --git a/src/installer/hw.c b/src/installer/hw.c index 0025e7d756..e453e23cbe 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -48,12 +49,12 @@ const char* other_filesystems[] = { NULL }; -static int system_chroot(const char* path, const char* cmd) { +static int system_chroot(const char* output, const char* path, const char* cmd) { char chroot_cmd[STRING_SIZE]; snprintf(chroot_cmd, sizeof(chroot_cmd), "/usr/sbin/chroot %s %s", path, cmd); - return mysystem(chroot_cmd); + return mysystem(output, chroot_cmd); } struct hw* hw_init() { @@ -165,7 +166,7 @@ static unsigned long long hw_block_device_get_size(const char* dev) { return size; } -struct hw_disk** hw_find_disks(struct hw* hw) { +struct hw_disk** hw_find_disks(struct hw* hw, const char* sourcedrive) { struct hw_disk** ret = hw_create_disks(); struct hw_disk** disks = ret; @@ -192,15 +193,15 @@ struct hw_disk** hw_find_disks(struct hw* hw) { continue; } - // DEVTYPE must be disk (otherwise we will see all sorts of partitions here) - const char* devtype = udev_device_get_property_value(dev, "DEVTYPE"); - if (devtype && (strcmp(devtype, "disk") != 0)) { + // Skip sourcedrive if we need to + if (sourcedrive && (strcmp(dev_path, sourcedrive) == 0)) { udev_device_unref(dev); continue; } - // Skip all source mediums - if (hw_test_source_medium(dev_path) == 0) { + // DEVTYPE must be disk (otherwise we will see all sorts of partitions here) + const char* devtype = udev_device_get_property_value(dev, "DEVTYPE"); + if (devtype && (strcmp(devtype, "disk") != 0)) { udev_device_unref(dev); continue; } @@ -219,6 +220,7 @@ struct hw_disk** hw_find_disks(struct hw* hw) { disk->ref = 1; strncpy(disk->path, dev_path, sizeof(disk->path)); + const char* p = disk->path + 5; disk->size = size; @@ -252,15 +254,15 @@ struct hw_disk** hw_find_disks(struct hw* hw) { if (*disk->vendor && *disk->model) { snprintf(disk->description, sizeof(disk->description), - "%s - %s - %s", size_str, disk->vendor, disk->model); + "%s - %s - %s - %s", size_str, p, disk->vendor, disk->model); } else if (*disk->vendor || *disk->model) { snprintf(disk->description, sizeof(disk->description), - "%s - %s", size_str, (*disk->vendor) ? disk->vendor : disk->model); + "%s - %s - %s", size_str, p, (*disk->vendor) ? disk->vendor : disk->model); } else { snprintf(disk->description, sizeof(disk->description), - "%s - N/A", size_str); + "%s - %s", size_str, p); } *disks++ = disk; @@ -307,7 +309,7 @@ struct hw_disk** hw_select_disks(struct hw_disk** disks, int* selection) { unsigned int num_disks = hw_count_disks(disks); for (unsigned int i = 0; i < num_disks; i++) { - if (selection && selection[i]) { + if (!selection || selection[i]) { struct hw_disk *selected_disk = disks[i]; selected_disk->ref++; @@ -356,11 +358,26 @@ static unsigned long long hw_boot_size(struct hw_destination* dest) { return MB2BYTES(64); } +static int hw_device_has_p_suffix(const struct hw_destination* dest) { + // All RAID devices have the p suffix. + if (dest->is_raid) + return 1; + + // Devices with a number at the end have the p suffix, too. + // e.g. mmcblk0, cciss0 + unsigned int last_char = strlen(dest->path) - 1; + if ((dest->path[last_char] >= '0') && (dest->path[last_char] <= '9')) + return 1; + + return 0; +} + static int hw_calculate_partition_table(struct hw_destination* dest) { char path[DEV_SIZE]; int part_idx = 1; - snprintf(path, sizeof(path), "%s%s", dest->path, (dest->is_raid) ? "p" : ""); + snprintf(path, sizeof(path), "%s%s", dest->path, + hw_device_has_p_suffix(dest) ? "p" : ""); dest->part_boot_idx = 0; // Determine the size of the target block device @@ -486,23 +503,13 @@ struct hw_destination* hw_make_destination(int part_type, struct hw_disk** disks } unsigned long long hw_memory() { - FILE* handle = NULL; - char line[STRING_SIZE]; + struct sysinfo si; - unsigned long long memory = 0; - - /* Calculate amount of memory in machine */ - if ((handle = fopen("/proc/meminfo", "r"))) { - while (fgets(line, sizeof(line), handle)) { - if (!sscanf (line, "MemTotal: %llu kB", &memory)) { - memory = 0; - } - } - - fclose(handle); - } + int r = sysinfo(&si); + if (r < 0) + return 0; - return memory * 1024; + return si.totalram; } static int hw_zero_out_device(const char* path, int bytes) { @@ -526,7 +533,17 @@ static int hw_zero_out_device(const char* path, int bytes) { return bytes_written; } -int hw_create_partitions(struct hw_destination* dest) { +static int try_open(const char* path) { + FILE* f = fopen(path, "r"); + if (f) { + fclose(f); + return 0; + } + + return -1; +} + +int hw_create_partitions(struct hw_destination* dest, const char* output) { // Before we write a new partition table to the disk, we will erase // the first couple of megabytes at the beginning of the device to // get rid of all left other things like bootloaders and partition tables. @@ -597,7 +614,7 @@ int hw_create_partitions(struct hw_destination* dest) { asprintf(&cmd, "%s disk_set pmbr_boot on", cmd); } - r = mysystem(cmd); + r = mysystem(output, cmd); // Wait until the system re-read the partition table if (r == 0) { @@ -606,19 +623,19 @@ int hw_create_partitions(struct hw_destination* dest) { while (counter-- > 0) { sleep(1); - if (*dest->part_bootldr && (access(dest->part_bootldr, R_OK) != 0)) + if (*dest->part_bootldr && (try_open(dest->part_bootldr) != 0)) continue; - if (*dest->part_boot && (access(dest->part_boot, R_OK) != 0)) + if (*dest->part_boot && (try_open(dest->part_boot) != 0)) continue; - if (*dest->part_swap && (access(dest->part_swap, R_OK) != 0)) + if (*dest->part_swap && (try_open(dest->part_swap) != 0)) continue; - if (*dest->part_root && (access(dest->part_root, R_OK) != 0)) + if (*dest->part_root && (try_open(dest->part_root) != 0)) continue; - if (*dest->part_data && (access(dest->part_data, R_OK) != 0)) + if (*dest->part_data && (try_open(dest->part_data) != 0)) continue; // All partitions do exist, exiting the loop. @@ -632,7 +649,7 @@ int hw_create_partitions(struct hw_destination* dest) { return r; } -static int hw_format_filesystem(const char* path, int fs) { +static int hw_format_filesystem(const char* path, int fs, const char* output) { char cmd[STRING_SIZE] = "\0"; // Swap @@ -657,36 +674,36 @@ static int hw_format_filesystem(const char* path, int fs) { assert(*cmd); - int r = mysystem(cmd); + int r = mysystem(output, cmd); return r; } -int hw_create_filesystems(struct hw_destination* dest) { +int hw_create_filesystems(struct hw_destination* dest, const char* output) { int r; // boot if (*dest->part_boot) { - r = hw_format_filesystem(dest->part_boot, dest->filesystem); + r = hw_format_filesystem(dest->part_boot, dest->filesystem, output); if (r) return r; } // swap if (*dest->part_swap) { - r = hw_format_filesystem(dest->part_swap, HW_FS_SWAP); + r = hw_format_filesystem(dest->part_swap, HW_FS_SWAP, output); if (r) return r; } // root - r = hw_format_filesystem(dest->part_root, dest->filesystem); + r = hw_format_filesystem(dest->part_root, dest->filesystem, output); if (r) return r; // data if (*dest->part_data) { - r = hw_format_filesystem(dest->part_data, dest->filesystem); + r = hw_format_filesystem(dest->part_data, dest->filesystem, output); if (r) return r; } @@ -779,6 +796,9 @@ int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { } int hw_umount_filesystems(struct hw_destination* dest, const char* prefix) { + // Write all buffers to disk before umounting + hw_sync(); + // boot if (*dest->part_boot) { hw_umount(dest->part_boot); @@ -809,12 +829,36 @@ int hw_umount_filesystems(struct hw_destination* dest, const char* prefix) { return 0; } -int hw_setup_raid(struct hw_destination* dest) { +int hw_destroy_raid_superblocks(const struct hw_destination* dest, const char* output) { + char cmd[STRING_SIZE]; + + hw_stop_all_raid_arrays(output); + hw_stop_all_raid_arrays(output); + + if (dest->disk1) { + snprintf(cmd, sizeof(cmd), "/sbin/mdadm --zero-superblock %s", dest->disk1->path); + mysystem(output, cmd); + } + + if (dest->disk2) { + snprintf(cmd, sizeof(cmd), "/sbin/mdadm --zero-superblock %s", dest->disk2->path); + mysystem(output, cmd); + } + + return 0; +} + +int hw_setup_raid(struct hw_destination* dest, const char* output) { char* cmd = NULL; int r; assert(dest->is_raid); + // Stop all RAID arrays that might be around (again). + // It seems that there is some sort of race-condition with udev re-enabling + // the raid arrays and therefore locking the disks. + r = hw_destroy_raid_superblocks(dest, output); + asprintf(&cmd, "echo \"y\" | /sbin/mdadm --create --verbose --metadata=%s --auto=mdp %s", RAID_METADATA, dest->path); @@ -845,7 +889,7 @@ int hw_setup_raid(struct hw_destination* dest) { return r; } - r = mysystem(cmd); + r = mysystem(output, cmd); free(cmd); // Wait a moment until the device has been properly brought up @@ -857,28 +901,25 @@ int hw_setup_raid(struct hw_destination* dest) { // If the raid device has not yet been properly brought up, // opening it will fail with the message: Device or resource busy // Hence we will wait a bit until it becomes usable. - FILE* f = fopen(dest->path, "r"); - if (f) { - fclose(f); + if (try_open(dest->path) == 0) break; - } } } return r; } -int hw_stop_all_raid_arrays() { - return mysystem("/sbin/mdadm --stop --scan"); +int hw_stop_all_raid_arrays(const char* output) { + return mysystem(output, "/sbin/mdadm --stop --scan --verbose"); } -int hw_install_bootloader(struct hw_destination* dest) { +int hw_install_bootloader(struct hw_destination* dest, const char* output) { char cmd[STRING_SIZE]; int r; // Generate configuration file snprintf(cmd, sizeof(cmd), "/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg"); - r = system_chroot(DESTINATION_MOUNT_PATH, cmd); + r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd); if (r) return r; @@ -887,15 +928,15 @@ int hw_install_bootloader(struct hw_destination* dest) { if (dest->is_raid) { snprintf(cmd, sizeof(cmd), "%s %s", cmd_grub, dest->disk1->path); - r = system_chroot(DESTINATION_MOUNT_PATH, cmd); + r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd); if (r) return r; snprintf(cmd, sizeof(cmd), "%s %s", cmd_grub, dest->disk2->path); - r = system_chroot(DESTINATION_MOUNT_PATH, cmd); + r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd); } else { snprintf(cmd, sizeof(cmd), "%s %s", cmd_grub, dest->path); - r = system_chroot(DESTINATION_MOUNT_PATH, cmd); + r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd); } return r;