Add ZFS support to the bsdinstall partition editor and sade.

Submitted by:	Kurt Lidl (original version)
MFC after:	6 weeks
This commit is contained in:
Nathan Whitehorn 2014-09-13 18:24:54 +00:00
parent 299153b570
commit 6e15678a47
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=271539
13 changed files with 217 additions and 45 deletions

View File

@ -27,6 +27,7 @@
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <libutil.h>
#include <inttypes.h>
@ -119,6 +120,53 @@ newfs_command(const char *fstype, char *command, int use_default)
else if (strcmp(items[i].name, "TRIM") == 0)
strcat(command, "-t ");
}
} else if (strcmp(fstype, "freebsd-zfs") == 0) {
int i;
DIALOG_LISTITEM items[] = {
{"fletcher4", "checksum algorithm: fletcher4",
"Use fletcher4 for data integrity checking. "
"(default)", 1 },
{"fletcher2", "checksum algorithm: fletcher2",
"Use fletcher2 for data integrity checking. "
"(not recommended)", 0 },
{"sha256", "checksum algorithm: sha256",
"Use sha256 for data integrity checking. "
"(not recommended)", 0 },
{"atime", "Update atimes for files",
"Disable atime update", 0 },
};
if (!use_default) {
int choice;
choice = dlg_checklist("ZFS Options", "", 0, 0, 0,
sizeof(items)/sizeof(items[0]), items, NULL,
FLAG_CHECK, &i);
if (choice == 1) /* Cancel */
return;
}
strcpy(command, "zpool create -f -m none ");
if (getenv("BSDINSTALL_TMPBOOT") != NULL) {
char zfsboot_path[MAXPATHLEN];
sprintf(zfsboot_path, "%s/zfs",
getenv("BSDINSTALL_TMPBOOT"));
mkdir(zfsboot_path, S_IRWXU | S_IRGRP | S_IXGRP |
S_IROTH | S_IXOTH);
sprintf(command, "%s -o cachefile=%s/zpool.cache ",
command, zfsboot_path);
}
for (i = 0; i < (int)(sizeof(items)/sizeof(items[0])); i++) {
if (items[i].state == 0)
continue;
if (strcmp(items[i].name, "fletcher4") == 0)
strcat(command, "-O checksum=fletcher4 ");
else if (strcmp(items[i].name, "fletcher2") == 0)
strcat(command, "-O checksum=fletcher2 ");
else if (strcmp(items[i].name, "sha256") == 0)
strcat(command, "-O checksum=sha256 ");
else if (strcmp(items[i].name, "atime") == 0)
strcat(command, "-O atime=off ");
}
} else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0) {
int i;
DIALOG_LISTITEM items[] = {
@ -329,7 +377,7 @@ gpart_bootcode(struct ggeom *gp)
}
static void
gpart_partcode(struct gprovider *pp)
gpart_partcode(struct gprovider *pp, const char *fstype)
{
struct gconfig *gc;
const char *scheme;
@ -344,7 +392,7 @@ gpart_partcode(struct gprovider *pp)
}
/* Make sure this partition scheme needs partcode on this platform */
if (partcode_path(scheme) == NULL)
if (partcode_path(scheme, fstype) == NULL)
return;
LIST_FOREACH(gc, &pp->lg_config, lg_config) {
@ -356,7 +404,7 @@ gpart_partcode(struct gprovider *pp)
/* Shell out to gpart for partcode for now */
sprintf(command, "gpart bootcode -p %s -i %s %s",
partcode_path(scheme), indexstr, pp->lg_geom->lg_name);
partcode_path(scheme, fstype), indexstr, pp->lg_geom->lg_name);
if (system(command) != 0) {
sprintf(message, "Error installing partcode on partition %s",
pp->lg_name);
@ -416,15 +464,15 @@ gpart_edit(struct gprovider *pp)
const char *errstr, *oldtype, *scheme;
struct partition_metadata *md;
char sizestr[32];
char newfs[64];
char newfs[255];
intmax_t idx;
int hadlabel, choice, junk, nitems;
unsigned i;
DIALOG_FORMITEM items[] = {
{0, "Type:", 5, 0, 0, FALSE, "", 11, 0, 12, 15, 0,
FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-swap)",
FALSE},
FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
"freebsd-swap)", FALSE},
{0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 0, 0,
FALSE, "Partition size. Append K, M, G for kilobytes, "
"megabytes or gigabytes.", FALSE},
@ -565,6 +613,8 @@ set_default_part_metadata(const char *name, const char *scheme,
const char *type, const char *mountpoint, const char *newfs)
{
struct partition_metadata *md;
char *zpool_name = NULL;
int i;
/* Set part metadata */
md = get_part_metadata(name, 1);
@ -577,8 +627,18 @@ set_default_part_metadata(const char *name, const char *scheme,
if (newfs != NULL && newfs[0] != '\0') {
md->newfs = malloc(strlen(newfs) + strlen(" /dev/") +
strlen(name) + 1);
sprintf(md->newfs, "%s /dev/%s", newfs, name);
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,
zpool_name, name);
} else {
sprintf(md->newfs, "%s /dev/%s", newfs, name);
}
}
}
@ -587,8 +647,9 @@ set_default_part_metadata(const char *name, const char *scheme,
if (strcmp(type, bootpart_type(scheme)) == 0)
md->bootcode = 1;
/* VTOC8 needs partcode in UFS partitions */
if (strcmp(scheme, "VTOC8") == 0 && strcmp(type, "freebsd-ufs") == 0)
/* VTOC8 needs partcode at the start of partitions */
if (strcmp(scheme, "VTOC8") == 0 && (strcmp(type, "freebsd-ufs") == 0
|| strcmp(type, "freebsd-zfs") == 0))
md->bootcode = 1;
if (mountpoint == NULL || mountpoint[0] == '\0') {
@ -611,8 +672,13 @@ set_default_part_metadata(const char *name, const char *scheme,
free(md->fstab->fs_mntops);
free(md->fstab->fs_type);
}
md->fstab->fs_spec = malloc(strlen(name) + 6);
sprintf(md->fstab->fs_spec, "/dev/%s", name);
if (strcmp("freebsd-zfs", type) == 0) {
md->fstab->fs_spec = strdup(zpool_name);
} else {
md->fstab->fs_spec = malloc(strlen(name) +
strlen("/dev/") + 1);
sprintf(md->fstab->fs_spec, "/dev/%s", name);
}
md->fstab->fs_file = strdup(mountpoint);
/* Get VFS from text after freebsd-, if possible */
if (strncmp("freebsd-", type, 8) == 0)
@ -625,6 +691,10 @@ set_default_part_metadata(const char *name, const char *scheme,
md->fstab->fs_type = strdup(FSTAB_SW);
md->fstab->fs_freq = 0;
md->fstab->fs_passno = 0;
} else if (strcmp(type, "freebsd-zfs") == 0) {
md->fstab->fs_type = strdup(FSTAB_RW);
md->fstab->fs_freq = 0;
md->fstab->fs_passno = 0;
} else {
md->fstab->fs_type = strdup(FSTAB_RW);
if (strcmp(mountpoint, "/") == 0) {
@ -637,6 +707,9 @@ set_default_part_metadata(const char *name, const char *scheme,
}
md->fstab->fs_mntops = strdup(md->fstab->fs_type);
}
if (zpool_name != NULL)
free(zpool_name);
}
static
@ -748,7 +821,7 @@ gpart_create(struct gprovider *pp, char *default_type, char *default_size,
struct ggeom *geom;
const char *errstr, *scheme;
char sizestr[32], startstr[32], output[64], *newpartname;
char newfs[64], options_fstype[64];
char newfs[255], options_fstype[64];
intmax_t maxsize, size, sector, firstfree, stripe;
uint64_t bytes;
int nitems, choice, junk;
@ -756,8 +829,8 @@ gpart_create(struct gprovider *pp, char *default_type, char *default_size,
DIALOG_FORMITEM items[] = {
{0, "Type:", 5, 0, 0, FALSE, "freebsd-ufs", 11, 0, 12, 15, 0,
FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-swap)",
FALSE},
FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
"freebsd-swap)", FALSE},
{0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 15, 0,
FALSE, "Partition size. Append K, M, G for kilobytes, "
"megabytes or gigabytes.", FALSE},
@ -935,6 +1008,20 @@ gpart_create(struct gprovider *pp, char *default_type, char *default_size,
goto addpartform;
}
/* If this is the root partition, check that this fs is bootable */
if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
items[0].text)) {
char message[512];
sprintf(message, "This file system (%s) is not bootable "
"on this system. Are you sure you want to proceed?",
items[0].text);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
goto addpartform;
}
/*
* If this is the root partition, and we need a boot partition, ask
* the user to add one.
@ -1177,12 +1264,22 @@ gpart_commit(struct gmesh *mesh)
struct gctl_req *r;
const char *errstr;
const char *modified;
const char *rootfs;
LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
if (strcmp(classp->lg_name, "PART") == 0)
break;
}
/* Figure out what filesystem / uses */
rootfs = "ufs"; /* Assume ufs if nothing else present */
TAILQ_FOREACH(md, &part_metadata, metadata) {
if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) {
rootfs = md->fstab->fs_vfstype;
break;
}
}
if (strcmp(classp->lg_name, "PART") != 0) {
dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
return;
@ -1222,7 +1319,7 @@ gpart_commit(struct gmesh *mesh)
break;
if (cp == NULL) /* No sub-partitions */
gpart_partcode(pp);
gpart_partcode(pp, rootfs);
}
r = gctl_get_handle();

