installer - use a more modern mount setup for UFS and HAMMER.
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 14 Dec 2015 03:18:47 +0000 (19:18 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 14 Dec 2015 07:07:56 +0000 (23:07 -0800)
* 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.

etc/mtree/BSD.root.dist
etc/mtree/BSD.var.dist
share/installer/sources.conf
usr.sbin/installer/dfuibe_installer/flow.h
usr.sbin/installer/dfuibe_installer/fn.h
usr.sbin/installer/dfuibe_installer/fn_configure.c
usr.sbin/installer/dfuibe_installer/fn_install.c
usr.sbin/installer/dfuibe_installer/fn_subpart_hammer.c
usr.sbin/installer/dfuibe_installer/fn_subpart_ufs.c
usr.sbin/installer/libinstaller/diskutil.c

index 3a0364a..c2df8b0 100644 (file)
@@ -13,6 +13,8 @@
         kernel
         ..
     ..
+    build
+    ..
     compat
         ndis
         ..
index 1475133..e2e15d6 100644 (file)
@@ -18,6 +18,8 @@
 /set mode=0750
     backups
     ..
+    cache              mode=0755
+    ..
     crash
     ..
     cron
index 515b868..0b09b50 100644 (file)
@@ -2,7 +2,6 @@
 /bin
 /boot
 /compat
-/dev
 /etc
 /lib
 /libexec
index a15887b..ee93ad4 100644 (file)
 #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;
index 7edfb9d..6bf3e58 100644 (file)
@@ -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 */
 
index 616de96..84189e5 100644 (file)
@@ -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;
 }
index 9ec1d75..4797dc7 100644 (file)
@@ -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
 #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;
+}
index 9df10a5..8440451 100644 (file)
@@ -39,6 +39,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #ifdef ENABLE_NLS
 #include <libintl.h>
 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;
+}
index 530b496..19e2f0f 100644 (file)
@@ -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
 #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)) {
index 2ca75c5..6b74735 100644 (file)
@@ -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);
 }