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 gpart
29
30# See if device is a full disk or partition/slice
31is_disk()
32{
33  for _dsk in `sysctl -n kern.disks`
34  do
35    if [ "$_dsk" = "${1}" ] ; then return 0 ; fi
36  done
37
38  return 1
39}
40
41# Get a MBR partitions sysid
42get_partition_sysid_mbr()
43{
44  INPART="0"
45  DISK="$1"
46  PARTNUM=`echo ${2} | sed "s|${DISK}s||g"`
47  fdisk ${DISK} >${TMPDIR}/disk-${DISK} 2>/dev/null
48  while read i
49  do
50    echo "$i" | grep "The data for partition"  >/dev/null 2>/dev/null
51    if [ "$?" = "0" ] ; then
52       INPART="0"
53       PART="`echo ${i} | cut -d ' ' -f 5`"
54       if [ "$PART" = "$PARTNUM" ] ; then
55          INPART="1"
56       fi
57    fi
58
59    # In the partition section
60    if [ "$INPART" = "1" ] ; then
61       echo "$i" | grep "^sysid" >/dev/null 2>/dev/null
62       if [ "$?" = "0" ] ; then
63         SYSID="`echo ${i} | tr -s '\t' ' ' | cut -d ' ' -f 2`"
64         break
65       fi
66
67    fi
68
69  done < ${TMPDIR}/disk-${DISK}
70  rm ${TMPDIR}/disk-${DISK}
71
72  VAL="${SYSID}"
73  export VAL
74};
75
76# Get the partitions MBR label
77get_partition_label_mbr()
78{
79  INPART="0"
80  DISK="$1"
81  PARTNUM=`echo ${2} | sed "s|${DISK}s||g"`
82  fdisk ${DISK} >${TMPDIR}/disk-${DISK} 2>/dev/null
83  while read i
84  do
85    echo "$i" | grep "The data for partition"  >/dev/null 2>/dev/null
86    if [ "$?" = "0" ] ; then
87       INPART="0"
88       PART="`echo ${i} | cut -d ' ' -f 5`"
89       if [ "$PART" = "$PARTNUM" ] ; then
90          INPART="1"
91       fi
92    fi
93
94    # In the partition section
95    if [ "$INPART" = "1" ] ; then
96       echo "$i" | grep "^sysid" >/dev/null 2>/dev/null
97       if [ "$?" = "0" ] ; then
98         LABEL="`echo ${i} | tr -s '\t' ' ' | cut -d ',' -f 2-10`"
99         break
100       fi
101
102    fi
103
104  done < ${TMPDIR}/disk-${DISK}
105  rm ${TMPDIR}/disk-${DISK}
106
107  VAL="${LABEL}"
108  export VAL
109};
110
111# Get a GPT partitions label
112get_partition_label_gpt()
113{
114  DISK="${1}"
115  PARTNUM=`echo ${2} | sed "s|${DISK}p||g"`
116
117  gpart show ${DISK} >${TMPDIR}/disk-${DISK}
118  while read i
119  do
120     SLICE="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 3`"
121     if [ "${SLICE}" = "${PARTNUM}" ] ; then
122       LABEL="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 4`"
123       break
124     fi
125  done <${TMPDIR}/disk-${DISK}
126  rm ${TMPDIR}/disk-${DISK}
127
128  VAL="${LABEL}"
129  export VAL
130};
131
132# Get a partitions startblock
133get_partition_startblock()
134{
135  DISK="${1}"
136  PARTNUM=`echo ${2} | sed "s|${DISK}p||g" | sed "s|${DISK}s||g"`
137
138  gpart show ${DISK} >${TMPDIR}/disk-${DISK}
139  while read i
140  do
141     SLICE="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 3`"
142     if [ "$SLICE" = "${PARTNUM}" ] ; then
143       SB="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 1`"
144       break
145     fi
146  done <${TMPDIR}/disk-${DISK}
147  rm ${TMPDIR}/disk-${DISK}
148
149  VAL="${SB}"
150  export VAL
151};
152
153# Get a partitions blocksize
154get_partition_blocksize()
155{
156  DISK="${1}"
157  PARTNUM=`echo ${2} | sed "s|${DISK}p||g" | sed "s|${DISK}s||g"`
158
159  gpart show ${DISK} >${TMPDIR}/disk-${DISK}
160  while read i
161  do
162     SLICE="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 3`"
163     if [ "$SLICE" = "${PARTNUM}" ] ; then
164       BS="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 2`"
165       break
166     fi
167  done <${TMPDIR}/disk-${DISK}
168  rm ${TMPDIR}/disk-${DISK}
169
170  VAL="${BS}"
171  export VAL
172};
173
174# Function which returns the partitions on a target disk
175get_disk_partitions()
176{
177  gpart show ${1} >/dev/null 2>/dev/null
178  if [ "$?" != "0" ] ; then
179    VAL="" ; export VAL
180    return
181  fi
182
183  gpart show ${1} | grep "MBR" >/dev/null 2>/dev/null
184  if [ "$?" = "0" ] ; then
185    type="MBR"
186  else
187    type="GPT"
188  fi
189
190  SLICES="`gpart show ${1} | grep -v ${1} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 4 | sed '/^$/d'`"
191  for i in ${SLICES}
192  do
193    case $type in
194      MBR) name="${1}s${i}" ;;
195      GPT) name="${1}p${i}";;
196      *) name="${1}s${i}";;
197    esac
198    if [ -z "${RSLICES}" ]
199    then
200      RSLICES="${name}"
201    else
202      RSLICES="${RSLICES} ${name}"
203    fi
204  done
205
206  VAL="${RSLICES}" ; export VAL
207};
208
209# Function which returns a target disks cylinders
210get_disk_cyl()
211{
212  cyl=`diskinfo -v ${1} | grep "# Cylinders" | tr -s ' ' | cut -f 2`
213  VAL="${cyl}" ; export VAL
214};
215
216# Function which returns a target disks sectors
217get_disk_sectors()
218{
219  sec=`diskinfo -v ${1} | grep "# Sectors" | tr -s ' ' | cut -f 2`
220  VAL="${sec}" ; export VAL
221};
222
223# Function which returns a target disks heads
224get_disk_heads()
225{
226  head=`diskinfo -v ${1} | grep "# Heads" | tr -s ' ' | cut -f 2`
227  VAL="${head}" ; export VAL
228};
229
230# Function which returns a target disks mediasize in sectors
231get_disk_mediasize()
232{
233  mediasize=`diskinfo -v ${1} | grep "# mediasize in sectors" | tr -s ' ' | cut -f 2`
234  VAL="${mediasize}" ; export VAL
235};
236
237# Function which exports all zpools, making them safe to overwrite potentially
238export_all_zpools()
239{
240  # Export any zpools
241  for i in `zpool list -H -o name`
242  do
243    zpool export -f ${i}
244  done
245};
246
247# Function to delete all gparts before starting an install
248delete_all_gpart()
249{
250  echo_log "Deleting all gparts"
251  DISK="$1"
252
253  # Check for any swaps to stop
254  for i in `gpart show ${DISK} 2>/dev/null | grep 'freebsd-swap' | tr -s ' ' | cut -d ' ' -f 4`
255  do
256    swapoff /dev/${DISK}s${i}b >/dev/null 2>/dev/null
257    swapoff /dev/${DISK}p${i} >/dev/null 2>/dev/null
258  done
259
260  # Delete the gparts now
261  for i in `gpart show ${DISK} 2>/dev/null | tr -s ' ' | cut -d ' ' -f 4`
262  do
263   if [ "${i}" != "${DISK}" -a "${i}" != "-" ] ; then
264     rc_nohalt "gpart delete -i ${i} ${DISK}"
265   fi
266  done
267
268  rc_nohalt "dd if=/dev/zero of=/dev/${DISK} count=3000"
269
270};
271
272# Function to export all zpools before starting an install
273stop_all_zfs()
274{
275  # Export all zpools again, so that we can overwrite these partitions potentially
276  for i in `zpool list -H -o name`
277  do
278    zpool export -f ${i}
279  done
280};
281
282# Function which stops all gmirrors before doing any disk manipulation
283stop_all_gmirror()
284{
285  DISK="${1}"
286  GPROV="`gmirror list | grep ". Name: mirror/" | cut -d '/' -f 2`"
287  for gprov in $GPROV
288  do
289    gmirror list | grep "Name: ${DISK}" >/dev/null 2>/dev/null
290    if [ "$?" = "0" ]
291    then
292      echo_log "Stopping mirror $gprov $DISK"
293      rc_nohalt "gmirror remove $gprov $DISK"
294      rc_nohalt "dd if=/dev/zero of=/dev/${DISK} count=4096"
295    fi
296  done
297};
298
299# Make sure we don't have any geli providers active on this disk
300stop_all_geli()
301{
302  _geld="${1}"
303  cd /dev
304
305  for i in `ls ${_geld}*`
306  do
307    echo $i | grep '.eli' >/dev/null 2>/dev/null
308    if [ "$?" = "0" ]
309    then
310      echo_log "Detaching GELI on ${i}"
311      rc_halt "geli detach ${i}"
312    fi
313  done
314
315};
316
317# Function which reads in the disk slice config, and performs it
318setup_disk_slice()
319{
320
321  # Cleanup any slice / mirror dirs
322  rm -rf ${SLICECFGDIR} >/dev/null 2>/dev/null
323  mkdir ${SLICECFGDIR}
324  rm -rf ${MIRRORCFGDIR} >/dev/null 2>/dev/null
325  mkdir ${MIRRORCFGDIR}
326
327  # Start with disk0
328  disknum="0"
329
330  # Make sure all zpools are exported
331  export_all_zpools
332
333  # We are ready to start setting up the disks, lets read the config and do the actions
334  while read line
335  do
336    echo $line | grep "^disk${disknum}=" >/dev/null 2>/dev/null
337    if [ "$?" = "0" ]
338    then
339
340      # Found a disk= entry, lets get the disk we are working on
341      get_value_from_string "${line}"
342      strip_white_space "$VAL"
343      DISK="$VAL"
344
345      # Before we go further, lets confirm this disk really exists
346      if [ ! -e "/dev/${DISK}" ]
347      then
348        exit_err "ERROR: The disk ${DISK} does not exist!"
349      fi
350
351      # Make sure we stop any gmirrors on this disk
352      stop_all_gmirror ${DISK}
353
354      # Make sure we stop any geli stuff on this disk
355      stop_all_geli ${DISK}
356
357      # Make sure we don't have any zpools loaded
358      stop_all_zfs
359
360    fi
361
362    # Lets look if this device will be mirrored on another disk
363    echo $line | grep "^mirror=" >/dev/null 2>/dev/null
364    if [ "$?" = "0" ]
365    then
366
367      # Found a disk= entry, lets get the disk we are working on
368      get_value_from_string "${line}"
369      strip_white_space "$VAL"
370      MIRRORDISK="$VAL"
371
372      # Before we go further, lets confirm this disk really exists
373      if [ ! -e "/dev/${MIRRORDISK}" ]
374      then
375        exit_err "ERROR: The mirror disk ${MIRRORDISK} does not exist!"
376      fi
377    fi
378
379    # Lets see if we have been given a mirror balance choice
380    echo $line | grep "^mirrorbal=" >/dev/null 2>/dev/null
381    if [ "$?" = "0" ]
382    then
383
384      # Found a disk= entry, lets get the disk we are working on
385      get_value_from_string "${line}"
386      strip_white_space "$VAL"
387      MIRRORBAL="$VAL"
388    fi
389
390    echo $line | grep "^partition=" >/dev/null 2>/dev/null
391    if [ "$?" = "0" ]
392    then
393      # Found a partition= entry, lets read / set it
394      get_value_from_string "${line}"
395      strip_white_space "$VAL"
396      PTYPE=`echo $VAL|tr A-Z a-z`
397
398      # We are using free space, figure out the slice number
399      if [ "${PTYPE}" = "free" ]
400      then
401        # Lets figure out what number this slice will be
402        LASTSLICE="`gpart show ${DISK} \
403          | grep -v ${DISK} \
404          | grep -v ' free' \
405          | tr -s '\t' ' ' \
406          | cut -d ' ' -f 4 \
407          | sed '/^$/d' \
408          | tail -n 1`"
409
410        if [ -z "${LASTSLICE}" ]
411        then
412          LASTSLICE="1"
413        else
414          LASTSLICE="`expr $LASTSLICE + 1`"
415        fi
416
417        if [ $LASTSLICE -gt 4 ]
418        then
419          exit_err "ERROR: BSD only supports primary partitions, and there are none availble on $DISK"
420        fi
421
422      fi
423    fi
424
425    # Check if we have an image file defined
426    echo $line | grep "^image=" >/dev/null 2>/dev/null
427    if [ "$?" = "0" ] ; then
428      # Found an image= entry, lets read / set it
429      get_value_from_string "${line}"
430      strip_white_space "$VAL"
431      IMAGE="$VAL"
432      if [ ! -f "$IMAGE" ] ; then
433        exit_err "$IMAGE file does not exist"
434      fi
435    fi
436
437    # Check if we have a partscheme specified
438    echo $line | grep "^partscheme=" >/dev/null 2>/dev/null
439    if [ "$?" = "0" ] ; then
440      # Found a partscheme= entry, lets read / set it
441      get_value_from_string "${line}"
442      strip_white_space "$VAL"
443      PSCHEME="$VAL"
444      if [ "$PSCHEME" != "GPT" -a "$PSCHEME" != "MBR" ] ; then
445        exit_err "Unknown partition scheme: $PSCHEME"
446      fi
447    fi
448
449    echo $line | grep "^bootManager=" >/dev/null 2>/dev/null
450    if [ "$?" = "0" ]
451    then
452      # Found a bootManager= entry, lets read /set it
453      get_value_from_string "${line}"
454      strip_white_space "$VAL"
455      BMANAGER="$VAL"
456    fi
457
458    echo $line | grep "^commitDiskPart" >/dev/null 2>/dev/null
459    if [ "$?" = "0" ]
460    then
461      # Found our flag to commit this disk setup / lets do sanity check and do it
462      if [ ! -z "${DISK}" -a ! -z "${PTYPE}" ]
463      then
464        case ${PTYPE} in
465          all)
466            if [ "$PSCHEME" = "MBR" -o -z "$PSCHEME" ] ; then
467              PSCHEME="MBR"
468              tmpSLICE="${DISK}s1"
469            else
470              tmpSLICE="${DISK}p1"
471            fi
472
473            run_gpart_full "${DISK}" "${BMANAGER}" "${PSCHEME}"
474            ;;
475
476          s1|s2|s3|s4)
477            tmpSLICE="${DISK}${PTYPE}"
478            # Get the number of the slice we are working on
479            s="`echo ${PTYPE} | awk '{print substr($0,length,1)}'`"
480            run_gpart_slice "${DISK}" "${BMANAGER}" "${s}"
481            ;;
482
483          free)
484            tmpSLICE="${DISK}s${LASTSLICE}"
485            run_gpart_free "${DISK}" "${LASTSLICE}" "${BMANAGER}"
486            ;;
487
488          image)
489            if [ -z "${IMAGE}" ]
490            then
491              exit_err "ERROR: partition type image specified with no image!"
492            fi
493            ;;
494
495          *) exit_err "ERROR: Unknown PTYPE: $PTYPE" ;;
496        esac
497
498
499		if [ -n "${IMAGE}" ]
500		then
501          local DEST
502
503		  if [ -n "${tmpSLICE}" ]
504          then
505			DEST="${tmpSLICE}"
506          else
507			DEST="${DISK}"
508          fi
509
510          if iscompressed "${IMAGE}"
511          then
512            local COMPRESSION
513
514            get_compression_type "${IMAGE}"
515            COMPRESSION="${VAL}"
516
517            decompress_file "${IMAGE}" "${COMPRESSION}"
518            IMAGE="${VAL}"
519          fi
520
521          write_image "${IMAGE}" "${DEST}"
522          check_disk_layout "${DEST}"
523		fi
524
525        # Now save which disk<num> this is, so we can parse it later during slice partition setup
526        if [ -z "${IMAGE}" ]
527        then
528          echo "disk${disknum}" >${SLICECFGDIR}/$tmpSLICE
529        fi
530
531        # Save any mirror config
532        if [ ! -z "$MIRRORDISK" ]
533        then
534          # Default to round-robin if the user didn't specify
535          if [ -z "$MIRRORBAL" ]
536          then
537            MIRRORBAL="round-robin"
538          fi
539          echo "$MIRRORDISK:$MIRRORBAL" >${MIRRORCFGDIR}/$DISK
540        fi
541
542        # Increment our disk counter to look for next disk and unset
543        unset BMANAGER PTYPE DISK MIRRORDISK MIRRORBAL PSCHEME IMAGE
544        disknum="`expr $disknum + 1`"
545      else
546        exit_err "ERROR: commitDiskPart was called without procceding disk<num>= and partition= entries!!!"
547      fi
548    fi
549
550  done <${CFGF}
551
552};
553
554# Stop all gjournals on disk / slice
555stop_gjournal()
556{
557  _gdsk="$1"
558  # Check if we need to shutdown any journals on this drive
559  ls /dev/${_gdsk}*.journal >/dev/null 2>/dev/null
560  if [ "$?" = "0" ]
561  then
562    cd /dev
563    for i in `ls ${_gdsk}*.journal`
564    do
565      rawjournal="`echo ${i} | cut -d '.' -f 1`"
566      gjournal stop -f ${rawjournal} >>${LOGOUT} 2>>${LOGOUT}
567      gjournal clear ${rawjournal} >>${LOGOUT} 2>>${LOGOUT}
568    done
569  fi
570} ;
571
572# Function which runs gpart and creates a single large GPT partition scheme
573init_gpt_full_disk()
574{
575  _intDISK=$1
576
577  # Set our sysctl so we can overwrite any geom using drives
578  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
579
580  # Stop any journaling
581  stop_gjournal "${_intDISK}"
582
583  # Remove any existing partitions
584  delete_all_gpart "${_intDISK}"
585
586  #Erase any existing bootloader
587  echo_log "Cleaning up ${_intDISK}"
588  rc_halt "dd if=/dev/zero of=/dev/${_intDISK} count=2048"
589
590  sleep 2
591
592  echo_log "Running gpart on ${_intDISK}"
593  rc_halt "gpart create -s GPT ${_intDISK}"
594  rc_halt "gpart add -b 34 -s 128 -t freebsd-boot ${_intDISK}"
595
596  echo_log "Stamping boot sector on ${_intDISK}"
597  rc_halt "gpart bootcode -b /boot/pmbr ${_intDISK}"
598
599}
600
601# Function which runs gpart and creates a single large MBR partition scheme
602init_mbr_full_disk()
603{
604  _intDISK=$1
605  _intBOOT=$2
606
607  startblock="63"
608
609  # Set our sysctl so we can overwrite any geom using drives
610  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
611
612  # Stop any journaling
613  stop_gjournal "${_intDISK}"
614
615  # Remove any existing partitions
616  delete_all_gpart "${_intDISK}"
617
618  #Erase any existing bootloader
619  echo_log "Cleaning up ${_intDISK}"
620  rc_halt "dd if=/dev/zero of=/dev/${_intDISK} count=2048"
621
622  sleep 2
623
624  echo_log "Running gpart on ${_intDISK}"
625  rc_halt "gpart create -s mbr ${_intDISK}"
626
627  # Lets figure out disk size in blocks
628  # Get the cyl of this disk
629  get_disk_cyl "${_intDISK}"
630  cyl="${VAL}"
631
632  # Get the heads of this disk
633  get_disk_heads "${_intDISK}"
634  head="${VAL}"
635
636  # Get the tracks/sectors of this disk
637  get_disk_sectors "${_intDISK}"
638  sec="${VAL}"
639
640  # Multiply them all together to get our total blocks
641  totalblocks="`expr ${cyl} \* ${head}`"
642  totalblocks="`expr ${totalblocks} \* ${sec}`"
643  if [ -z "${totalblocks}" ]
644  then
645    totalblocks=`gpart show "${_intDISK}"|tail -2|head -1|awk '{ print $2 }'`
646  fi
647
648  # Now set the ending block to the total disk block size
649  sizeblock="`expr ${totalblocks} - ${startblock}`"
650
651  # Install new partition setup
652  echo_log "Running gpart add on ${_intDISK}"
653  rc_halt "gpart add -b ${startblock} -s ${sizeblock} -t freebsd -i 1 ${_intDISK}"
654  sleep 2
655
656  echo_log "Cleaning up ${_intDISK}s1"
657  rc_halt "dd if=/dev/zero of=/dev/${_intDISK}s1 count=1024"
658
659  if [ "$_intBOOT" = "bsd" ] ; then
660    echo_log "Stamping boot sector on ${_intDISK}"
661    rc_halt "gpart bootcode -b /boot/boot0 ${_intDISK}"
662  fi
663
664}
665
666# Function which runs gpart and creates a single large slice
667run_gpart_full()
668{
669  DISK=$1
670  BOOT=$2
671  SCHEME=$3
672
673  if [ "$SCHEME" = "MBR" ] ; then
674    init_mbr_full_disk "$DISK" "$BOOT"
675    slice="${DISK}-1-mbr"
676  else
677    init_gpt_full_disk "$DISK"
678    slice="${DISK}-1-gpt"
679  fi
680
681  # Lets save our slice, so we know what to look for in the config file later on
682  if [ -z "$WORKINGSLICES" ]
683  then
684    WORKINGSLICES="${slice}"
685    export WORKINGSLICES
686  else
687    WORKINGSLICES="${WORKINGSLICES} ${slice}"
688    export WORKINGSLICES
689  fi
690};
691
692# Function which runs gpart on a specified s1-4 slice
693run_gpart_slice()
694{
695  DISK=$1
696  if [ ! -z "$2" ]
697  then
698    BMANAGER="$2"
699  fi
700
701  # Set the slice we will use later
702  slice="${1}s${3}"
703
704  # Set our sysctl so we can overwrite any geom using drives
705  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
706
707  # Get the number of the slice we are working on
708  slicenum="$3"
709
710  # Stop any journaling
711  stop_gjournal "${slice}"
712
713  # Make sure we have disabled swap on this drive
714  if [ -e "${slice}b" ]
715  then
716   swapoff ${slice}b >/dev/null 2>/dev/null
717   swapoff ${slice}b.eli >/dev/null 2>/dev/null
718  fi
719
720  # Modify partition type
721  echo_log "Running gpart modify on ${DISK}"
722  rc_halt "gpart modify -t freebsd -i ${slicenum} ${DISK}"
723  sleep 2
724
725  # Clean up old partition
726  echo_log "Cleaning up $slice"
727  rc_halt "dd if=/dev/zero of=/dev/${DISK}s${slicenum} count=1024"
728
729  sleep 1
730
731  if [ "${BMANAGER}" = "bsd" ]
732  then
733    echo_log "Stamping boot sector on ${DISK}"
734    rc_halt "gpart bootcode -b /boot/boot0 ${DISK}"
735  fi
736
737  # Set the slice to the format we'll be using for gpart later
738  slice="${1}-${3}-mbr"
739
740  # Lets save our slice, so we know what to look for in the config file later on
741  if [ -z "$WORKINGSLICES" ]
742  then
743    WORKINGSLICES="${slice}"
744    export WORKINGSLICES
745  else
746    WORKINGSLICES="${WORKINGSLICES} ${slice}"
747    export WORKINGSLICES
748  fi
749};
750
751# Function which runs gpart and creates a new slice from free disk space
752run_gpart_free()
753{
754  DISK=$1
755  SLICENUM=$2
756  if [ ! -z "$3" ]
757  then
758    BMANAGER="$3"
759  fi
760
761  # Set our sysctl so we can overwrite any geom using drives
762  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
763
764  slice="${DISK}s${SLICENUM}"
765  slicenum="${SLICENUM}"
766
767  # Working on the first slice, make sure we have MBR setup
768  gpart show ${DISK} >/dev/null 2>/dev/null
769  if [ "$?" != "0" -a "$SLICENUM" = "1" ] ; then
770    echo_log "Initializing disk, no existing MBR setup"
771    rc_halt "gpart create -s mbr ${DISK}"
772  fi
773
774  # Lets get the starting block first
775  if [ "${slicenum}" = "1" ]
776  then
777     startblock="63"
778  else
779     # Lets figure out where the prior slice ends
780     checkslice="`expr ${slicenum} - 1`"
781
782     # Get starting block of this slice
783     sblk=`gpart show ${DISK} | grep -v ${DISK} | tr -s '\t' ' ' | sed '/^$/d' | grep " ${checkslice} " | cut -d ' ' -f 2`
784     blksize=`gpart show ${DISK} | grep -v ${DISK} | tr -s '\t' ' ' | sed '/^$/d' | grep " ${checkslice} " | cut -d ' ' -f 3`
785     startblock="`expr ${sblk} + ${blksize}`"
786  fi
787
788  # No slice after the new slice, lets figure out the free space remaining and use it
789  # Get the cyl of this disk
790  get_disk_cyl "${DISK}"
791  cyl="${VAL}"
792
793  # Get the heads of this disk
794  get_disk_heads "${DISK}"
795  head="${VAL}"
796
797  # Get the tracks/sectors of this disk
798  get_disk_sectors "${DISK}"
799  sec="${VAL}"
800
801  # Multiply them all together to get our total blocks
802  totalblocks="`expr ${cyl} \* ${head}`"
803  totalblocks="`expr ${totalblocks} \* ${sec}`"
804
805
806  # Now set the ending block to the total disk block size
807  sizeblock="`expr ${totalblocks} - ${startblock}`"
808
809  # Install new partition setup
810  echo_log "Running gpart on ${DISK}"
811  rc_halt "gpart add -b ${startblock} -s ${sizeblock} -t freebsd -i ${slicenum} ${DISK}"
812  sleep 2
813
814  echo_log "Cleaning up $slice"
815  rc_halt "dd if=/dev/zero of=/dev/${slice} count=1024"
816
817  sleep 1
818
819  if [ "${BMANAGER}" = "bsd" ]
820  then
821    echo_log "Stamping boot sector on ${DISK}"
822    rc_halt "gpart bootcode -b /boot/boot0 ${DISK}"
823  fi
824
825  slice="${DISK}-${SLICENUM}-mbr"
826  # Lets save our slice, so we know what to look for in the config file later on
827  if [ -z "$WORKINGSLICES" ]
828  then
829    WORKINGSLICES="${slice}"
830    export WORKINGSLICES
831  else
832    WORKINGSLICES="${WORKINGSLICES} ${slice}"
833    export WORKINGSLICES
834  fi
835};
836