Index: usr.sbin/bsdinstall/partedit/gpart_ops.c =================================================================== --- usr.sbin/bsdinstall/partedit/gpart_ops.c +++ usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -80,9 +80,10 @@ } static void -newfs_command(const char *fstype, char *command, int use_default) +newfs_command(struct partition_metadata *md, char *command, int use_default) { - if (strcmp(fstype, "freebsd-ufs") == 0) { + md->bootenv = 0; + if (strcmp(md->fstype, "freebsd-ufs") == 0) { int i; DIALOG_LISTITEM items[] = { {"UFS1", "UFS Version 1", @@ -120,7 +121,7 @@ else if (strcmp(items[i].name, "TRIM") == 0) strcat(command, "-t "); } - } else if (strcmp(fstype, "freebsd-zfs") == 0) { + } else if (strcmp(md->fstype, "freebsd-zfs") == 0) { int i; DIALOG_LISTITEM items[] = { {"fletcher4", "checksum algorithm: fletcher4", @@ -132,8 +133,12 @@ {"sha256", "checksum algorithm: sha256", "Use sha256 for data integrity checking. " "(not recommended)", 0 }, - {"atime", "Update atimes for files", - "Disable atime update", 0 }, + {"atime", "Disable atime for files", + "Disable updating last accessed time on files", 0 }, + {"compression", "Enable compression", + "Transparently compress files to save space", 0 }, + {"bootenv", "Enable Boot Environments", + "Layout the pool to support Boot Environments", 1 }, }; if (!use_default) { @@ -145,7 +150,7 @@ return; } - strcpy(command, "zpool create -f -m none "); + strcpy(command, "zpool create -f -m none -o altroot=/mnt "); if (getenv("BSDINSTALL_TMPBOOT") != NULL) { char zfsboot_path[MAXPATHLEN]; sprintf(zfsboot_path, "%s/zfs", @@ -166,8 +171,12 @@ strcat(command, "-O checksum=sha256 "); else if (strcmp(items[i].name, "atime") == 0) strcat(command, "-O atime=off "); + else if (strcmp(items[i].name, "compression") == 0) + strcat(command, "-O compression=on "); + else if (strcmp(items[i].name, "bootenv") == 0) + md->bootenv = 1; } - } else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0) { + } else if (strcmp(md->fstype, "fat32") == 0 || strcmp(md->fstype, "efi") == 0) { int i; DIALOG_LISTITEM items[] = { {"FAT32", "FAT Type 32", @@ -599,13 +608,9 @@ idx = atoi(gc->lg_val); } - TAILQ_FOREACH(md, &part_metadata, metadata) { - if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) { - if (md->fstab != NULL) - items[2].text = md->fstab->fs_file; - break; - } - } + md = get_part_metadata(pp->lg_name, 1); + if (md->fstab != NULL) + items[2].text = md->fstab->fs_file; humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL); @@ -641,7 +646,10 @@ } gctl_free(r); - newfs_command(items[0].text, newfs, 1); + if (md->fstype != NULL) + free(md->fstype); + md->fstype = strdup(items[0].text); + newfs_command(md, newfs, 1); set_default_part_metadata(pp->lg_name, scheme, items[0].text, items[2].text, (strcmp(oldtype, items[0].text) != 0) ? newfs : NULL); @@ -674,20 +682,26 @@ free(md->newfs); md->newfs = NULL; } + if (md->poolname != NULL) { + free(md->poolname); + md->poolname = NULL; + } if (newfs != NULL && newfs[0] != '\0') { - md->newfs = malloc(strlen(newfs) + strlen(" /dev/") + - strlen(mountpoint) + 5 + strlen(name) + 1); - if (strcmp("freebsd-zfs", type) == 0) { - zpool_name = strdup((strlen(mountpoint) == 1) ? - "root" : &mountpoint[1]); - for (i = 0; zpool_name[i] != 0; i++) - if (!isalnum(zpool_name[i])) - zpool_name[i] = '_'; - sprintf(md->newfs, "%s %s /dev/%s", newfs, + if (strcmp(type, "freebsd-zfs") == 0) { + if (strlen(mountpoint) == 1) { + zpool_name = strdup("zroot"); + } else { + zpool_name = strdup(&mountpoint[1]); + for (i = 0; zpool_name[i] != 0; i++) + if (!isalnum(zpool_name[i])) + zpool_name[i] = '_'; + } + md->poolname = strdup(zpool_name); + asprintf(&md->newfs, "%s %s /dev/%s", newfs, zpool_name, name); } else { - sprintf(md->newfs, "%s /dev/%s", newfs, name); + asprintf(&md->newfs, "%s /dev/%s", newfs, name); } } } @@ -702,7 +716,7 @@ || strcmp(type, "freebsd-zfs") == 0)) md->bootcode = 1; - if (mountpoint == NULL || mountpoint[0] == '\0') { + if (mountpoint == NULL || mountpoint[0] == '\0' || md->bootenv == 1) { if (md->fstab != NULL) { free(md->fstab->fs_spec); free(md->fstab->fs_file); @@ -722,7 +736,17 @@ free(md->fstab->fs_mntops); free(md->fstab->fs_type); } - if (strcmp("freebsd-zfs", type) == 0) { + if (strcmp(type, "freebsd-zfs") == 0) { + if (zpool_name == NULL) { + if (strlen(mountpoint) == 1) { + zpool_name = strdup("zroot"); + } else { + zpool_name = strdup(&mountpoint[1]); + for (i = 0; zpool_name[i] != 0; i++) + if (!isalnum(zpool_name[i])) + zpool_name[i] = '_'; + } + } md->fstab->fs_spec = strdup(zpool_name); } else { md->fstab->fs_spec = malloc(strlen(name) + @@ -869,6 +893,7 @@ struct gconfig *gc; struct gconsumer *cp; struct ggeom *geom; + struct partition_metadata tmd, *md; const char *errstr, *scheme; char sizestr[32], startstr[32], output[64], *newpartname; char newfs[255], options_fstype[64]; @@ -968,7 +993,8 @@ /* Default options */ strncpy(options_fstype, items[0].text, sizeof(options_fstype)); - newfs_command(options_fstype, newfs, 1); + tmd.fstype = options_fstype; + newfs_command(&tmd, newfs, 1); addpartform: if (interactive) { dialog_vars.extra_label = "Options"; @@ -984,7 +1010,8 @@ case 3: /* Options */ strncpy(options_fstype, items[0].text, sizeof(options_fstype)); - newfs_command(options_fstype, newfs, 0); + tmd.fstype = options_fstype; + newfs_command(&tmd, newfs, 0); goto addpartform; } } @@ -995,7 +1022,8 @@ */ if (strcmp(options_fstype, items[0].text) != 0) { strncpy(options_fstype, items[0].text, sizeof(options_fstype)); - newfs_command(options_fstype, newfs, 1); + tmd.fstype = options_fstype; + newfs_command(&tmd, newfs, 1); } size = maxsize; @@ -1169,8 +1197,13 @@ gctl_issue(r); /* Error usually expected and non-fatal */ gctl_free(r); + md = get_part_metadata(newpartname, 1); + md->bootenv = tmd.bootenv; + if (md->fstype != NULL) + free(md->fstype); + md->fstype = strdup(tmd.fstype); if (strcmp(items[0].text, bootpart_type(scheme)) == 0) - get_part_metadata(newpartname, 1)->bootcode = 1; + md->bootcode = 1; else if (strcmp(items[0].text, "freebsd") == 0) gpart_partition(newpartname, "BSD"); else Index: usr.sbin/bsdinstall/partedit/partedit.h =================================================================== --- usr.sbin/bsdinstall/partedit/partedit.h +++ usr.sbin/bsdinstall/partedit/partedit.h @@ -44,8 +44,11 @@ char *name; /* name of this partition, as in GEOM */ struct fstab *fstab; /* fstab data for this partition */ + char *fstype; /* the type of the file system */ char *newfs; /* shell command to initialize partition */ + char *poolname; /* setup ZFS boot environments */ + int bootenv; int bootcode; TAILQ_ENTRY(partition_metadata) metadata; Index: usr.sbin/bsdinstall/partedit/partedit.c =================================================================== --- usr.sbin/bsdinstall/partedit/partedit.c +++ usr.sbin/bsdinstall/partedit/partedit.c @@ -42,6 +42,22 @@ struct pmetadata_head part_metadata; static int sade_mode = 0; +static const char *zfs_be_datasets[] = { + "zfs create -o mountpoint=none %s/ROOT", + "zfs create -o mountpoint=/ %s/ROOT/default", + "zfs create -o mountpoint=/tmp -o exec=on -o setuid=off %s/tmp", + "zfs create -o mountpoint=/usr -o canmount=off %s/usr", + "zfs create %s/usr/home", + "zfs create -o setuid=off %s/usr/ports", + "zfs create %s/usr/src", + "zfs create -o mountpoint=/var -o canmount=off %s/var", + "zfs create -o exec=off -o setuid=off %s/var/audit", + "zfs create -o exec=off -o setuid=off %s/var/crash", + "zfs create -o exec=off -o setuid=off %s/var/log", + "zfs create -o atime=on %s/var/mail", + "zfs create -o setuid=off %s/var/tmp", + NULL, +}; static int apply_changes(struct gmesh *mesh); static void apply_workaround(struct gmesh *mesh); @@ -158,8 +174,12 @@ free(md->fstab->fs_type); free(md->fstab); } + if (md->fstype != NULL) + free(md->poolname); if (md->newfs != NULL) free(md->newfs); + if (md->poolname != NULL) + free(md->poolname); free(md->name); TAILQ_REMOVE(&part_metadata, md, metadata); @@ -208,6 +228,8 @@ error = geom_gettree(&mesh); if (validate_setup()) { error = apply_changes(&mesh); + if (!error) + apply_workaround(&mesh); } else { gpart_revert_all(&mesh); error = -1; @@ -254,8 +276,12 @@ free(md->fstab->fs_type); free(md->fstab); } + if (md->fstype != NULL) + free(md->fstype); if (md->newfs != NULL) free(md->newfs); + if (md->poolname != NULL) + free(md->poolname); free(md->name); TAILQ_REMOVE(&part_metadata, md, metadata); @@ -274,6 +300,8 @@ TAILQ_FOREACH(md, &part_metadata, metadata) { if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) root = md; + else if (md->bootenv == 1) + root = md; /* XXX: Check for duplicate mountpoints */ } @@ -310,11 +338,12 @@ apply_changes(struct gmesh *mesh) { struct partition_metadata *md; - char message[512]; + char message[512], zfscommand[512], *rcconf_path; int i, nitems, error; + size_t z; const char **items; const char *fstab_path; - FILE *fstab; + FILE *fstab, *rcconf; nitems = 1; /* Partition table changes */ TAILQ_FOREACH(md, &part_metadata, metadata) { @@ -357,6 +386,39 @@ md->newfs, md->newfs, getenv("BSDINSTALL_LOG"), getenv("BSDINSTALL_LOG")); error = system(message); + if (md->bootenv == 1) { + for (z = 0; zfs_be_datasets[z] != NULL; z++) { + if (error != 0) + break; + sprintf(zfscommand, zfs_be_datasets[z], + md->poolname); + sprintf(message, "(echo %s; %s) >>%s 2>>%s", + zfscommand, zfscommand, + getenv("BSDINSTALL_LOG"), + getenv("BSDINSTALL_LOG")); + error = system(message); + } + if (error == 0) { + sprintf(zfscommand, + "zfs set mountpoint=/%s %s", + md->poolname, md->poolname); + sprintf(message, "(echo %s; %s) >>%s 2>>%s", + zfscommand, zfscommand, + getenv("BSDINSTALL_LOG"), + getenv("BSDINSTALL_LOG")); + error = system(message); + } + if (error == 0) { + sprintf(zfscommand, + "zpool set bootfs=%s/ROOT/default %s", + md->poolname, md->poolname); + sprintf(message, "(echo %s; %s) >>%s 2>>%s", + zfscommand, zfscommand, + getenv("BSDINSTALL_LOG"), + getenv("BSDINSTALL_LOG")); + error = system(message); + } + } items[i*2 + 1] = (error == 0) ? "3" : "1"; i++; } @@ -390,6 +452,29 @@ } fclose(fstab); + TAILQ_FOREACH(md, &part_metadata, metadata) { + if (md->fstype != NULL && strcmp(md->fstype, "freebsd-zfs") == 0) { + if (getenv("BSDINSTALL_TMPETC") != NULL) + asprintf(&rcconf_path, "%s/rc.conf.zfs", + getenv("BSDINSTALL_TMPETC")); + else + rcconf_path = "/etc/rc.conf"; + rcconf = fopen(rcconf_path, "w+"); + if (rcconf == NULL) { + sprintf(message, "Cannot open rc.conf file %s " + "for writing (%s)\n", rcconf_path, + strerror(errno)); + dialog_msgbox("Error", message, 0, 0, TRUE); + return (-1); + } + if (fseek(rcconf, 0, SEEK_END) == 0) { + fprintf(rcconf, "\nzfs_enable=\"YES\"\n"); + } + fclose(rcconf); + break; /* Only need to add the entry once */ + } + } + return (0); } Index: usr.sbin/bsdinstall/partedit/partedit_x86.c =================================================================== --- usr.sbin/bsdinstall/partedit/partedit_x86.c +++ usr.sbin/bsdinstall/partedit/partedit_x86.c @@ -80,9 +80,7 @@ if (strcmp(fs, "freebsd-ufs") == 0) return (1); - if (strcmp(fs, "freebsd-zfs") == 0 && - strcmp(part_type, "GPT") == 0 && - strcmp(x86_bootmethod(), "BIOS") == 0) + if (strcmp(fs, "freebsd-zfs") == 0 && strcmp(part_type, "GPT") == 0) return (1); return (0);