1#!/bin/sh 2#- 3# Copyright (c) 2010 iXsystems, Inc. All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24# SUCH DAMAGE. 25# 26# $FreeBSD$ 27 28# Functions related to disk operations using newfs 29 30 31# Function which performs the ZFS magic 32setup_zfs_filesystem() 33{ 34 PART="$1" 35 PARTFS="$2" 36 PARTMNT="$3" 37 EXT="$4" 38 PARTGEOM="$5" 39 ZPOOLOPTS="$6" 40 ROOTSLICE="`echo ${PART} | rev | cut -b 2- | rev`" 41 ZPOOLNAME=$(get_zpool_name "${PART}") 42 43 # Sleep a few moments, let the disk catch its breath 44 sleep 5 45 sync 46 47 # Check if we have multiple zfs mounts specified 48 for i in `echo ${PARTMNT} | sed 's|,| |g'` 49 do 50 # Check if we ended up with needing a zfs bootable partition 51 if [ "${i}" = "/" -o "${i}" = "/boot" ] 52 then 53 if [ "$HAVEBOOT" = "YES" ] ; then continue ; fi 54 if [ "${PARTGEOM}" = "MBR" ] ; then 55 # Lets stamp the proper ZFS boot loader 56 echo_log "Setting up ZFS boot loader support" 57 rc_halt "dd if=/boot/zfsboot of=${ROOTSLICE} count=1" 58 rc_halt "dd if=/boot/zfsboot of=${PART}${EXT} skip=1 seek=1024" 59 fi 60 fi 61 done 62 63 # Check if we have some custom zpool arguments and use them if so 64 if [ ! -z "${ZPOOLOPTS}" ] ; then 65 # Sort through devices and run gnop on them 66 local gnopDev="" 67 local newOpts="" 68 for i in $ZPOOLOPTS 69 do 70 echo "$i" | grep -q '/dev/' 71 if [ $? -eq 0 ] ; then 72 rc_halt "gnop create -S 4096 ${i}" 73 gnopDev="$gnopDev $i" 74 newOpts="$newOpts ${i}.nop" 75 else 76 newOpts="$newOpts $i" 77 fi 78 done 79 80 echo_log "Creating zpool ${ZPOOLNAME} with $newOpts" 81 rc_halt "zpool create -m none -f ${ZPOOLNAME} ${newOpts}" 82 83 # Export the pool 84 rc_halt "zpool export ${ZPOOLNAME}" 85 86 # Destroy the gnop devices 87 for i in $gnopDev 88 do 89 rc_halt "gnop destroy ${i}.nop" 90 done 91 92 # And lastly re-import the pool 93 rc_halt "zpool import ${ZPOOLNAME}" 94 else 95 # Lets do our pseudo-4k drive 96 rc_halt "gnop create -S 4096 ${PART}${EXT}" 97 98 # No zpool options, create pool on single device 99 echo_log "Creating zpool ${ZPOOLNAME} on ${PART}${EXT}" 100 rc_halt "zpool create -m none -f ${ZPOOLNAME} ${PART}${EXT}.nop" 101 102 # Finish up the gnop 4k trickery 103 rc_halt "zpool export ${ZPOOLNAME}" 104 rc_halt "gnop destroy ${PART}${EXT}.nop" 105 rc_halt "zpool import ${ZPOOLNAME}" 106 fi 107 108 # Disable atime for this zfs partition, speed increase 109 rc_nohalt "zfs set atime=off ${ZPOOLNAME}" 110 111 112 113}; 114 115# Runs newfs on all the partiions which we've setup with bsdlabel 116setup_filesystems() 117{ 118 119 # Create the keydir 120 rm -rf ${GELIKEYDIR} >/dev/null 2>/dev/null 121 mkdir ${GELIKEYDIR} 122 123 # Lets go ahead and read through the saved partitions we created, and determine if we need to run 124 # newfs on any of them 125 for PART in `ls ${PARTDIR}` 126 do 127 PARTDEV="`echo $PART | sed 's|-|/|g'`" 128 PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`" 129 PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`" 130 PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`" 131 PARTLABEL="`cat ${PARTDIR}/${PART} | cut -d '#' -f 4`" 132 PARTGEOM="`cat ${PARTDIR}/${PART} | cut -d '#' -f 5`" 133 PARTXTRAOPTS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 6`" 134 PARTIMAGE="`cat ${PARTDIR}/${PART} | cut -d '#' -f 7`" 135 136 if [ ! -e "${PARTDEV}" ] ; then 137 exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?" 138 fi 139 140 # Make sure journaling isn't enabled on this device 141 if [ -e "${PARTDEV}.journal" ] 142 then 143 rc_nohalt "gjournal stop -f ${PARTDEV}.journal" 144 rc_nohalt "gjournal clear ${PARTDEV}" 145 fi 146 147 # Setup encryption if necessary 148 if [ "${PARTENC}" = "ON" -a "${PARTFS}" != "SWAP" ] 149 then 150 echo_log "Creating geli provider for ${PARTDEV}" 151 152 if [ -e "${PARTDIR}-enc/${PART}-encpass" ] ; then 153 # Using a passphrase 154 rc_halt "dd if=/dev/random of=${GELIKEYDIR}/${PART}.key bs=64 count=1" 155 rc_halt "geli init -J ${PARTDIR}-enc/${PART}-encpass ${PARTDEV}" 156 rc_halt "geli attach -j ${PARTDIR}-enc/${PART}-encpass ${PARTDEV}" 157 else 158 # No Encryption password, use key file 159 rc_halt "dd if=/dev/random of=${GELIKEYDIR}/${PART}.key bs=64 count=1" 160 rc_halt "geli init -b -s 4096 -P -K ${GELIKEYDIR}/${PART}.key ${PARTDEV}" 161 rc_halt "geli attach -p -k ${GELIKEYDIR}/${PART}.key ${PARTDEV}" 162 163 fi 164 165 EXT=".eli" 166 else 167 # No Encryption 168 EXT="" 169 fi 170 171 case ${PARTFS} in 172 UFS) 173 echo_log "NEWFS: ${PARTDEV} - ${PARTFS}" 174 sleep 2 175 rc_halt "newfs -t ${PARTXTRAOPTS} ${PARTDEV}${EXT}" 176 sleep 2 177 rc_halt "sync" 178 rc_halt "glabel label ${PARTLABEL} ${PARTDEV}${EXT}" 179 rc_halt "sync" 180 181 # Set flag that we've found a boot partition 182 if [ "$PARTMNT" = "/boot" -o "${PARTMNT}" = "/" ] ; then 183 HAVEBOOT="YES" 184 fi 185 sleep 2 186 ;; 187 188 UFS+S) 189 echo_log "NEWFS: ${PARTDEV} - ${PARTFS}" 190 sleep 2 191 rc_halt "newfs -t ${PARTXTRAOPTS} -U ${PARTDEV}${EXT}" 192 sleep 2 193 rc_halt "sync" 194 rc_halt "glabel label ${PARTLABEL} ${PARTDEV}${EXT}" 195 rc_halt "sync" 196 # Set flag that we've found a boot partition 197 if [ "$PARTMNT" = "/boot" -o "${PARTMNT}" = "/" ] ; then 198 HAVEBOOT="YES" 199 fi 200 sleep 2 201 ;; 202 203 UFS+SUJ) 204 echo_log "NEWFS: ${PARTDEV} - ${PARTFS}" 205 sleep 2 206 rc_halt "newfs -t ${PARTXTRAOPTS} -U ${PARTDEV}${EXT}" 207 sleep 2 208 rc_halt "sync" 209 rc_halt "tunefs -j enable ${PARTDEV}${EXT}" 210 sleep 2 211 rc_halt "sync" 212 rc_halt "glabel label ${PARTLABEL} ${PARTDEV}${EXT}" 213 rc_halt "sync" 214 # Set flag that we've found a boot partition 215 if [ "$PARTMNT" = "/boot" -o "${PARTMNT}" = "/" ] ; then 216 HAVEBOOT="YES" 217 fi 218 sleep 2 219 ;; 220 221 222 UFS+J) 223 echo_log "NEWFS: ${PARTDEV} - ${PARTFS}" 224 sleep 2 225 rc_halt "newfs ${PARTDEV}${EXT}" 226 sleep 2 227 rc_halt "gjournal label -f ${PARTDEV}${EXT}" 228 sleep 2 229 rc_halt "newfs ${PARTXTRAOPTS} -O 2 -J ${PARTDEV}${EXT}.journal" 230 sleep 2 231 rc_halt "sync" 232 rc_halt "glabel label ${PARTLABEL} ${PARTDEV}${EXT}.journal" 233 rc_halt "sync" 234 # Set flag that we've found a boot partition 235 if [ "$PARTMNT" = "/boot" -o "${PARTMNT}" = "/" ] ; then 236 HAVEBOOT="YES" 237 fi 238 sleep 2 239 ;; 240 241 ZFS) 242 echo_log "NEWFS: ${PARTDEV} - ${PARTFS}" 243 setup_zfs_filesystem "${PARTDEV}" "${PARTFS}" "${PARTMNT}" "${EXT}" "${PARTGEOM}" "${PARTXTRAOPTS}" 244 ;; 245 246 SWAP) 247 rc_halt "sync" 248 rc_halt "glabel label ${PARTLABEL} ${PARTDEV}${EXT}" 249 rc_halt "sync" 250 sleep 2 251 ;; 252 253 IMAGE) 254 write_image "${PARTIMAGE}" "${PARTDEV}" 255 sleep 2 256 ;; 257 258 *) exit_err "ERROR: Got unknown file-system type $PARTFS" ;; 259 esac 260 261 done 262}; 263