Created
April 8, 2013 13:39
-
-
Save sathlan/5336814 to your computer and use it in GitHub Desktop.
modification to mfsbsd zfsinstall to take into account ssd alignment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
IP_PREFIX='10.11.12' | |
help () { | |
cat<<EOF | |
USAGE: $0 [-h] -i LAST_BLOCK_IP -m CIDR -v VLAN -n NAME | |
DESCRIPTION: | |
Simple wrapper around the creation of a new jails with | |
some default. | |
LAST_BLOCK_IP in XXX.XXX.XXX.YYY is YYY. The current | |
ip prefix is $IP_PREFIX | |
EOF | |
} | |
net_exists () { | |
ifconfig -l | grep -q $1 | |
} | |
add_network() { | |
TAP=tap${IP} | |
net_exists ${TAP} || ifconfig ${TAP} create up | |
net_exists ${TAP}.${VLAN} || ifconfig ${TAP}.${VLAN} create \ | |
vlan ${VLAN} vlandev ${TAP} up | |
BDG=bridge${VLAN} | |
net_exists $BDG || ifconfig $BDG create up | |
ifconfig bridge${VLAN} addm ${TAP}.${VLAN} | |
} | |
add_jail() { | |
ezjail-admin create -f `hostname -s` -c zfs $NAME "tap${IP}.${VLAN}|${IP_PREFIX}.${IP}/${MASK}" | |
/usr/local/etc/rc.d/ezjail start $NAME | |
} | |
while getopts :hi:v:n:m: OPT; do | |
case $OPT in | |
h|+h) | |
help | |
exit 0 | |
;; | |
i|+i) | |
IP="$OPTARG" | |
;; | |
v|+v) | |
VLAN="$OPTARG" | |
;; | |
n|+n) | |
NAME="$OPTARG" | |
;; | |
m|+m) | |
MASK="$OPTARG" | |
;; | |
*) | |
help | |
exit 2 | |
esac | |
done | |
shift `expr $OPTIND - 1` | |
OPTIND=1 | |
if [ -z "$IP" -o -z "$VLAN" -o -z "$NAME" -o -z "$MASK" ]; then | |
echo "Missing argument." >&2 | |
help | |
exit 4 | |
fi | |
add_network | |
add_jail | |
jls | |
echo ezjail-admin console $NAME |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# $Id$ | |
# | |
# mfsBSD ZFS install script | |
# Copyright (c) 2011 Martin Matuska <mm at FreeBSD.org> | |
# | |
FS_LIST="var tmp" | |
# SSD page size (or sector size) in byte. | |
usage() { | |
echo "Usage: $0 [-h] -d geom_provider [-d geom_provider ...] [-r mirror|raidz] [-m mount_point] [-p zfs_pool_name] [-V zfs_pool_version] [-s swap_partition_size] [-z zfs_partition_size] [-c] [-l] [-4]" | |
} | |
help() { | |
echo; echo "Install FreeBSD using ZFS" | |
echo; echo "Required flags:" | |
echo "-d geom_provider : geom provider(s) to install to (e.g. da0)" | |
echo " supported compression formats are: gzip, bzip2, xz" | |
echo; echo "Optional flags:" | |
echo "-r raidz|mirror : select raid mode if more than one -d provider given" | |
echo "-s swap_part_size : create a swap partition with given size (default: no swap)" | |
echo "-z zfs_part_size : create zfs parition of this size (default: all space left)" | |
echo "-p pool_name : specify a name for the ZFS pool (default: tank)" | |
echo "-V pool_version : specify a version number for ZFS pool (default: 13)" | |
echo "-m mount_point : use this mount point for operations (default: /mnt)" | |
echo "-c : enable lzjb compression for all datasets" | |
echo "-l : use legacy mounts (via fstab) instead of ZFS mounts" | |
echo "-4 : use fletcher4 as default checksum algorithm" | |
echo "-a alignment : specify alignment for disk creation" | |
echo; echo "Examples:" | |
echo "Install on a single drive with 2GB swap:" | |
echo "$0 -d ad4 -s 2G" | |
echo "Install on a mirror without swap, pool name rpool:" | |
echo "$0 -d ad4 -d ad6 -r mirror -p rpool" | |
echo; echo "Notes:" | |
echo "When using swap and raidz/mirror, the swap partition is created on all drives." | |
echo "The /etc/fstab entry will contatin only the first drive's swap partition." | |
echo "You can enable all swap partitions and/or make a gmirror-ed swap later." | |
} | |
while getopts d:r:p:s:z:m:V:hcl4S: o; do | |
case "$o" in | |
d) DEVS="$DEVS ${OPTARG##/dev/}" ;; | |
p) POOL="${OPTARG}" ;; | |
s) SWAP="${OPTARG}" ;; | |
m) MNT="${OPTARG}" ;; | |
r) RAID="${OPTARG}" ;; | |
z) ZPART="${OPTARG}" ;; | |
V) VERSION="${OPTARG}" ;; | |
S) SECTOR="${OPTARG}" ;; | |
a) ALIGN="${OPTARG}" ;; | |
c) LZJB=1 ;; | |
l) LEGACY=1 ;; | |
4) FLETCHER=1 ;; | |
h) help; exit 1;; | |
[?]) usage; exit 1;; | |
esac | |
done | |
if ! `/sbin/kldstat -m zfs >/dev/null 2>/dev/null`; then | |
/sbin/kldload zfs >/dev/null 2>/dev/null | |
fi | |
ZFS_VERSION=`/sbin/sysctl -n vfs.zfs.version.spa 2>/dev/null` | |
if [ -z "$ZFS_VERSION" ]; then | |
echo "Error: failed to load ZFS module" | |
exit 1 | |
elif [ "$ZFS_VERSION" -lt "13" ]; then | |
echo "Error: ZFS module too old, version 13 or higher required" | |
exit 1 | |
fi | |
if [ -z "$DEVS" ]; then | |
usage | |
exit 1 | |
fi | |
if [ -z "$POOL" ]; then | |
POOL=tank | |
fi | |
if [ -z "$VERSION" ]; then | |
VERSION=${ZFS_VERSION} | |
elif [ "$VERSION" -gt "$ZFS_VERSION" ]; then | |
echo "Error: invalid ZFS pool version (maximum: $ZFS_VERSION)" | |
exit 1 | |
fi | |
if [ "$VERSION" = "5000" ]; then | |
VERSION= | |
else | |
VERSION="-o version=${VERSION}" | |
fi | |
if /sbin/zpool list $POOL > /dev/null 2> /dev/null; then | |
echo Error: ZFS pool \"$POOL\" already exists | |
echo Please choose another pool name or rename/destroy the existing pool. | |
exit 1 | |
fi | |
EXPOOLS=`/sbin/zpool import | /usr/bin/grep pool: | /usr/bin/awk '{ print $2 }'` | |
if [ -n "${EXPOOLS}" ]; then | |
for P in ${EXPOOLS}; do | |
if [ "$P" = "$POOL" ]; then | |
echo Error: An exported ZFS pool \"$POOL\" already exists | |
echo Please choose another pool name or rename/destroy the exported pool. | |
exit 1 | |
fi | |
done | |
fi | |
COUNT=`echo ${DEVS} | /usr/bin/wc -w | /usr/bin/awk '{ print $1 }'` | |
if [ "$COUNT" -lt "3" -a "$RAID" = "raidz" ]; then | |
echo "Error: raidz needs at least three devices (-d switch)" | |
exit 1 | |
elif [ "$COUNT" = "1" -a "$RAID" = "mirror" ]; then | |
echo "Error: mirror needs at least two devices (-d switch)" | |
exit 1 | |
elif [ "$COUNT" = "2" -a "$RAID" != "mirror" ]; then | |
echo "Notice: two drives selected, automatically choosing mirror mode" | |
RAID="mirror" | |
elif [ "$COUNT" -gt "2" -a "$RAID" != "mirror" -a "$RAID" != "raidz" ]; then | |
echo "Error: please choose raid mode with the -r switch (mirror or raidz)" | |
exit 1 | |
fi | |
for DEV in ${DEVS}; do | |
if ! [ -c "/dev/${DEV}" ]; then | |
echo "Error: /dev/${DEV} is not a block device" | |
exit 1 | |
fi | |
if /sbin/gpart show $DEV > /dev/null 2> /dev/null; then | |
echo "Error: /dev/${DEV} already contains a partition table." | |
echo "" | |
/sbin/gpart show $DEV | |
echo "You may erase the partition table manually with the destroygeom command" | |
exit 1 | |
fi | |
done | |
if [ -z "$MNT" ]; then | |
MNT=/mnt | |
fi | |
if ! [ -d "${MNT}" ]; then | |
echo "Error: $MNT is not a directory" | |
exit 1 | |
fi | |
if [ -n "${ZPART}" ]; then | |
SZPART="-s ${ZPART}" | |
fi | |
if [ "${LEGACY}" = "1" ]; then | |
ALTROOT= | |
ROOTMNT=legacy | |
else | |
# / is mounted readonly | |
mkdir -p /var/zfs | |
ALTROOT="-o altroot=${MNT} -o cachefile=/var/zfs/zpool.cache" | |
ROOTMNT=/ | |
fi | |
# Create GPT | |
for DEV in ${DEVS}; do | |
echo -n "Creating GUID partitions on ${DEV} ..." | |
# size is in byte. See the comment to freebsd-ufs for the | |
# rational. | |
size_available=`diskinfo /dev/${DEV} | awk '{print $3}'` | |
size_free=$(( $size_available * 90 / 100 )) | |
sector_size=`diskinfo /dev/${DEV} | awk '{print $2}'` | |
# ALIGN should divisible by what the system thinks is the | |
# sector size or else there is a problem. | |
if [ $(($ALIGN % $sector_size)) -ne 0 ]; then | |
echo " error, align value \"$ALIGN\" is not divisible by sector size \"$sector_size\"." | |
exit 1 | |
else | |
# alignment in gpart add is in number of block of whatever | |
# it believes to be the block size. Here, my problem is | |
# that the SSD is reporting a invalid block size of 512b. | |
# To have a 8kb alignment (which is the real sector size | |
# of my SSD - crucial M4 256M, according to | |
# http://www.hardware.fr/articles/830-2/crucial-m4-128-go-256-go-test.html | |
# - ), I must use 8192/512=16 as option to gpart add. | |
# With 8196 passed to gpart add, I get a 4Mb alignment, as | |
# 8192*512=4Mb. For gnop, the sector size argument is in | |
# byte so there is no problem. | |
# Now ... I can certainly pass "-a ${ALIGN}b" to "gpart | |
# add" with SI unit suffix, but all this calculus make a | |
# good verification that the value is valid. | |
GPART_ALIGN=$(($ALIGN / $sector_size)) | |
fi | |
if ! /sbin/gpart create -s GPT /dev/${DEV} > /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
/bin/sleep 1 | |
# if ! echo "a 1" | /sbin/fdisk -f - ${DEV} > /dev/null 2> /dev/null; then | |
# echo " error" | |
# exit 1 | |
# fi | |
# get block of 512Kb ? | |
# 96 * 512 = 49152 is aligned with 8Kb block | |
# 32 * 512 = 16384 is aligned with 8Kb block | |
# 65536 = 96*512 + 32*512 is aligned with 8Kb block | |
if ! /sbin/gpart add -t freebsd-boot -a ${GPART_ALIGN} -b 16384b -s 49152b ${DEV} > /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
if [ -n "${SWAP}" ]; then | |
if ! /sbin/gpart add -t freebsd-swap -a ${GPART_ALIGN} -s "${SWAP}" ${DEV} > /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
SWAPPART=`/sbin/glabel status ${DEV}p2 | /usr/bin/grep gptid | /usr/bin/awk '{ print $1 }'` | |
if [ -z "$SWAPPART" ]; then | |
echo " error determining swap partition" | |
fi | |
if [ -z "$FSWAP" ]; then | |
FSWAP=${SWAPPART} | |
fi | |
fi | |
if ! /sbin/gpart add -t freebsd-zfs -a ${GPART_ALIGN} -s ${size_free}b ${DEV} > /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
# add a ufs partition to send the trim command on 10% of the | |
# disk to improve ssd performance, until this patch | |
# http://svnweb.freebsd.org/base?view=revision&revision=240868 | |
# is backported or upgrade to 10 | |
if ! /sbin/gpart add -t freebsd-ufs -a ${GPART_ALIGN} ${DEV} > /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
if ! bsdlabel -w ${DEV}p3 ; then | |
echo " error: could not write bsd partitions" | |
exit 1 | |
fi | |
if ! newfs -O1 -m0 -L 'trim' -n -t ${DEV}p3a; then | |
echo " error: could not format bsd partition" | |
exit 1 | |
fi | |
if ! mkdir -p /tmp/ufs-trim; then | |
echo " error, could not create trim mount point" | |
exit 1 | |
fi | |
if ! mount -t ufs /dev/${DEV}p3a /tmp/ufs-trim; then | |
echo " error, could not mount trim partition" | |
exit 1 | |
fi | |
dd if=/dev/zero of=/tmp/ufs-trim/to-be-removed-and-send-trim bs=$ALIGN | |
# send the trim command! | |
sync | |
rm -f /tmp/ufs-trim/to-be-removed-and-send-trim | |
# /bin/dd if=/dev/zero of=/dev/${DEV}p2 bs=512 count=560 > /dev/null 2> /dev/null | |
# if [ -n "${SWAP}" ]; then | |
# /bin/dd if=/dev/zero of=/dev/${DEV}p3 bs=512 count=560 > /dev/null 2> /dev/null | |
# fi | |
echo " done" | |
echo -n "Configuring ZFS bootcode on ${DEV} ..." | |
if ! /sbin/gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${DEV} > /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
echo " done" | |
/sbin/gpart show ${DEV} | |
done | |
# Create zpool and zfs | |
for DEV in ${DEVS}; do | |
PART=`/sbin/gpart show ${DEV} | /usr/bin/grep freebsd-zfs | /usr/bin/awk '{ print $3 }'` | |
if [ -z "${PART}" ]; then | |
echo Error: freebsd-zfs partition not found on /dev/$DEV | |
exit 1 | |
fi | |
GPART=`/sbin/glabel list ${DEV}p${PART} | /usr/bin/grep gptid | /usr/bin/awk -F"gptid/" '{ print "gptid/" $2 }'` | |
GPARTS="${GPARTS} ${GPART}" | |
PARTS="${PARTS} ${DEV}p${PART}" | |
done | |
# align for 8k block (crucial m4 >= 256M) | |
for part in ${PARTS}; do | |
if ! /sbin/gnop create -S ${ALIGN} ${part}; then | |
echo " error creating nop partition ${part}" | |
fi | |
PARTS_NOP=" $PARTS_NOP ${part}.nop" | |
done | |
echo -n "Creating ZFS pool ${POOL} on${PARTS_NOP} ..." | |
if ! /sbin/zpool create -f -m none ${ALTROOT} ${VERSION} ${POOL} ${RAID} ${PARTS_NOP} > /dev/null 2> /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
echo " done" | |
if [ "${FLETCHER}" = "1" ]; then | |
echo -n "Setting default checksum to fletcher4 for ${POOL} ..." | |
if ! /sbin/zfs set checksum=fletcher4 ${POOL} > /dev/null 2> /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
echo " done" | |
fi | |
if [ "${LZJB}" = "1" ]; then | |
echo -n "Setting default compression to lzjb for ${POOL} ..." | |
if ! /sbin/zfs set compression=lzjb ${POOL} > /dev/null 2> /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
echo " done" | |
fi | |
echo -n "Creating ${POOL} root partition:" | |
if ! /sbin/zfs create -o mountpoint=${ROOTMNT} ${POOL}/root > /dev/null 2> /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
echo " ... done" | |
echo -n "Creating ${POOL} partitions:" | |
for FS in ${FS_LIST}; do | |
if [ "${LEGACY}" = 1 ]; then | |
MNTPT="-o mountpoint=legacy" | |
else | |
MNTPT= | |
fi | |
# if ! /sbin/zfus create ${MNTPT} ${POOL}/root/${FS} > /dev/null 2> /dev/null; then | |
# echo " error" | |
# exit 1 | |
# fi | |
# echo -n " ${FS}" | |
done | |
zfs create -o compression=on -o exec=on -o setuid=off ${POOL}/root/tmp | |
zfs create ${POOL}/root/usr | |
zfs create ${POOL}/root/usr/home | |
zfs create -o compression=lzjb -o setuid=off ${POOL}/root/usr/ports | |
zfs create -o compression=off -o exec=off -o setuid=off ${POOL}/root/usr/ports/distfiles | |
zfs create -o compression=off -o exec=off -o setuid=off ${POOL}/root/usr/ports/packages | |
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL}/root/usr/src | |
zfs create ${POOL}/root/var | |
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL}/root/var/crash | |
zfs create -o exec=off -o setuid=off ${POOL}/root/var/db | |
zfs create -o compression=lzjb -o exec=on -o setuid=off ${POOL}/root/var/db/pkg | |
zfs create -o exec=off -o setuid=off ${POOL}/root/var/empty | |
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL}/root/var/log | |
zfs create -o compression=gzip -o exec=off -o setuid=off ${POOL}/root/var/mail | |
zfs create -o exec=off -o setuid=off ${POOL}/root/var/run | |
zfs create -o compression=lzjb -o exec=on -o setuid=off ${POOL}/root/var/tmp | |
chmod 1777 /${MNT}/var/tmp | |
echo " ... done" | |
echo -n "Setting bootfs for ${POOL} to ${POOL}/root ..." | |
if ! /sbin/zpool set bootfs=${POOL}/root ${POOL} > /dev/null 2> /dev/null; then | |
echo " error" | |
exit 1 | |
fi | |
echo " done" | |
/sbin/zfs list -r ${POOL} | |
# Mount and populate zfs (if legacy) | |
if [ "${LEGACY}" = "1" ]; then | |
echo -n "Mounting ${POOL} on ${MNT} ..." | |
/bin/mkdir -p ${MNT} | |
if ! /sbin/mount -t zfs ${POOL}/root ${MNT} > /dev/null 2> /dev/null; then | |
echo " error mounting pool/root" | |
exit 1 | |
fi | |
for FS in ${FS_LIST}; do | |
/bin/mkdir -p ${MNT}/${FS} | |
if ! /sbin/mount -t zfs ${POOL}/root/${FS} ${MNT}/${FS} > /dev/null 2> /dev/null; then | |
echo " error mounting ${POOL}/root/${FS}" | |
exit 1 | |
fi | |
done | |
echo " done" | |
fi | |
echo -n "Extracting FreeBSD distribution ..." | |
# https://calomel.org/zfs_freebsd_root_install.html | |
cd /usr/freebsd-dist | |
export DESTDIR=${MNT} | |
for file in base.txz lib32.txz kernel.txz doc.txz ports.txz src.txz; do | |
(cat $file | tar --unlink -xpJf - -C ${DESTDIR:-/}); | |
done | |
echo " done" | |
# Adjust configuration files | |
echo -n "Writing /boot/loader.conf..." | |
echo "zfs_load=\"YES\"" > ${MNT}/boot/loader.conf | |
echo "vfs.root.mountfrom=\"zfs:${POOL}/root\"" >> ${MNT}/boot/loader.conf | |
echo " done" | |
# Write fstab if swap or legacy | |
echo -n "Writing /etc/fstab..." | |
rm -f ${MNT}/etc/fstab | |
touch ${MNT}/etc/fstab | |
if [ -n "${FSWAP}" -o "${LEGACY}" = "1" ]; then | |
if [ -n "${FSWAP}" ]; then | |
echo "/dev/${FSWAP} none swap sw 0 0" > ${MNT}/etc/fstab | |
fi | |
if [ "${LEGACY}" = "1" ]; then | |
for FS in ${FS_LIST}; do | |
echo ${POOL}/root/${FS} /${FS} zfs rw 0 0 >> ${MNT}/etc/fstab | |
done | |
fi | |
fi | |
if [ "${LEGACY}" != "1" ]; then | |
echo -n "Writing /etc/rc.conf..." | |
echo 'zfs_enable="YES"' >> ${MNT}/etc/rc.conf | |
fi | |
echo " done" | |
echo -n "Copying /var/zfs/zpool.cache ..." | |
if [ -n "${LEGACY}" ]; then | |
for FS in ${FS_LIST}; do | |
/sbin/umount ${MNT}/${FS} > /dev/null 2> /dev/null | |
done | |
/sbin/umount ${MNT} > /dev/null 2> /dev/null | |
fi | |
if ! /sbin/zpool export ${POOL} > /dev/null 2> /dev/null; then | |
echo " error exporting pool" | |
exit 1 | |
fi | |
for part in ${PARTS_NOP}; do | |
if ! /sbin/gnop destroy ${part}; then | |
echo " error deleting nop ${part}" | |
fi | |
done | |
if ! /sbin/zpool import ${ALTROOT} ${POOL} > /dev/null 2> /dev/null; then | |
echo " error importing pool" | |
exit 1 | |
fi | |
if [ -n "${LEGACY}" ]; then | |
if ! /sbin/mount -t zfs ${POOL}/root ${MNT} > /dev/null 2> /dev/null; then | |
echo " error mounting ${POOL}/root" | |
exit 1 | |
fi | |
fi | |
if ! /bin/cp /var/zfs/zpool.cache ${MNT}/boot/zfs/ > /dev/null 2> /dev/null; then | |
echo " error copying zpool.cache" | |
exit 1 | |
fi | |
if [ -n "${LEGACY}" ]; then | |
for FS in ${FS_LIST}; do | |
if ! /sbin/mount -t zfs ${POOL}/${FS} ${MNT}/${FS} > /dev/null 2> /dev/null; then | |
echo " error mounting ${POOL}/${FS}" | |
exit 1 | |
fi | |
done | |
fi | |
echo " done" | |
# Mount devfs for post-configuration | |
if ! /sbin/mount -t devfs devfs ${MNT}/dev; then | |
echo "Error mounting devfs on ${MNT}/dev" | |
fi | |
echo "Copying packages ...." | |
mkdir -p /usr/ports/packages | |
if ! cp -ap /packages/* /usr/ports/packages; then | |
echo " error copying packages" | |
exit 1 | |
fi | |
echo "Installing specific configurations ...." | |
if ! tar -C ${MNT} -x -z -f /usr/freebsd-usr/confs.tar.gz; then | |
echo " error installing configurations" | |
exit 1 | |
fi | |
echo "" | |
echo "Installation complete." | |
echo "The system will boot from ZFS with clean install on next reboot" | |
echo "" | |
echo "You may type \"chroot ${MNT}\" and make any adjustments you need." | |
echo "For example, change the root password or edit/create /etc/rc.conf for" | |
echo "for system services. " | |
echo "" | |
echo "WARNING - Don't export ZFS pool \"${POOL}\"!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment