From: Matthew Dillon Date: Mon, 14 Dec 2015 03:18:47 +0000 (-0800) Subject: installer - use a more modern mount setup for UFS and HAMMER. X-Git-Tag: v4.6.0rc~1186 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/f9602a12d5f0345feed0941d0b9e3b4e1816a411 installer - use a more modern mount setup for UFS and HAMMER. * Rewrite a large chunk of the disklabeling and mount point code. UFS now gains a separate /boot partition, avoiding issues with the boot loader if the user desires to install a large UFS root on a drive. * Normalize the mount mechanics for both UFS and HAMMER. Instead of using PFSs on HAMMER, we create two large partitions by default: One is the root partition, the other is /build. The /build partition holds major elements of the system which would normally not have to be backed up: /var/tmp (from /build/var.tmp) /var/cache (from /build/var.cache) /var/crash (from /build/var.crash) /var/spool (from /build/var.spool) /var/log (from /build/var.log) /usr/obj (from /build/usr.obj) The root partition holds all remaining major directories, including the base /var. There are several reasons for this. Generally speaking, stuff in /home, /usr and most of the stuff in /var is critical to system operation and user happiness, and it makes little sense to separate it out from the root mount. We pick-out the less critical directories and place them on /build, using NULL mounts to mount them in their expected locations. * Users can easily make adjustments post-install without having to mess around with PFSs, and can make simple adjustments pre-install. * Drives smaller than around 40GB will not create a separate /build partition by default, but will still create a /build directory in the root partition and generate the same nullfs mounts. This makes it easier for the user to adjust to a larger configuration later on if desired. * This also improves crash recovery mechanics, increasing the chance that the root partition will be able to mount with minimal recovery work. * We now use a tmpfs filesystem for /tmp by default. /var/tmp is mounted from storage. Again, the user can change this easily post-install. * Calculate better values for swap, root, and /build, based on the size of the slice being installed to. The /build directory will cap-out at around 20GB leaving. Swap will be made smaller if the root partition seems to small, and so forth. Some swap is always configured. Swap is a very useful thing to have, even if you have tons of memory, because there will always be a certain number of always-idle pages from idle services laying around. * Remove /dev from sources.conf, it is no longer appropriate to try to cpdup /dev. Fixes a cpdup error. * UFS root can now be encrypted (it couldn't before), because the UFS install now splits out a separate /boot partition. * Tested w/non-crypto UFS and HAMMER install, crypto UFS and HAMMER install, and with small and large drives. --- diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index 3a0364a04a..c2df8b0c94 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -13,6 +13,8 @@ kernel .. .. + build + .. compat ndis .. diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist index 1475133083..e2e15d6577 100644 --- a/etc/mtree/BSD.var.dist +++ b/etc/mtree/BSD.var.dist @@ -18,6 +18,8 @@ /set mode=0750 backups .. + cache mode=0755 + .. crash .. cron diff --git a/share/installer/sources.conf b/share/installer/sources.conf index 515b86861e..0b09b5077a 100644 --- a/share/installer/sources.conf +++ b/share/installer/sources.conf @@ -2,7 +2,6 @@ /bin /boot /compat -/dev /etc /lib /libexec diff --git a/usr.sbin/installer/dfuibe_installer/flow.h b/usr.sbin/installer/dfuibe_installer/flow.h index a15887bcf5..ee93ad48d6 100644 --- a/usr.sbin/installer/dfuibe_installer/flow.h +++ b/usr.sbin/installer/dfuibe_installer/flow.h @@ -42,16 +42,11 @@ #define DISK_MIN 4096 #define HAMMER_WARN 51200 #define HAMMER_MIN 10240 -#if defined(__x86_64__) -#define SWAP_MAX 524288 -#endif -#define MTPT_ROOT 0 -#define MTPT_SWAP 1 -#define MTPT_VAR 2 -#define MTPT_TMP 3 -#define MTPT_USR 4 -#define MTPT_HOME 5 +#define SWAP_MIN 256 /* suggested minimum */ +#define SWAP_MAX 524288 +#define BUILD_MIN 10240 /* suggested */ +#define BUILD_MAX 20480 /* suggested */ struct i_fn_args; int use_hammer; diff --git a/usr.sbin/installer/dfuibe_installer/fn.h b/usr.sbin/installer/dfuibe_installer/fn.h index 7edfb9dbdc..6bf3e582d0 100644 --- a/usr.sbin/installer/dfuibe_installer/fn.h +++ b/usr.sbin/installer/dfuibe_installer/fn.h @@ -98,6 +98,7 @@ int format_slice(struct i_fn_args *); void fn_create_subpartitions_ufs(struct i_fn_args *); void fn_create_subpartitions_hammer(struct i_fn_args *); void fn_install_os(struct i_fn_args *); +const char *fn_mapper_name(const char *mountpt, int withdev); /* Global variables */ diff --git a/usr.sbin/installer/dfuibe_installer/fn_configure.c b/usr.sbin/installer/dfuibe_installer/fn_configure.c index 616de96fdb..84189e5aae 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_configure.c +++ b/usr.sbin/installer/dfuibe_installer/fn_configure.c @@ -1,5 +1,5 @@ /* - * Copyright (c)2004 The DragonFly Project. All rights reserved. + * Copyright (c)2004,2015 The DragonFly Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -79,7 +79,6 @@ #include "pathnames.h" static const char *yes_to_y(const char *); -static char *convert_tmpfs_options(char *); /** CONFIGURE FUNCTIONS **/ @@ -1132,12 +1131,18 @@ fn_assign_ip(struct i_fn_args *a) if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { new_ds = dfui_response_dataset_get_first(r); - interface_ip = dfui_dataset_get_value(new_ds, "interface_ip"); - interface_netmask = dfui_dataset_get_value(new_ds, "interface_netmask"); - defaultrouter = dfui_dataset_get_value(new_ds, "defaultrouter"); - dns_resolver = dfui_dataset_get_value(new_ds, "dns_resolver"); - hostname = dfui_dataset_get_value(new_ds, "hostname"); - domain = dfui_dataset_get_value(new_ds, "domain"); + interface_ip = dfui_dataset_get_value( + new_ds, "interface_ip"); + interface_netmask = dfui_dataset_get_value( + new_ds, "interface_netmask"); + defaultrouter = dfui_dataset_get_value( + new_ds, "defaultrouter"); + dns_resolver = dfui_dataset_get_value( + new_ds, "dns_resolver"); + hostname = dfui_dataset_get_value( + new_ds, "hostname"); + domain = dfui_dataset_get_value( + new_ds, "domain"); asprintf(&string, "ifconfig_%s", interface); asprintf(&string1, "inet %s netmask %s", @@ -1231,7 +1236,8 @@ fn_select_services(struct i_fn_args *a) f = dfui_form_create( "select_services", _("Select Services"), - _("Please select which services you would like started at boot time."), + _("Please select which services you would like " + "started at boot time."), "", "f", "syslogd", "syslogd", @@ -1287,41 +1293,11 @@ fn_select_services(struct i_fn_args *a) /*** NON-fn_ FUNCTIONS ***/ -/* - * Caller is responsible for deallocation. - */ -static char * -convert_tmpfs_options(char *line) -{ - char *result, *word; - int i; - - result = malloc(256); - result[0] = '\0'; - - for (; (word = strsep(&line, ",")) != NULL; ) { - if (word[0] == '-') { - /* - * Don't bother trying to honour the -C - * option, since we can't copy files from - * the right place anyway. - */ - if (strcmp(word, "-C") != 0) { - for (i = 0; word[i] != '\0'; i++) { - if (word[i] == '=') - word[i] = ' '; - } - strlcat(result, word, 256); - strlcat(result, " ", 256); - } - } - } - - return(result); -} - /* * Uses ss->selected_{disk,slice} as the target system. + * + * XXX We now assume that the root mount has enough of the topology + * to handle any configuration actions. */ int mount_target_system(struct i_fn_args *a) @@ -1330,11 +1306,10 @@ mount_target_system(struct i_fn_args *a) struct commands *cmds; struct command *cmd; struct subpartition *a_subpart; - char name[256], device[256], mtpt[256], fstype[256], options[256]; + struct subpartition *d_subpart; + char name[256], device[256]; char *filename, line[256]; - const char *try_mtpt[5] = {"/var", "/tmp", "/usr", "/home", NULL}; - char *word, *cvtoptions; - int i; + char *word; /* * Mount subpartitions from this installation if they are @@ -1358,17 +1333,23 @@ mount_target_system(struct i_fn_args *a) * Create a temporary dummy subpartition - that we * assume exists */ - a_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s), - "/dummy", 0, 0, 0, 0, 0, 0); + "/dummy", 0, 0, 0, 0, 0, 0); + subpartition_new_ufs(storage_get_selected_slice(a->s), + "swap", 0, 0, 0, 0, 0, 0); + d_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s), + "/dummy", 0, 0, 0, 0, 0, 0); /* * Mount the target's / and read its /etc/fstab. + * + * XXX NEEDS TO BE REWRITTEN XXX */ +#if 0 if (use_hammer == 0) { command_add(cmds, "%s%s /dev/%s %s%s", a->os_root, cmd_name(a, "MOUNT"), - subpartition_get_device_name(a_subpart), + subpartition_get_device_name(d_subpart), a->os_root, a->cfg_root); cmd = command_add(cmds, "%s%s -f %st2;" @@ -1377,7 +1358,9 @@ mount_target_system(struct i_fn_args *a) a->os_root, cmd_name(a, "GREP"), a->os_root, a->cfg_root, a->tmp); command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE); - } else { + } else +#endif + { command_add(cmds, "%s%s /dev/%s %sboot", a->os_root, cmd_name(a, "MOUNT"), subpartition_get_device_name(a_subpart), @@ -1397,8 +1380,13 @@ mount_target_system(struct i_fn_args *a) commands_free(cmds); cmds = commands_new(); - if (use_hammer) { + /* + * XXX NEEDS TO BE REWRITTEN XXX + */ + { struct stat sb = { .st_size = 0 }; + const char *fsname = use_hammer ? "hammer" : "ufs"; + stat("/tmp/t2", &sb); if (sb.st_size > 0) { command_add(cmds, "%s%s %sboot", @@ -1407,26 +1395,35 @@ mount_target_system(struct i_fn_args *a) fn_get_passphrase(a); command_add(cmds, "%s%s -d /tmp/t1 luksOpen /dev/`%s%s \"^vfs\\.root\\.realroot=\" %st2 |" - "%s%s -Fhammer: '{print $2;}' |" - "%s%s -F: '{print $1;}'` root", + "%s%s -F%s: '{print $2;}' |" + "%s%s -F: '{print $1;}'` %s", a->os_root, cmd_name(a, "CRYPTSETUP"), a->os_root, cmd_name(a, "GREP"), a->tmp, a->os_root, cmd_name(a, "AWK"), - a->os_root, cmd_name(a, "AWK")); + fsname, + a->os_root, cmd_name(a, "AWK"), + fn_mapper_name(subpartition_get_device_name(d_subpart), -1) + ); command_add(cmds, - "%s%s /dev/mapper/root %s%s", - a->os_root, cmd_name(a, "MOUNT_HAMMER"), + "%s%s %s %s%s", + a->os_root, + (use_hammer ? cmd_name(a, "MOUNT_HAMMER") : + cmd_name(a, "MOUNT")), + fn_mapper_name(subpartition_get_device_name(d_subpart), 1), a->os_root, a->cfg_root); } else { command_add(cmds, "%s%s /dev/`%s%s \"^vfs\\.root\\.mountfrom\" %sboot/loader.conf |" - "%s%s -Fhammer: '{print $2;}' |" + "%s%s -F%s: '{print $2;}' |" "%s%s 's/\"//'` %s%s", - a->os_root, cmd_name(a, "MOUNT_HAMMER"), + a->os_root, + (use_hammer ? cmd_name(a, "MOUNT_HAMMER") : + cmd_name(a, "MOUNT")), a->os_root, cmd_name(a, "GREP"), a->os_root, a->os_root, cmd_name(a, "AWK"), + fsname, a->os_root, cmd_name(a, "SED"), a->os_root, a->cfg_root); command_add(cmds, "%s%s %sboot", @@ -1448,13 +1445,16 @@ mount_target_system(struct i_fn_args *a) /* * See if an /etc/crypttab exists. + * + * Scan and open the related mappings (currently not used since + * we removed the additional mounts from the fstab scan, but we + * might put those back in at a future date so leave this in for + * now). */ asprintf(&filename, "%s%s/etc/crypttab", a->os_root, a->cfg_root); crypttab = fopen(filename, "r"); free(filename); if (crypttab != NULL) { - if (!use_hammer) - fn_get_passphrase(a); while (fgets(line, 256, crypttab) != NULL) { /* * Parse the crypttab line. @@ -1464,8 +1464,14 @@ mount_target_system(struct i_fn_args *a) if ((word = strtok(line, " \t")) == NULL) continue; strlcpy(name, word, 256); + + /* don't mount encrypted swap */ if (strcmp(name, "swap") == 0) continue; + /* encrypted root already mounted */ + if (strcmp(name, fn_mapper_name(subpartition_get_device_name(d_subpart), -1)) == 0) + continue; + if ((word = strtok(NULL, " \t")) == NULL) continue; strlcpy(device, word, 256); @@ -1485,6 +1491,10 @@ mount_target_system(struct i_fn_args *a) } commands_free(cmds); + /* + * (current we do not mount the other partitions, everything needed + * for system configuration should be on the already-mounted root). + */ asprintf(&filename, "%s%s/etc/fstab", a->os_root, a->cfg_root); fstab = fopen(filename, "r"); free(filename); @@ -1500,86 +1510,7 @@ mount_target_system(struct i_fn_args *a) commands_free(cmds); return(0); } - - cmds = commands_new(); - - while (fgets(line, 256, fstab) != NULL) { - /* - * Parse the fstab line. - */ - if (first_non_space_char_is(line, '#')) - continue; - if ((word = strtok(line, " \t")) == NULL) - continue; - strlcpy(device, word, 256); - if ((word = strtok(NULL, " \t")) == NULL) - continue; - strlcpy(mtpt, word, 256); - if ((word = strtok(NULL, " \t")) == NULL) - continue; - strlcpy(fstype, word, 256); - if ((word = strtok(NULL, " \t")) == NULL) - continue; - strlcpy(options, word, 256); - - /* - * Now, if the mountpoint has /usr, /var, /tmp, or /home - * as a prefix, mount it under a->cfg_root. - */ - for (i = 0; try_mtpt[i] != NULL; i++) { - if (strstr(mtpt, try_mtpt[i]) == mtpt) { - /* - * Don't mount it if it's optional. - */ - if (strstr(options, "noauto") != NULL) - continue; - - /* - * Don't mount it if device doesn't start - * with /dev/ or /pfs and it isn't 'tmpfs'. - */ - if (strstr(device, "/dev/") != NULL && - strstr(device, "/pfs/") != NULL && - strcmp(device, "tmpfs") != 0) - continue; - - /* - * If the device is 'tmpfs', mount_tmpfs it instead. - */ - if (strcmp(device, "tmpfs") == 0) { - cvtoptions = convert_tmpfs_options(options); - command_add(cmds, - "%s%s %s tmpfs %s%s%s", - a->os_root, cmd_name(a, "MOUNT_TMPFS"), - cvtoptions, a->os_root, a->cfg_root, mtpt); - free(cvtoptions); - } else { - if (use_hammer == 0) { - command_add(cmds, - "%s%s -o %s %s%s %s%s%s", - a->os_root, cmd_name(a, "MOUNT"), - options, - a->os_root, device, a->os_root, - a->cfg_root, mtpt); - } else { - command_add(cmds, - "%s%s -o %s %s%s%s %s%s%s", - a->os_root, cmd_name(a, "MOUNT_NULL"), - options, - a->os_root, a->cfg_root, device, - a->os_root, a->cfg_root, mtpt); - } - } - } - } - } fclose(fstab); - if (!commands_execute(a, cmds)) { - commands_free(cmds); - return(0); - } - commands_free(cmds); - - return(1); + return 1; } diff --git a/usr.sbin/installer/dfuibe_installer/fn_install.c b/usr.sbin/installer/dfuibe_installer/fn_install.c index 9ec1d75506..4797dc7800 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_install.c +++ b/usr.sbin/installer/dfuibe_installer/fn_install.c @@ -1,5 +1,5 @@ /* - * Copyright (c)2004 The DragonFly Project. All rights reserved. + * Copyright (c)2004,2015 The DragonFly Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -66,63 +66,105 @@ #include "pathnames.h" #include "fn.h" -static const char *pfs_mountpt[] = {"/var", "/tmp", "/home", - "/usr/obj", "/var/crash", "/var/tmp", NULL}; - -static const int pfs_nohistory[] = {0, 1, 0, 1, 1, 1}; +/* + * NOTE: Even though /var/run doesn't need to be backedup, nearly all + * services depend on it so it is best to leave it on the root. + */ +static const char *nullfs_mountpt[] = { + "/usr/obj", "/var/crash", "/var/cache", + "/var/spool", "/var/log", "/var/tmp", + NULL }; +static const char *nullfs_mountname[] = { + "/build/usr.obj", "/build/var.crash", "/build/var.cache", + "/build/var.spool", "/build/var.log", "/build/var.tmp", + NULL }; static void -handle_pfs(struct i_fn_args *a, struct commands *cmds) +handle_altfs(struct i_fn_args *a, struct commands *cmds) { - int j; + int i; /* - * Create PFS root directory. + * Create directories for null mounts if not specified as a partition. + * (null mounts are from /build) */ - command_add(cmds, "%s%s -p %smnt/pfs", - a->os_root, cmd_name(a, "MKDIR"), - a->os_root); + for (i = 0; nullfs_mountpt[i]; ++i) { + if (subpartition_find(storage_get_selected_slice(a->s), "%s", nullfs_mountpt[i]) != NULL) + continue; - for (j = 0; pfs_mountpt[j] != NULL; j++) { /* - * We have a PFS for a subdirectory, e.g. /var/crash, so we - * need to create /pfs/var.crash + * Create directory infrastructure for null-mount if + * necessary, then issue the null mount(s). */ - if (rindex(pfs_mountpt[j]+1, '/') != NULL) { - command_add(cmds, "%s%s pfs-master %smnt/pfs%s.%s", - a->os_root, cmd_name(a, "HAMMER"), - a->os_root, dirname(pfs_mountpt[j]), - basename(pfs_mountpt[j])); - command_add(cmds, "%s%s -p %smnt%s", + command_add(cmds, "%s%s -p %smnt%s", a->os_root, cmd_name(a, "MKDIR"), - a->os_root, pfs_mountpt[j]); - command_add(cmds, "%s%s %smnt/pfs%s.%s %smnt%s", - a->os_root, cmd_name(a, "MOUNT_NULL"), - a->os_root, dirname(pfs_mountpt[j]), - basename(pfs_mountpt[j]), - a->os_root, pfs_mountpt[j]); - } else { - command_add(cmds, "%s%s pfs-master %smnt/pfs%s", - a->os_root, cmd_name(a, "HAMMER"), - a->os_root, pfs_mountpt[j]); - command_add(cmds, "%s%s -p %smnt%s", + a->os_root, nullfs_mountname[i]); + command_add(cmds, "%s%s -p %smnt%s", a->os_root, cmd_name(a, "MKDIR"), - a->os_root, pfs_mountpt[j]); - command_add(cmds, "%s%s %smnt/pfs%s %smnt%s", - a->os_root, cmd_name(a, "MOUNT_NULL"), - a->os_root, pfs_mountpt[j], - a->os_root, pfs_mountpt[j]); - } + a->os_root, nullfs_mountpt[i]); + command_add(cmds, "%s%s %smnt%s %smnt%s", + a->os_root, cmd_name(a, "MOUNT_NULL"), + a->os_root, nullfs_mountname[i], + a->os_root, nullfs_mountpt[i]); + } + + /* + * Create directory for /tmp and tmpfs mount if not specified as + * a partition. + */ + if (subpartition_find(storage_get_selected_slice(a->s), "%s", "/tmp") == NULL) { + command_add(cmds, "%s%s -p %smnt/tmp", + a->os_root, cmd_name(a, "MKDIR"), a->os_root); + command_add(cmds, "%s%s 1777 %smnt/tmp", + a->os_root, cmd_name(a, "CHMOD"), a->os_root); + command_add(cmds, "%s%s dummy %smnt/tmp", + a->os_root, cmd_name(a, "MOUNT_TMPFS"), a->os_root); } } +static void +unmount_altfs(struct i_fn_args *a __unused, struct commands *cmds __unused) +{ + return; +#if 0 + int i; + + /* + * Unmount null mounts + */ + i = sizeof(nullfs_mountpt) / sizeof(nullfs_mountpt[0]) - 1; + while (i >= 0) { + if (subpartition_find(storage_get_selected_slice(a->s), "%s", nullfs_mountpt[i]) != NULL) + continue; + + /* + * Create directory infrastructure for null-mount if + * necessary, then issue the null mount(s). + */ + command_add(cmds, "%s%s %smnt%s", + a->os_root, cmd_name(a, "UMOUNT"), + a->os_root, nullfs_mountpt[i]); + --i; + } + + /* + * Unmount tmpfs mounts + */ + if (subpartition_find(storage_get_selected_slice(a->s), "%s", "/tmp") == NULL) { + command_add(cmds, "%s%s -p %smnt%s", + a->os_root, cmd_name(a, "UMOUNT"), + a->os_root, "/tmp"); + } +#endif +} + /* * fn_install_os: actually put DragonFly on a disk. */ void fn_install_os(struct i_fn_args *a) { - struct subpartition *sp; + struct subpartition *sp, *spnext; struct commands *cmds; struct command *cmd; int i, seen_it, prefix, j, needcrypt; @@ -132,6 +174,7 @@ fn_install_os(struct i_fn_args *a) char file_path[256]; char *string; int lines = 0; + int nfsidx; /* * Read SOURCES_CONF_FILE and populate our copy sources. @@ -171,6 +214,7 @@ fn_install_os(struct i_fn_args *a) /* * Unmount anything already mounted on /mnt. */ + unmount_altfs(a, cmds); unmount_all_under(a, cmds, "%smnt", a->os_root); /* Check if crypto support is needed */ @@ -185,18 +229,25 @@ fn_install_os(struct i_fn_args *a) for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); sp != NULL; sp = subpartition_next(sp)) { - if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) { + if (strcmp(subpartition_get_mountpoint(sp), "/") == 0 || + strcmp(subpartition_get_mountpoint(sp), "/build") == 0) { + /* make sure mountpoint directory exists */ + command_add(cmds, "%s%s -p %smnt%s", + a->os_root, cmd_name(a, "MKDIR"), + a->os_root, + subpartition_get_mountpoint(sp)); if (use_hammer == 1) { command_add(cmds, "%s%s /dev/%s %smnt%s", a->os_root, cmd_name(a, "MOUNT_HAMMER"), - subpartition_is_encrypted(sp) ? - "mapper/root" : subpartition_get_device_name(sp), + (subpartition_is_encrypted(sp) ? + fn_mapper_name(subpartition_get_device_name(sp), 0) : subpartition_get_device_name(sp)), a->os_root, subpartition_get_mountpoint(sp)); } else { command_add(cmds, "%s%s /dev/%s %smnt%s", a->os_root, cmd_name(a, "MOUNT"), - subpartition_get_device_name(sp), + subpartition_is_encrypted(sp) ? + fn_mapper_name(subpartition_get_device_name(sp), 0) : subpartition_get_device_name(sp), a->os_root, subpartition_get_mountpoint(sp)); } @@ -225,53 +276,48 @@ fn_install_os(struct i_fn_args *a) continue; } - if (use_hammer == 0) { - /* / is already mounted */ - if (strcmp(subpartition_get_mountpoint(sp), "/") != 0) { - command_add(cmds, "%s%s -p %smnt%s", - a->os_root, cmd_name(a, "MKDIR"), - a->os_root, - subpartition_get_mountpoint(sp)); - /* Don't mount it if it's TMPFS-backed. */ - if (subpartition_is_tmpfsbacked(sp)) - continue; - if (subpartition_is_encrypted(sp)) { - command_add(cmds, "%s%s /dev/mapper/%s %smnt%s", - a->os_root, cmd_name(a, "MOUNT"), - subpartition_get_mountpoint(sp) + 1, - a->os_root, - subpartition_get_mountpoint(sp)); - } else { - command_add(cmds, "%s%s /dev/%s %smnt%s", - a->os_root, cmd_name(a, "MOUNT"), - subpartition_get_device_name(sp), - a->os_root, - subpartition_get_mountpoint(sp)); - } - } - } else if (strcmp(subpartition_get_mountpoint(sp), "/boot") == 0) { + /* + * mount everything except / and /build (which have already + * been mounted). This should also get /boot. + */ + if (strcmp(subpartition_get_mountpoint(sp), "/") != 0 && + strcmp(subpartition_get_mountpoint(sp), "/build") != 0) { + const char *mapper_name; + + mapper_name = fn_mapper_name(subpartition_get_device_name(sp), 0); + + /* make sure mountpoint directory exists */ command_add(cmds, "%s%s -p %smnt%s", a->os_root, cmd_name(a, "MKDIR"), a->os_root, subpartition_get_mountpoint(sp)); - command_add(cmds, "%s%s /dev/%s %smnt%s", - a->os_root, cmd_name(a, "MOUNT"), - subpartition_get_device_name(sp), - a->os_root, - subpartition_get_mountpoint(sp)); + /* Don't mount it if it's TMPFS-backed. */ + if (subpartition_is_tmpfsbacked(sp)) + continue; + if (subpartition_is_encrypted(sp)) { + command_add(cmds, "%s%s /dev/%s %smnt%s", + a->os_root, cmd_name(a, "MOUNT"), + mapper_name, + a->os_root, + subpartition_get_mountpoint(sp)); + } else { + command_add(cmds, "%s%s /dev/%s %smnt%s", + a->os_root, cmd_name(a, "MOUNT"), + subpartition_get_device_name(sp), + a->os_root, + subpartition_get_mountpoint(sp)); + } } } /* - * Take care of HAMMER PFS. + * Take care of tmpfs and null-mounts from /build */ - if (use_hammer == 1) - handle_pfs(a, cmds); + handle_altfs(a, cmds); /* * Actually copy files now. */ - for (i = 0; cp_src[i] != NULL && cp_src[i][0] != '\0'; i++) { char *src, *dest, *dn, *tmp_dest; @@ -312,11 +358,12 @@ fn_install_os(struct i_fn_args *a) else asprintf(&src, "%s", &dest[1]); - if (is_dir("%s%s", a->os_root, src) || is_file("%s%s", a->os_root, src)) { - /* - * Cpdup the chosen file or directory onto the HDD. - * if it exists on the source. - */ + /* + * Cpdup the chosen file or directory onto the HDD. + * if it exists on the source. + */ + if (is_dir("%s%s", a->os_root, src) || + is_file("%s%s", a->os_root, src)) { cmd = command_add(cmds, "%s%s %s%s %smnt%s", a->os_root, cmd_name(a, "CPDUP"), a->os_root, src, @@ -330,22 +377,45 @@ fn_install_os(struct i_fn_args *a) * we must copy anything that the user might've made a * seperate mount point for (e.g. /usr/libdata/lint.) */ - for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); - sp != NULL; sp = subpartition_next(sp)) { + nfsidx = 0; + sp = NULL; + spnext = slice_subpartition_first(storage_get_selected_slice(a->s)); + + for (;;) { + const char *mountpt; + + /* + * Iterate nullfs mounts and then partitions + */ + if (nullfs_mountpt[nfsidx]) { + mountpt = nullfs_mountpt[nfsidx]; + ++nfsidx; + } else { + sp = spnext; + if (sp == NULL) + break; + spnext = subpartition_next(sp); + mountpt = subpartition_get_mountpoint(sp); + } + /* * If the subpartition is a swap subpartition or an * TMPFS-backed mountpoint, don't try to copy anything * into it. */ - if (subpartition_is_swap(sp) || subpartition_is_tmpfsbacked(sp)) - continue; + if (sp) { + if (subpartition_is_swap(sp) || + subpartition_is_tmpfsbacked(sp)) { + continue; + } + } /* * If the mountpoint doesn't even exist on the installation * medium, don't try to copy anything from it! We assume * it's an empty subpartition for the user's needs. */ - if (!is_dir("%s%s", a->os_root, &subpartition_get_mountpoint(sp)[1])) + if (!is_dir("%s%s", a->os_root, mountpt + 1)) continue; /* @@ -358,13 +428,12 @@ fn_install_os(struct i_fn_args *a) seen_it = 0; prefix = 0; for (i = 0; cp_src[i] != NULL && cp_src[i][0] != '\0'; i++) { - if (strncmp(subpartition_get_mountpoint(sp), cp_src[i], - strlen(subpartition_get_mountpoint(sp))) == 0) { + if (strncmp(mountpt, cp_src[i], + strlen(mountpt)) == 0) { seen_it = 1; break; } - if (strncmp(cp_src[i], subpartition_get_mountpoint(sp), - strlen(cp_src[i])) == 0) { + if (strncmp(cp_src[i], mountpt, strlen(cp_src[i])) == 0) { prefix = 1; } } @@ -380,9 +449,9 @@ fn_install_os(struct i_fn_args *a) * that this part of the code is meant to handle. */ cmd = command_add(cmds, "%s%s %s%s %smnt%s", - a->os_root, cmd_name(a, "CPDUP"), - a->os_root, &subpartition_get_mountpoint(sp)[1], - a->os_root, subpartition_get_mountpoint(sp)); + a->os_root, cmd_name(a, "CPDUP"), + a->os_root, mountpt + 1, + a->os_root, mountpt); command_set_log_mode(cmd, COMMAND_LOG_QUIET); } @@ -395,44 +464,10 @@ fn_install_os(struct i_fn_args *a) a->os_root, cmd_name(a, "LN"), a->os_root); /* - * If the user has both /var and /tmp subpartitions, - * symlink /var/tmp to /tmp. - */ - if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") != NULL && - subpartition_find(storage_get_selected_slice(a->s), "/var") != NULL) { - command_add(cmds, "%s%s 1777 %smnt/tmp", - a->os_root, cmd_name(a, "CHMOD"), a->os_root); - command_add(cmds, "%s%s -rf %smnt/var/tmp", - a->os_root, cmd_name(a, "RM"), a->os_root); - command_add(cmds, "%s%s -s /tmp %smnt/var/tmp", - a->os_root, cmd_name(a, "LN"), a->os_root); - } - - /* - * If the user has /var, but no /tmp, - * symlink /tmp to /var/tmp. - */ - if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") == NULL && - subpartition_find(storage_get_selected_slice(a->s), "/var") != NULL) { - command_add(cmds, "%s%s -rf %smnt/tmp", - a->os_root, cmd_name(a, "RM"), a->os_root); - command_add(cmds, "%s%s -s /var/tmp %smnt/tmp", - a->os_root, cmd_name(a, "LN"), a->os_root); - } - - /* - * If the user has /usr, but no /home, - * symlink /home to /usr/home. + * Make sure /home exists (goes on root mount otherwise). */ - if (subpartition_find(storage_get_selected_slice(a->s), "/home") == NULL && - subpartition_find(storage_get_selected_slice(a->s), "/usr") != NULL) { - command_add(cmds, "%s%s -rf %smnt/home", - a->os_root, cmd_name(a, "RM"), a->os_root); - command_add(cmds, "%s%s %smnt/usr/home", + command_add(cmds, "%s%s -p %smnt/home", a->os_root, cmd_name(a, "MKDIR"), a->os_root); - command_add(cmds, "%s%s -s /usr/home %smnt/home", - a->os_root, cmd_name(a, "LN"), a->os_root); - } /* * XXX check for other possible combinations too? @@ -539,92 +574,112 @@ fn_install_os(struct i_fn_args *a) subpartition_get_device_name(sp), a->os_root); } - } else if (use_hammer == 0) { - if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) { - command_add(cmds, "%s%s '/dev/%s\t\t%s\t\tufs\trw\t\t1\t1' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - subpartition_get_device_name(sp), - subpartition_get_mountpoint(sp), - a->os_root); - } else if (subpartition_is_tmpfsbacked(sp)) { - command_add(cmds, "%s%s 'tmpfs\t\t\t%s\t\ttmpfs\trw,-s%luM\t1\t1' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - subpartition_get_mountpoint(sp), - subpartition_get_capacity(sp), - a->os_root); - } else if (subpartition_is_encrypted(sp)) { - command_add(cmds, "%s%s '%s\t/dev/%s\tnone\tnone' >>%smnt/etc/crypttab", - a->os_root, cmd_name(a, "ECHO"), - subpartition_get_mountpoint(sp) + 1, - subpartition_get_device_name(sp), - a->os_root); - command_add(cmds, "%s%s '/dev/mapper/%s\t\t%s\t\tufs\trw\t\t2\t2' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - subpartition_get_mountpoint(sp) + 1, - subpartition_get_mountpoint(sp), - a->os_root); - } else { - command_add(cmds, "%s%s '/dev/%s\t\t%s\t\tufs\trw\t\t2\t2' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - subpartition_get_device_name(sp), - subpartition_get_mountpoint(sp), - a->os_root); - } } else { + const char *fsname; + int order; + + /* + * fs type (/boot is always ufs) + */ + if (strcmp(subpartition_get_mountpoint(sp), "/boot") == 0) + fsname = "ufs"; + else if (use_hammer) + fsname = "hammer"; + else + fsname = "ufs"; + + if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) + order = 1; + else + order = 2; + + /* + * Adjust loader.conf for root partition + */ if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) { - command_add(cmds, "%s%s '/dev/%s\t\t%s\t\thammer\trw\t\t1\t1' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - subpartition_get_device_name(sp), - subpartition_get_mountpoint(sp), - a->os_root); if (subpartition_is_encrypted(sp)) { command_add(cmds, "%s%s 'vfs.root.mountfrom=\"ufs:md0s0\"' >>%smnt/boot/loader.conf", a->os_root, cmd_name(a, "ECHO"), a->os_root); command_add(cmds, - "%s%s 'vfs.root.realroot=\"crypt:hammer:%s:root\"' >>%smnt/boot/loader.conf", + "%s%s 'vfs.root.realroot=\"crypt:%s:%s:%s\"' >>%smnt/boot/loader.conf", a->os_root, cmd_name(a, "ECHO"), + fsname, subpartition_get_device_name(sp), + fn_mapper_name(subpartition_get_device_name(sp), -1), a->os_root); } else { command_add(cmds, - "%s%s 'vfs.root.mountfrom=\"hammer:%s\"' >>%smnt/boot/loader.conf", + "%s%s 'vfs.root.mountfrom=\"%s:%s\"' >>%smnt/boot/loader.conf", a->os_root, cmd_name(a, "ECHO"), + fsname, subpartition_get_device_name(sp), a->os_root); } - } else if (strcmp(subpartition_get_mountpoint(sp), "/boot") == 0) { - command_add(cmds, "%s%s '/dev/%s\t\t%s\t\tufs\trw\t\t1\t1' >>%smnt/etc/fstab", + } + if (subpartition_is_tmpfsbacked(sp)) { + command_add(cmds, "%s%s 'tmpfs\t\t\t%s\t\ttmpfs\trw,-s%luM\t1\t1' >>%smnt/etc/fstab", + a->os_root, cmd_name(a, "ECHO"), + subpartition_get_mountpoint(sp), + subpartition_get_capacity(sp), + a->os_root); + } else if (subpartition_is_encrypted(sp)) { + const char *mapper_name; + + mapper_name = fn_mapper_name(subpartition_get_device_name(sp), 0); + command_add(cmds, "%s%s '%s\t/dev/%s\tnone\tnone' >>%smnt/etc/crypttab", a->os_root, cmd_name(a, "ECHO"), + fn_mapper_name( subpartition_get_device_name(sp), -1), subpartition_get_device_name(sp), + a->os_root); + command_add(cmds, "%s%s '/dev/%s\t\t%s\t\t%s\trw\t\t2\t2' >>%smnt/etc/fstab", + a->os_root, cmd_name(a, "ECHO"), + mapper_name, subpartition_get_mountpoint(sp), + fsname, + a->os_root); + } else { + command_add(cmds, "%s%s '/dev/%s\t\t%s\t\t%s\trw\t\t%d\t%d' >>%smnt/etc/fstab", + a->os_root, cmd_name(a, "ECHO"), + subpartition_get_device_name(sp), + subpartition_get_mountpoint(sp), + fsname, + order, order, a->os_root); } } } /* - * Take care of HAMMER PFS null mounts. + * Take care of NULL mounts from /build for things like /var/crash + * and /usr/obj if not specified as a discrete partition. */ - if (use_hammer == 1) { - for (j = 0; pfs_mountpt[j] != NULL; j++) { - if (rindex(pfs_mountpt[j]+1, '/') != NULL) - command_add(cmds, "%s%s '/pfs%s.%s\t%s\t\tnull\trw\t\t0\t0' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - dirname(pfs_mountpt[j]), - basename(pfs_mountpt[j]), - pfs_mountpt[j], - a->os_root); - else - command_add(cmds, "%s%s '/pfs%s\t\t%s\t\tnull\trw\t\t0\t0' >>%smnt/etc/fstab", - a->os_root, cmd_name(a, "ECHO"), - pfs_mountpt[j], - pfs_mountpt[j], - a->os_root); + for (j = 0; nullfs_mountpt[j] != NULL; j++) { + if (subpartition_find(storage_get_selected_slice(a->s), + "%s", nullfs_mountpt[i]) != NULL) { + continue; } + command_add(cmds, + "%s%s '%s\t%s\t\tnull\trw\t\t0\t0' >>%smnt/etc/fstab", + a->os_root, cmd_name(a, "ECHO"), + nullfs_mountname[j], + nullfs_mountpt[j], + a->os_root); + } + + /* + * Take care of /tmp as a tmpfs filesystem + */ + if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") == NULL) { + command_add(cmds, + "%s%s 'tmpfs\t/tmp\t\ttmpfs\trw\t\t0\t0' >>%smnt/etc/fstab", + a->os_root, cmd_name(a, "ECHO"), a->os_root); } + /* + * Take care of /proc + */ command_add(cmds, "%s%s '%s' >>%smnt/etc/fstab", a->os_root, cmd_name(a, "ECHO"), "proc\t\t\t/proc\t\tprocfs\trw\t\t0\t0", @@ -637,12 +692,14 @@ fn_install_os(struct i_fn_args *a) a->os_root, slice_get_device_name(storage_get_selected_slice(a->s))); +#if 0 /* 'chflags nohistory' as needed */ for (j = 0; pfs_mountpt[j] != NULL; j++) if (pfs_nohistory[j] == 1) command_add(cmds, "%s%s -R nohistory %smnt%s", a->os_root, cmd_name(a, "CHFLAGS"), a->os_root, pfs_mountpt[j]); +#endif /* Do some preparation if encrypted partitions were configured */ if (needcrypt) { @@ -704,6 +761,7 @@ fn_install_os(struct i_fn_args *a) * command chain, so that partitions are unmounted, even if an error * occurs in one of the preceding commands, or it is cancelled. */ + unmount_altfs(a, cmds); unmount_all_under(a, cmds, "%smnt", a->os_root); /* @@ -728,3 +786,37 @@ fn_install_os(struct i_fn_args *a) if (remove_all_mappings(a) == NULL) inform(a->c, _("Warning: mappings could not be removed.")); } + +/* + * /dev/mapper/ + * + * (result is persistant until next call) + */ +const char * +fn_mapper_name(const char *mountpt, int withdev) +{ + const char *src; + static char *save; + + src = strrchr(mountpt, '/'); + if (src == NULL || src[1] == 0) + src = "root"; + else + ++src; + + if (save) + free(save); + switch(withdev) { + case -1: + asprintf(&save, "%s", src); + break; + case 0: + asprintf(&save, "mapper/%s", src); + break; + case 1: + default: + asprintf(&save, "/dev/mapper/%s", src); + break; + } + return save; +} diff --git a/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c b/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c index 9df10a50b9..844045119f 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c +++ b/usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef ENABLE_NLS #include @@ -68,15 +69,21 @@ static int create_subpartitions(struct i_fn_args *); static long default_capacity(struct storage *, const char *); static int check_capacity(struct i_fn_args *); -static int check_subpartition_selections(struct dfui_response *, struct i_fn_args *); -static void save_subpartition_selections(struct dfui_response *, struct i_fn_args *); -static void populate_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); +static int check_subpartition_selections(struct dfui_response *, + struct i_fn_args *); +static void save_subpartition_selections(struct dfui_response *, + struct i_fn_args *); +static void populate_create_subpartitions_form(struct dfui_form *, + struct i_fn_args *); static int warn_subpartition_selections(struct i_fn_args *); static int warn_encrypted_boot(struct i_fn_args *); static struct dfui_form *make_create_subpartitions_form(struct i_fn_args *); -static int show_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); +static int show_create_subpartitions_form(struct dfui_form *, + struct i_fn_args *); +static char *construct_lname(const char *mtpt); -static const char *def_mountpt[] = {"/boot", "swap", "/", NULL}; +static const char *def_mountpt[] = {"/boot", "swap", "/", "/build", NULL}; +static long min_capacity[] = { 128, 0, DISK_MIN - 128, BUILD_MIN }; static int expert = 0; /* @@ -117,7 +124,10 @@ create_subpartitions(struct i_fn_args *a) * '16 partitions' line. */ num_partitions = 16; - command_add(cmds, "%s%s '$2==\"partitions:\" || cut { cut = 1 } !cut { print $0 }' <%sinstall.disklabel.%s >%sinstall.disklabel", + command_add(cmds, + "%s%s '$2==\"partitions:\" || " + "cut { cut = 1 } !cut { print $0 }' " + "<%sinstall.disklabel.%s >%sinstall.disklabel", a->os_root, cmd_name(a, "AWK"), a->tmp, slice_get_device_name(storage_get_selected_slice(a->s)), @@ -155,19 +165,25 @@ create_subpartitions(struct i_fn_args *a) continue; } if (subpartition_is_swap(sp)) { - command_add(cmds, "%s%s ' %c:\t%s\t*\tswap' >>%sinstall.disklabel", + command_add(cmds, + "%s%s ' %c:\t%s\t*\tswap' " + ">>%sinstall.disklabel", a->os_root, cmd_name(a, "ECHO"), subpartition_get_letter(sp), capacity_to_string(subpartition_get_capacity(sp)), a->tmp); } else if (strcmp(subpartition_get_mountpoint(sp), "/boot") == 0) { - command_add(cmds, "%s%s ' %c:\t%s\t0\t4.2BSD' >>%sinstall.disklabel", + command_add(cmds, + "%s%s ' %c:\t%s\t0\t4.2BSD' " + ">>%sinstall.disklabel", a->os_root, cmd_name(a, "ECHO"), subpartition_get_letter(sp), capacity_to_string(subpartition_get_capacity(sp)), a->tmp); } else { - command_add(cmds, "%s%s ' %c:\t%s\t*\tHAMMER' >>%sinstall.disklabel", + command_add(cmds, + "%s%s ' %c:\t%s\t*\tHAMMER' " + ">>%sinstall.disklabel", a->os_root, cmd_name(a, "ECHO"), subpartition_get_letter(sp), capacity_to_string(subpartition_get_capacity(sp)), @@ -208,7 +224,8 @@ create_subpartitions(struct i_fn_args *a) */ for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); sp != NULL; sp = subpartition_next(sp)) { - if (subpartition_is_swap(sp) || subpartition_is_tmpfsbacked(sp)) { + if (subpartition_is_swap(sp) || + subpartition_is_tmpfsbacked(sp)) { if (subpartition_is_swap(sp) && subpartition_is_encrypted(sp)) { command_add(cmds, @@ -228,20 +245,25 @@ create_subpartitions(struct i_fn_args *a) a->os_root, cmd_name(a, "NEWFS"), subpartition_get_device_name(sp)); } else { + char *ham_name; if (subpartition_is_encrypted(sp)) { command_add(cmds, "%s%s -d /tmp/t1 luksFormat /dev/%s", a->os_root, cmd_name(a, "CRYPTSETUP"), subpartition_get_device_name(sp)); command_add(cmds, - "%s%s -d /tmp/t1 luksOpen /dev/%s root", + "%s%s -d /tmp/t1 luksOpen /dev/%s %s", a->os_root, cmd_name(a, "CRYPTSETUP"), - subpartition_get_device_name(sp)); + subpartition_get_device_name(sp), + fn_mapper_name(subpartition_get_device_name(sp), -1)); } - command_add(cmds, "%s%s -f -L ROOT /dev/%s", + ham_name = construct_lname(subpartition_get_mountpoint(sp)); + command_add(cmds, "%s%s -f -L %s /dev/%s", a->os_root, cmd_name(a, "NEWFS_HAMMER"), + ham_name, subpartition_is_encrypted(sp) ? - "mapper/root" : subpartition_get_device_name(sp)); + fn_mapper_name(subpartition_get_device_name(sp), 0) : subpartition_get_device_name(sp)); + free(ham_name); } } @@ -250,39 +272,83 @@ create_subpartitions(struct i_fn_args *a) return(result); } +/* + * Return default capacity field filler. Return 0 for /build if drive + * space minus swap is < 40GB (causes installer to use PFS's on the root + * partition instead). + */ static long default_capacity(struct storage *s, const char *mtpt) { - unsigned long boot, root, swap; + unsigned long boot, root, swap, build; unsigned long capacity; unsigned long mem; - capacity = slice_get_capacity(storage_get_selected_slice(s)); + capacity = slice_get_capacity(storage_get_selected_slice(s)); /* MB */ mem = storage_get_memsize(s); /* - * Slice capacity is at least 10G at this point. - * /boot is 1G and root is at least 75% slice size. - * The rest goes to swap, up to twice the memory amount - * or SWAP_MAX. - * The 'root' variable is just for calculation and any - * disk space beyond the above constraints goes to root. + * Slice capacity is at least 10G at this point. Calculate basic + * defaults. */ - - root = capacity / 4 * 3; swap = 2 * mem; - if (swap > SWAP_MAX) + if (swap > capacity / 10) /* max 1/10 capacity */ + swap = capacity / 10; + if (swap < SWAP_MIN) /* having a little is nice */ + swap = SWAP_MIN; + if (swap > SWAP_MAX) /* installer cap */ swap = SWAP_MAX; + boot = 1024; - if (boot + root + swap > capacity) - swap = capacity - boot - root; + + build = (capacity - swap - boot) / 3; + if (build > BUILD_MAX) + build = BUILD_MAX; + + for (;;) { + root = (capacity - swap - boot - build); + + /* + * Adjust until the defaults look sane + * + * root should be at least twice as large as build + */ + if (build && root < build * 2) { + --build; + continue; + } + + /* + * root should be at least 1/2 capacity + */ + if (build && root < capacity / 2) { + --build; + continue; + } + break; + } + + /* + * Finalize. If build is too small do not supply a /build, + * and if swap is too small do not supply swap. + */ + if (build < BUILD_MIN) + build = 0; + if (swap < SWAP_MIN) + swap = 0; + if (build == 0) + root = -1; /* root is the last part */ + else + build = -1; /* last partition just use remaining space */ if (strcmp(mtpt, "/boot") == 0) return(boot); + else if (strcmp(mtpt, "/build") == 0) + return(build); else if (strcmp(mtpt, "swap") == 0) return(swap); else if (strcmp(mtpt, "/") == 0) - return(-1); + return(root); /* shouldn't ever happen */ return(-1); @@ -292,12 +358,13 @@ static int check_capacity(struct i_fn_args *a) { struct subpartition *sp; - long min_capacity[] = {128, 0, DISK_MIN - 128, 0}; unsigned long total_capacity = 0; unsigned long remaining_capacity; int mtpt, warn_smallpart = 0; + int good; - remaining_capacity = slice_get_capacity(storage_get_selected_slice(a->s)); + remaining_capacity = slice_get_capacity( + storage_get_selected_slice(a->s)); for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); sp != NULL; sp = subpartition_next(sp)) { if (subpartition_get_capacity(sp) != -1) @@ -317,20 +384,24 @@ check_capacity(struct i_fn_args *a) if (strcmp(mountpt, def_mountpt[mtpt]) == 0 && subpart_capacity < min_capacity[mtpt] && subpart_capacity != -1) { - inform(a->c, _("WARNING: The size (%ldM) specified for " + inform(a->c, + _("WARNING: The size (%ldM) specified for " "the %s subpartition is too small. It " "should be at least %ldM or you will " "risk running out of space during " - "the installation."), + "installation or operation."), subpart_capacity, mountpt, min_capacity[mtpt]); } } if (strcmp(mountpt, "/boot") != 0 && strcmp(mountpt, "swap") != 0) { - if ((subpart_capacity == -1 && remaining_capacity < HAMMER_WARN) || - (subpart_capacity != -1 && subpart_capacity < HAMMER_WARN)) + if ((subpart_capacity == -1 && + remaining_capacity < HAMMER_WARN) || + (subpart_capacity != -1 && + subpart_capacity < HAMMER_WARN)) { warn_smallpart++; + } } } @@ -340,19 +411,24 @@ check_capacity(struct i_fn_args *a) "capacity of the selected primary partition " "(%luM). Remove some subpartitions or choose " "a smaller size for them and try again."), - total_capacity, slice_get_capacity(storage_get_selected_slice(a->s))); + total_capacity, + slice_get_capacity(storage_get_selected_slice(a->s))); return(0); } - if (warn_smallpart) - return (confirm_dangerous_action(a->c, - _("WARNING: HAMMER filesystems less than 50GB are " - "not recommended!\n" - "You may have to run 'hammer prune-everything' and " - "'hammer reblock'\n" - "quite often, even if using a nohistory mount."))); + if (warn_smallpart) { + good = confirm_dangerous_action(a->c, + _("WARNING: Small HAMMER filesystems can fill up " + "very quickly!\n" + "You may have to run 'hammer prune-everything' and " + "'hammer reblock'\n" + "manually or often via a cron job, even if using a " + "nohistory mount.")); + } else { + good = 1; + } - return(1); + return (good); } static int @@ -520,6 +596,8 @@ populate_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a) */ for (i = 0; def_mountpt[i] != NULL; i++) { capacity = default_capacity(a->s, def_mountpt[i]); + if (capacity == 0) /* used to disable /build */ + continue; ds = dfui_dataset_new(); dfui_dataset_celldata_add(ds, "mountpoint", def_mountpt[i]); @@ -538,16 +616,10 @@ warn_subpartition_selections(struct i_fn_args *a) if (subpartition_find(storage_get_selected_slice(a->s), "/boot") == NULL) { inform(a->c, _("The /boot partition must not be omitted.")); - } else if (subpartition_find(storage_get_selected_slice(a->s), "/home") != NULL || - subpartition_find(storage_get_selected_slice(a->s), "/tmp") != NULL || - subpartition_find(storage_get_selected_slice(a->s), "/usr") != NULL || - subpartition_find(storage_get_selected_slice(a->s), "/usr/obj") != NULL || - subpartition_find(storage_get_selected_slice(a->s), "/var") != NULL || - subpartition_find(storage_get_selected_slice(a->s), "/var/crash") != NULL || - subpartition_find(storage_get_selected_slice(a->s), "/var/tmp") != NULL) { - inform(a->c, _("Pseudo filesystems will automatically be created " - "for /home, /tmp, /usr, /usr/obj, /var, /var/crash " - "and /var/tmp and must not be specified.")); + } else if (subpartition_find(storage_get_selected_slice(a->s), "/build") == NULL) { + inform(a->c, _("Without a /build, things like /usr/obj and " + "/var/crash will just be on the root mount.")); + valid = check_capacity(a); } else { valid = check_capacity(a); } @@ -605,10 +677,13 @@ make_create_subpartitions_form(struct i_fn_args *a) f = dfui_form_create( "create_subpartitions", _("Create Subpartitions"), - _("Set up the subpartitions (also known as just `partitions' " - "in BSD tradition) you want to have on this primary " + _("Set up the subpartitions you want to have on this primary " "partition. In most cases you should be fine with " - "the default settings.\n\n" + "the default settings." + " Note that /build will hold /usr/obj, /var/crash, and other" + " elements of the topology that do not need to be backed up." + " If no /build is specified, these dirs will be on the root." + "\n\n" "For Capacity, use 'M' to indicate megabytes, 'G' to " "indicate gigabytes, and so on (up to 'E'.) A single '*' " "indicates 'use the remaining space on the primary partition'."), @@ -762,3 +837,25 @@ fn_create_subpartitions_hammer(struct i_fn_args *a) dfui_form_free(f); } } + +static +char * +construct_lname(const char *mtpt) +{ + char *res; + int i; + + if (strcmp(mtpt, "/") == 0) { + res = strdup("ROOT"); + } else { + if (strrchr(mtpt, '/')) + mtpt = strrchr(mtpt, '/') + 1; + if (*mtpt == 0) + mtpt = "unknown"; + res = malloc(strlen(mtpt) + 1); + for (i = 0; mtpt[i]; ++i) + res[i] = toupper(mtpt[i]); + res[i] = 0; + } + return res; +} diff --git a/usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c b/usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c index 530b496e5a..19e2f0fb67 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c +++ b/usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c @@ -1,5 +1,5 @@ /* - * Copyright (c)2004 The DragonFly Project. All rights reserved. + * Copyright (c)2004,2015 The DragonFly Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -66,18 +66,23 @@ #include "flow.h" #include "pathnames.h" +#define MTPT_BOOT 0 +#define MTPT_SWAP 1 +#define MTPT_ROOT 2 +#define MTPT_BUILD 3 + static int create_subpartitions(struct i_fn_args *); -static long default_capacity(struct storage *, int); +static long default_capacity(struct storage *, const char *); static int check_capacity(struct i_fn_args *); static int check_subpartition_selections(struct dfui_response *, struct i_fn_args *); static void save_subpartition_selections(struct dfui_response *, struct i_fn_args *); static void populate_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); static int warn_subpartition_selections(struct i_fn_args *); -static int warn_encrypted_root(struct i_fn_args *); static struct dfui_form *make_create_subpartitions_form(struct i_fn_args *); static int show_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); -static const char *def_mountpt[] = {"/", "swap", "/var", "/tmp", "/usr", "/home", NULL}; +static const char *def_mountpt[] = {"/boot", "swap", "/", "/build", NULL}; +static long min_capacity[] = { 128, 0, DISK_MIN - 128, BUILD_MIN }; static int expert = 0; /* @@ -219,8 +224,7 @@ create_subpartitions(struct i_fn_args *a) continue; } - if (subpartition_is_encrypted(sp) && - strcmp(subpartition_get_mountpoint(sp), "/") != 0) { + if (subpartition_is_encrypted(sp)) { command_add(cmds, "%s%s -d /tmp/t1 luksFormat /dev/%s", a->os_root, cmd_name(a, "CRYPTSETUP"), @@ -229,13 +233,13 @@ create_subpartitions(struct i_fn_args *a) "%s%s -d /tmp/t1 luksOpen /dev/%s %s", a->os_root, cmd_name(a, "CRYPTSETUP"), subpartition_get_device_name(sp), - subpartition_get_mountpoint(sp) + 1); + fn_mapper_name(subpartition_get_device_name(sp), -1)); command_add(cmds, "%s%s%s -b %ld -f %ld /dev/mapper/%s", a->os_root, cmd_name(a, "NEWFS"), subpartition_is_softupdated(sp) ? " -U" : "", subpartition_get_bsize(sp), subpartition_get_fsize(sp), - subpartition_get_mountpoint(sp) + 1); + fn_mapper_name(subpartition_get_device_name(sp), -1)); } else { command_add(cmds, "%s%s%s -b %ld -f %ld /dev/%s", a->os_root, cmd_name(a, "NEWFS"), @@ -251,43 +255,84 @@ create_subpartitions(struct i_fn_args *a) return(result); } +/* + * Return default capacity field filler. Return 0 for /build if drive + * space minus swap is < 40GB (causes installer to use PFS's on the root + * partition instead). + */ static long -default_capacity(struct storage *s, int mtpt) +default_capacity(struct storage *s, const char *mtpt) { - unsigned long swap; + unsigned long boot, root, swap, build; unsigned long capacity; unsigned long mem; - if (mtpt == MTPT_HOME) - return(-1); - - capacity = slice_get_capacity(storage_get_selected_slice(s)); - if (capacity <= 8192 && mtpt == MTPT_ROOT) - return(-1); + capacity = slice_get_capacity(storage_get_selected_slice(s)); /* MB */ mem = storage_get_memsize(s); + + /* + * Slice capacity is at least 10G at this point. Calculate basic + * defaults. + */ swap = 2 * mem; - while (swap > capacity / 4) - swap -= 128; - if (swap > SWAP_MAX) + if (swap > capacity / 10) /* max 1/10 capacity */ + swap = capacity / 10; + if (swap < SWAP_MIN) /* having a little is nice */ + swap = SWAP_MIN; + if (swap > SWAP_MAX) /* installer cap */ swap = SWAP_MAX; - if (capacity < 12800) { - switch (mtpt) { - case MTPT_ROOT: return(640); - case MTPT_SWAP: return(swap); - case MTPT_VAR: return(256); - case MTPT_TMP: return(256); - case MTPT_USR: return(2688); + boot = 1024; + + build = (capacity - swap - boot) / 3; + if (build > BUILD_MAX) + build = BUILD_MAX; + + for (;;) { + root = (capacity - swap - boot - build); + + /* + * Adjust until the defaults look sane + * + * root should be at least twice as large as build + */ + if (build && root < build * 2) { + --build; + continue; } - } else { - switch (mtpt) { - case MTPT_ROOT: return(1024); - case MTPT_SWAP: return(swap); - case MTPT_VAR: return(256); - case MTPT_TMP: return(256); - case MTPT_USR: return(7680); + + /* + * root should be at least 1/2 capacity + */ + if (build && root < capacity / 2) { + --build; + continue; } + break; } + + /* + * Finalize. If build is too small do not supply a /build, + * and if swap is too small do not supply swap. + */ + if (build < BUILD_MIN) + build = 0; + if (swap < SWAP_MIN) + swap = 0; + if (build == 0) + root = -1; /* no /build, root is the last part */ + else + build = -1; /* last partition just use remaining space */ + + if (strcmp(mtpt, "/boot") == 0) + return(boot); + else if (strcmp(mtpt, "/build") == 0) + return(build); + else if (strcmp(mtpt, "swap") == 0) + return(swap); + else if (strcmp(mtpt, "/") == 0) + return(root); + /* shouldn't ever happen */ return(-1); } @@ -296,13 +341,9 @@ static int check_capacity(struct i_fn_args *a) { struct subpartition *sp; - long min_capacity[] = {320, 0, 16, 0, 1472, 0, 0}; unsigned long total_capacity = 0; int mtpt; - if (subpartition_find(storage_get_selected_slice(a->s), "/usr") == NULL) - min_capacity[MTPT_ROOT] += min_capacity[MTPT_USR]; - for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); sp != NULL; sp = subpartition_next(sp)) { long subpart_capacity = subpartition_get_capacity(sp); @@ -544,7 +585,9 @@ populate_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a) * total physical memory (for swap.) */ for (mtpt = 0; def_mountpt[mtpt] != NULL; mtpt++) { - capacity = default_capacity(a->s, mtpt); + capacity = default_capacity(a->s, def_mountpt[mtpt]); + if (capacity == 0) + continue; ds = dfui_dataset_new(); dfui_dataset_celldata_add(ds, "mountpoint", def_mountpt[mtpt]); @@ -570,85 +613,12 @@ static int warn_subpartition_selections(struct i_fn_args *a) { int valid = 0; - struct aura_buffer *omit, *consequences; /* Skip this check for disks <= 8GB */ if (slice_get_capacity(storage_get_selected_slice(a->s)) <= 8192) return 0; - omit = aura_buffer_new(2048); - consequences = aura_buffer_new(2048); - valid = check_capacity(a); - if (subpartition_find(storage_get_selected_slice(a->s), "/var") == NULL) { - aura_buffer_cat(omit, "/var "); - aura_buffer_cat(consequences, _("/var will be a plain dir in /\n")); - } - if (subpartition_find(storage_get_selected_slice(a->s), "/usr") == NULL) { - aura_buffer_cat(omit, "/usr "); - aura_buffer_cat(consequences, _("/usr will be a plain dir in /\n")); - } - if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") == NULL) { - aura_buffer_cat(omit, "/tmp "); - aura_buffer_cat(consequences, _("/tmp will be symlinked to /var/tmp\n")); - } - if (subpartition_find(storage_get_selected_slice(a->s), "/home") == NULL) { - aura_buffer_cat(omit, "/home "); - aura_buffer_cat(consequences, _("/home will be symlinked to /usr/home\n")); - } - - if (valid && aura_buffer_len(omit) > 0) { - switch (dfui_be_present_dialog(a->c, _("Really omit?"), - _("Omit Subpartition(s)|Return to Create Subpartitions"), - _("You have elected to not have the following " - "subpartition(s):\n\n%s\n\n" - "The ramifications of these subpartition(s) being " - "missing will be:\n\n%s\n" - "Is this really what you want to do?"), - aura_buffer_buf(omit), aura_buffer_buf(consequences))) { - case 1: - valid = 1; - break; - case 2: - valid = 0; - break; - default: - abort_backend(); - } - } - - aura_buffer_free(omit); - aura_buffer_free(consequences); - - return(!valid); -} - -static int -warn_encrypted_root(struct i_fn_args *a) -{ - int valid = 1; - struct subpartition *sp; - - sp = subpartition_find(storage_get_selected_slice(a->s), "/"); - if (sp == NULL) - return(!valid); - - if (subpartition_is_encrypted(sp)) { - switch (dfui_be_present_dialog(a->c, _("root cannot be encrypted"), - _("Leave root unencrypted|Return to Create Subpartitions"), - _("You have selected encryption for the root partition which " - "is not supported."))) { - case 1: - subpartition_clr_encrypted(sp); - valid = 1; - break; - case 2: - valid = 0; - break; - default: - abort_backend(); - } - } return(!valid); } @@ -761,8 +731,7 @@ show_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a) } else { if (check_subpartition_selections(r, a)) { save_subpartition_selections(r, a); - if (!warn_subpartition_selections(a) && - !warn_encrypted_root(a)) { + if (!warn_subpartition_selections(a)) { if (!create_subpartitions(a)) { inform(a->c, _("The subpartitions you chose were " "not correctly created, and the " @@ -803,8 +772,10 @@ fn_create_subpartitions_ufs(struct i_fn_args *a) "required %dM for the UFS filesystem."), DISK_MIN); return; } +#if 0 if (capacity <= 8192) def_mountpt[2] = NULL; /* XXX adjust each time in a session */ +#endif while (!done) { f = make_create_subpartitions_form(a); switch (show_create_subpartitions_form(f, a)) { diff --git a/usr.sbin/installer/libinstaller/diskutil.c b/usr.sbin/installer/libinstaller/diskutil.c index 2ca75c595e..6b74735e7f 100644 --- a/usr.sbin/installer/libinstaller/diskutil.c +++ b/usr.sbin/installer/libinstaller/diskutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c)2004 The DragonFly Project. All rights reserved. + * Copyright (c)2004,2015 The DragonFly Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -505,12 +505,12 @@ subpartition_new_hammer(struct slice *s, const char *mountpoint, long capacity, int encrypted) { struct subpartition *sp; + struct subpartition *last = s->subpartition_tail; AURA_MALLOC(sp, subpartition); sp->parent = s; - struct subpartition *last = s->subpartition_tail; if (last == NULL) { sp->letter = 'a'; } else if (last->letter == 'b') { @@ -518,6 +518,8 @@ subpartition_new_hammer(struct slice *s, const char *mountpoint, long capacity, } else { sp->letter = (char)(last->letter + 1); } + if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0) + sp->letter = 'd'; sp->mountpoint = aura_strdup(mountpoint); sp->capacity = capacity; @@ -538,12 +540,16 @@ subpartition_new_hammer(struct slice *s, const char *mountpoint, long capacity, sp->bsize = 16384; sp->is_swap = 0; +#if 0 sp->pfs = 0; +#endif if (strcasecmp(mountpoint, "swap") == 0) sp->is_swap = 1; +#if 0 if (strcmp(mountpoint, "/") != 0 && strcmp(mountpoint, "/boot") != 0 && strcmp(mountpoint, "swap") != 0) sp->pfs = 1; +#endif sp->next = NULL; if (s->subpartition_head == NULL) @@ -567,11 +573,27 @@ struct subpartition * subpartition_new_ufs(struct slice *s, const char *mountpoint, long capacity, int encrypted, int softupdates, long fsize, long bsize, int tmpfsbacked) { - struct subpartition *sp, *sptmp; - int letter='d'; + struct subpartition *sp; + struct subpartition *last = s->subpartition_tail; AURA_MALLOC(sp, subpartition); + if (tmpfsbacked) { + sp->letter = '@'; + } else { + while (last && last->letter == '@') + last = last->prev; + if (last == NULL) { + sp->letter = 'a'; + } else if (last->letter == 'b') { + sp->letter = 'd'; + } else { + sp->letter = (char)(last->letter + 1); + } + if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0) + sp->letter = 'd'; + } + sp->parent = s; sp->mountpoint = aura_strdup(mountpoint); @@ -612,29 +634,19 @@ subpartition_new_ufs(struct slice *s, const char *mountpoint, long capacity, if (strcasecmp(mountpoint, "swap") == 0) sp->is_swap = 1; - if (s->subpartition_head == NULL) { + /* + * install + */ + sp->next = NULL; + if (s->subpartition_head == NULL) s->subpartition_head = sp; - s->subpartition_tail = sp; - } else { - for (sptmp = s->subpartition_head; sptmp != NULL; - sptmp = sptmp->next) { - if (strcmp(sptmp->mountpoint, sp->mountpoint) > 0) - break; - } - if (sptmp != NULL) { - if (s->subpartition_head == sptmp) - s->subpartition_head = sp; - else - sptmp->prev->next = sp; - sp->next = sptmp; - sp->prev = sptmp->prev; - sptmp->prev = sp; - } else { - sp->prev = s->subpartition_tail; - s->subpartition_tail->next = sp; - s->subpartition_tail = sp; - } - } + else + s->subpartition_tail->next = sp; + + sp->prev = s->subpartition_tail; + s->subpartition_tail = sp; + +#if 0 for (sptmp = s->subpartition_head; sptmp != NULL; sptmp = sptmp->next) { @@ -648,6 +660,7 @@ subpartition_new_ufs(struct slice *s, const char *mountpoint, long capacity, else sptmp->letter = letter++; } +#endif return(sp); }