View File

@ -31,6 +31,9 @@
#include <libutil.h>
#include <inttypes.h>
#include <sys/sysctl.h>
#include <string.h>
#include <libgeom.h>
#include <dialog.h>
#include <dlg_keys.h>
@ -44,10 +47,16 @@ static char *boot_disk(struct gmesh *mesh);
static char *wizard_partition(struct gmesh *mesh, const char *disk);
int
part_wizard(void) {
part_wizard(const char *fsreq) {
int error;
struct gmesh mesh;
char *disk, *schemeroot;
const char *fstype;
if (fsreq != NULL)
fstype = fsreq;
else
fstype = "ufs";
startwizard:
error = geom_gettree(&mesh);
@ -70,11 +79,11 @@ part_wizard(void) {
dlg_put_backtitle();
error = geom_gettree(&mesh);
error = wizard_makeparts(&mesh, schemeroot, 1);
error = wizard_makeparts(&mesh, schemeroot, fstype, 1);
if (error)
goto startwizard;
free(schemeroot);
geom_deletetree(&mesh);
return (0);
@ -106,9 +115,9 @@ boot_disk(struct gmesh *mesh)
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
desc = type = NULL;
LIST_FOREACH(gc, &pp->lg_config, lg_config) {
if (strcmp(gc->lg_name, "type") == 0)
if (strcmp(gc->lg_name, "type") == 0)
type = gc->lg_val;
if (strcmp(gc->lg_name, "descr") == 0)
if (strcmp(gc->lg_name, "descr") == 0)
desc = gc->lg_val;
}
@ -200,7 +209,7 @@ wizard_partition(struct gmesh *mesh, const char *disk)
break;
if (classp != NULL) {
LIST_FOREACH(gpart, &classp->lg_geom, lg_geom)
LIST_FOREACH(gpart, &classp->lg_geom, lg_geom)
if (strcmp(gpart->lg_name, disk) == 0)
break;
}
@ -282,21 +291,29 @@ wizard_partition(struct gmesh *mesh, const char *disk)
}
int
wizard_makeparts(struct gmesh *mesh, const char *disk, int interactive)
wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype, int interactive)
{
struct gmesh submesh;
struct gclass *classp;
struct ggeom *gp;
struct gprovider *pp;
intmax_t swapsize, available;
char swapsizestr[10], rootsizestr[10];
char swapsizestr[10], rootsizestr[10], *fsname;
char *fsnames[] = {"freebsd-ufs", "freebsd-zfs"};
int retval;
if (strcmp(fstype, "zfs") == 0) {
fsname = fsnames[1];
} else {
/* default to UFS */
fsname = fsnames[0];
}
LIST_FOREACH(classp, &mesh->lg_class, lg_class)
if (strcmp(classp->lg_name, "PART") == 0)
break;
LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
if (strcmp(gp->lg_name, disk) == 0)
break;
@ -331,7 +348,7 @@ wizard_makeparts(struct gmesh *mesh, const char *disk, int interactive)
geom_gettree(&submesh);
pp = provider_for_name(&submesh, disk);
gpart_create(pp, "freebsd-ufs", rootsizestr, "/", NULL, 0);
gpart_create(pp, fsname, rootsizestr, "/", NULL, 0);
geom_deletetree(&submesh);
geom_gettree(&submesh);

View File

@ -95,7 +95,12 @@ main(int argc, const char **argv)
if (strcmp(basename(argv[0]), "autopart") == 0) { /* Guided */
prompt = "Please review the disk setup. When complete, press "
"the Finish button.";
part_wizard();
/* Experimental ZFS autopartition support */
if (argc > 1 && strcmp(argv[1], "zfs") == 0) {
part_wizard("zfs");
} else {
part_wizard("ufs");
}
} else if (strcmp(basename(argv[0]), "scriptedpart") == 0) {
error = scripted_editor(argc, argv);
prompt = NULL;
@ -162,7 +167,7 @@ main(int argc, const char **argv)
init_fstab_metadata();
break;
case 4: /* Auto */
part_wizard();
part_wizard("ufs");
break;
}

View File

@ -54,9 +54,10 @@ struct partition_metadata {
struct partition_metadata *get_part_metadata(const char *name, int create);
void delete_part_metadata(const char *name);
int part_wizard(void);
int part_wizard(const char *fstype);
int scripted_editor(int argc, const char **argv);
int wizard_makeparts(struct gmesh *mesh, const char *disk, int interactive);
int wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype,
int interactive);
/* gpart operations */
void gpart_delete(struct gprovider *pp);
@ -75,9 +76,10 @@ void set_default_part_metadata(const char *name, const char *scheme,
/* machine-dependent bootability checks */
const char *default_scheme(void);
int is_scheme_bootable(const char *scheme);
int is_fs_bootable(const char *scheme, const char *fs);
size_t bootpart_size(const char *scheme);
const char *bootpart_type(const char *scheme);
const char *bootcode_path(const char *scheme);
const char *partcode_path(const char *scheme);
const char *partcode_path(const char *scheme, const char *fs_type);
#endif

View File

@ -50,6 +50,11 @@ is_scheme_bootable(const char *part_type) {
return (1);
}
int
is_fs_bootable(const char *part_type, const char *fs) {
return (1);
}
/* No clue => no boot partition, bootcode, or partcode */
size_t
@ -68,7 +73,7 @@ bootcode_path(const char *part_type) {
}
const char *
partcode_path(const char *part_type) {
partcode_path(const char *part_type, const char *fs_type) {
return (NULL);
}

View File

@ -45,6 +45,15 @@ is_scheme_bootable(const char *part_type) {
return (0);
}
int
is_fs_bootable(const char *part_type, const char *fs)
{
if (strcmp(fs, "freebsd-ufs") == 0)
return (1);
return (0);
}
size_t
bootpart_size(const char *part_type) {
/* No boot partition */
@ -67,7 +76,7 @@ bootcode_path(const char *part_type) {
}
const char *
partcode_path(const char *part_type) {
partcode_path(const char *part_type, const char *fs_type) {
/* No partcode */
return (NULL);
}

View File

@ -67,6 +67,15 @@ is_scheme_bootable(const char *part_type) {
return (0);
}
int
is_fs_bootable(const char *part_type, const char *fs)
{
if (strcmp(fs, "freebsd-ufs") == 0)
return (1);
return (0);
}
size_t
bootpart_size(const char *part_type) {
size_t platlen = sizeof(platform);
@ -100,7 +109,7 @@ bootcode_path(const char *part_type) {
}
const char *
partcode_path(const char *part_type) {
partcode_path(const char *part_type, const char *fs_type) {
size_t platlen = sizeof(platform);
if (strlen(platform) == 0)
sysctlbyname("hw.platform", platform, &platlen, NULL, -1);

View File

@ -42,6 +42,15 @@ is_scheme_bootable(const char *part_type) {
return (0);
}
int
is_fs_bootable(const char *part_type, const char *fs)
{
if (strcmp(fs, "freebsd-ufs") == 0 || strcmp(fs, "freebsd-zfs") == 0)
return (1);
return (0);
}
size_t
bootpart_size(const char *part_type) {
/* No standalone boot partition */
@ -58,11 +67,16 @@ const char *
bootcode_path(const char *part_type) {
return (NULL);
}
const char *
partcode_path(const char *part_type) {
if (strcmp(part_type, "VTOC8") == 0)
return ("/boot/boot1");
partcode_path(const char *part_type, const char *fs_type) {
if (strcmp(part_type, "VTOC8") == 0) {
if (strcmp(fs_type, "ufs") == 0) {
return ("/boot/boot1");
} else if (strcmp(fs_type, "zfs") == 0) {
return ("/boot/zfsboot");
}
}
return (NULL);
}

View File

@ -58,6 +58,21 @@ is_scheme_bootable(const char *part_type) {
return (0);
}
int
is_fs_bootable(const char *part_type, const char *fs) {
size_t platlen = sizeof(platform);
if (strlen(platform) == 0)
sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
if (strcmp(fs, "freebsd-ufs") == 0)
return (1);
if (strcmp(fs, "freebsd-zfs") == 0 && strcmp(platform, "BIOS") == 0)
return (1);
return (0);
}
size_t
bootpart_size(const char *scheme) {
size_t platlen = sizeof(platform);
@ -107,7 +122,7 @@ bootcode_path(const char *part_type) {
}
const char *
partcode_path(const char *part_type) {
partcode_path(const char *part_type, const char *fs_type) {
size_t platlen = sizeof(platform);
if (strlen(platform) == 0)
sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
@ -115,6 +130,8 @@ partcode_path(const char *part_type) {
if (strcmp(part_type, "GPT") == 0) {
if (strcmp(platform, "UEFI") == 0)
return ("/boot/boot1.efifat");
else if (strcmp(fs_type, "zfs") == 0)
return ("/boot/gptzfsboot");
else
return ("/boot/gptboot");
}

View File

@ -68,7 +68,5 @@ with the equivalent part of
.Sh BUGS
The utility misses a lot of nice features, such as tools for
manipulating
.Xr gmirror 8
or
.Xr zfs 8 .
.Xr gmirror 8 .
These will be added later.

View File

@ -109,7 +109,7 @@ part_config(char *disk, const char *scheme, char *config)
/* Create partitions */
if (config == NULL) {
wizard_makeparts(&mesh, disk, 0);
wizard_makeparts(&mesh, disk, "ufs", 0);
goto finished;
}

View File

@ -36,6 +36,7 @@ cp $BSDINSTALL_TMPETC/* $BSDINSTALL_CHROOT/etc
cat $BSDINSTALL_TMPBOOT/loader.conf.* >> $BSDINSTALL_TMPBOOT/loader.conf
rm $BSDINSTALL_TMPBOOT/loader.conf.*
df -t zfs $BSDINSTALL_CHROOT > /dev/null && echo "zfs_load=\"YES\"" >> $BSDINSTALL_TMPBOOT/loader.conf
cp $BSDINSTALL_TMPBOOT/* $BSDINSTALL_CHROOT/boot

View File

@ -1272,8 +1272,6 @@ zfs_create_boot()
"$funcname"
f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_enable=\"YES\"' \
$BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE
f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_load=\"YES\"' \
$BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE
f_eval_catch $funcname echo "$ECHO_APPEND" \
'kern.geom.label.disk_ident.enable=\"0\"' \
$BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE