Project

General

Profile

Download (16.4 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/bin/sh
2
# Functions related to disk operations using gpart
3

    
4
# See if device is a full disk or partition/slice
5
is_disk() {
6
	for dsk in `sysctl -n kern.disks`
7
	do
8
		if [ "$dsk" = "${1}" ] ; then return 0 ; fi
9
	done
10

    
11
	return 1
12
}
13

    
14
# Get a MBR partitions sysid
15
get_partition_sysid_mbr()
16
{
17
  INPART="0"
18
  DISK="$1"
19
  PARTNUM=`echo ${2} | sed "s|${DISK}s||g"`
20
  fdisk ${DISK} >${TMPDIR}/disk-${DISK} 2>/dev/null
21
  while read i
22
  do
23
    echo "$i" | grep "The data for partition"  >/dev/null 2>/dev/null
24
    if [ "$?" = "0" ] ; then
25
       INPART="0"
26
       PART="`echo ${i} | cut -d ' ' -f 5`"
27
       if [ "$PART" = "$PARTNUM" ] ; then
28
          INPART="1"
29
       fi
30
    fi
31

    
32
    # In the partition section
33
    if [ "$INPART" = "1" ] ; then
34
       echo "$i" | grep "^sysid" >/dev/null 2>/dev/null
35
       if [ "$?" = "0" ] ; then
36
         SYSID="`echo ${i} | tr -s '\t' ' ' | cut -d ' ' -f 2`"
37
         break
38
       fi
39

    
40
    fi
41

    
42
  done < ${TMPDIR}/disk-${DISK}
43
  rm ${TMPDIR}/disk-${DISK}
44

    
45
  VAL="${SYSID}"
46
  export VAL
47
};
48

    
49
# Get the partitions MBR label
50
get_partition_label_mbr()
51
{
52
  INPART="0"
53
  DISK="$1"
54
  PARTNUM=`echo ${2} | sed "s|${DISK}s||g"`
55
  fdisk ${DISK} >${TMPDIR}/disk-${DISK} 2>/dev/null
56
  while read i
57
  do
58
    echo "$i" | grep "The data for partition"  >/dev/null 2>/dev/null
59
    if [ "$?" = "0" ] ; then
60
       INPART="0"
61
       PART="`echo ${i} | cut -d ' ' -f 5`"
62
       if [ "$PART" = "$PARTNUM" ] ; then
63
          INPART="1"
64
       fi
65
    fi
66

    
67
    # In the partition section
68
    if [ "$INPART" = "1" ] ; then
69
       echo "$i" | grep "^sysid" >/dev/null 2>/dev/null
70
       if [ "$?" = "0" ] ; then
71
         LABEL="`echo ${i} | tr -s '\t' ' ' | cut -d ',' -f 2-10`"
72
         break
73
       fi
74

    
75
    fi
76

    
77
  done < ${TMPDIR}/disk-${DISK}
78
  rm ${TMPDIR}/disk-${DISK}
79

    
80
  VAL="${LABEL}"
81
  export VAL
82
};
83

    
84
# Get a GPT partitions label
85
get_partition_label_gpt()
86
{
87
  DISK="${1}"
88
  PARTNUM=`echo ${2} | sed "s|${DISK}p||g"`
89

    
90
  gpart show ${DISK} >${TMPDIR}/disk-${DISK}
91
  while read i
92
  do
93
     SLICE="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 3`"
94
     if [ "${SLICE}" = "${PARTNUM}" ] ; then
95
       LABEL="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 4`"
96
       break
97
     fi
98
  done <${TMPDIR}/disk-${DISK}
99
  rm ${TMPDIR}/disk-${DISK}
100

    
101
  VAL="${LABEL}"
102
  export VAL
103
};
104

    
105
# Get a partitions startblock
106
get_partition_startblock()
107
{
108
  DISK="${1}"
109
  PARTNUM=`echo ${2} | sed "s|${DISK}p||g" | sed "s|${DISK}s||g"`
110

    
111
  gpart show ${DISK} >${TMPDIR}/disk-${DISK}
112
  while read i
113
  do
114
     SLICE="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 3`"
115
     if [ "$SLICE" = "${PARTNUM}" ] ; then
116
       SB="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 1`"
117
       break
118
     fi
119
  done <${TMPDIR}/disk-${DISK}
120
  rm ${TMPDIR}/disk-${DISK}
121

    
122
  VAL="${SB}"
123
  export VAL
124
};
125

    
126
# Get a partitions blocksize
127
get_partition_blocksize()
128
{
129
  DISK="${1}"
130
  PARTNUM=`echo ${2} | sed "s|${DISK}p||g" | sed "s|${DISK}s||g"`
131

    
132
  gpart show ${DISK} >${TMPDIR}/disk-${DISK}
133
  while read i
134
  do
135
     SLICE="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 3`"
136
     if [ "$SLICE" = "${PARTNUM}" ] ; then
137
       BS="`echo ${i} | grep -v ${DISK} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 2`"
138
       break
139
     fi
140
  done <${TMPDIR}/disk-${DISK}
141
  rm ${TMPDIR}/disk-${DISK}
142

    
143
  VAL="${BS}"
144
  export VAL
145
};
146

    
147
# Function which returns the partitions on a target disk
148
get_disk_partitions()
149
{
150
  gpart show ${1} >/dev/null 2>/dev/null
151
  if [ "$?" != "0" ] ; then
152
    VAL="" ; export VAL
153
    return
154
  fi
155

    
156
  gpart show ${1} | grep "MBR" >/dev/null 2>/dev/null
157
  if [ "$?" = "0" ] ; then
158
    type="MBR"
159
  else
160
    type="GPT"
161
  fi
162

    
163
  SLICES="`gpart show ${1} | grep -v ${1} | grep -v ' free ' |tr -s '\t' ' ' | cut -d ' ' -f 4 | sed '/^$/d'`"
164
  for i in ${SLICES}
165
  do
166
    case $type in
167
       MBR) name="${1}s${i}" ;;
168
       GPT) name="${1}p${i}";;
169
       *) name="${1}s${i}";;
170
    esac
171
    if [ -z "${RSLICES}" ]
172
    then
173
      RSLICES="${name}"
174
    else
175
      RSLICES="${RSLICES} ${name}"
176
    fi
177
  done
178

    
179
  VAL="${RSLICES}" ; export VAL
180
};
181

    
182
# Function which returns a target disks cylinders
183
get_disk_cyl()
184
{
185
  cyl=`diskinfo -v ${1} | grep "# Cylinders" | tr -s ' ' | cut -f 2`
186
  VAL="${cyl}" ; export VAL
187
};
188

    
189
# Function which returns a target disks sectors
190
get_disk_sectors()
191
{
192
  sec=`diskinfo -v ${1} | grep "# Sectors" | tr -s ' ' | cut -f 2`
193
  VAL="${sec}" ; export VAL
194
};
195

    
196
# Function which returns a target disks heads
197
get_disk_heads()
198
{
199
  head=`diskinfo -v ${1} | grep "# Heads" | tr -s ' ' | cut -f 2`
200
  VAL="${head}" ; export VAL
201
};
202

    
203
# Function which exports all zpools, making them safe to overwrite potentially
204
export_all_zpools() {
205
  # Export any zpools
206
  for i in `zpool list -H -o name`
207
  do
208
    zpool export -f ${i}
209
  done
210
};
211

    
212
# Function to delete all gparts before starting an install
213
delete_all_gpart()
214
{
215
  echo_log "Deleting all gparts"
216
  DISK="$1"
217

    
218
  # Check for any swaps to stop
219
  for i in `gpart show ${DISK} 2>/dev/null | grep 'freebsd-swap' | tr -s ' ' | cut -d ' ' -f 4`
220
  do
221
    swapoff /dev/${DISK}s${i}b >/dev/null 2>/dev/null
222
    swapoff /dev/${DISK}p${i} >/dev/null 2>/dev/null
223
  done
224

    
225
  # Delete the gparts now
226
  for i in `gpart show ${DISK} 2>/dev/null | tr -s ' ' | cut -d ' ' -f 4`
227
  do
228
   if [ "${i}" != "${DISK}" -a "${i}" != "-" ] ; then
229
     rc_nohalt "gpart delete -i ${i} ${DISK}"
230
   fi
231
  done
232

    
233
  rc_nohalt "dd if=/dev/zero of=/dev/${DISK} count=3000"
234

    
235
};
236

    
237
# Function to export all zpools before starting an install
238
stop_all_zfs()
239
{
240
  # Export all zpools again, so that we can overwrite these partitions potentially
241
  for i in `zpool list -H -o name`
242
  do
243
    zpool export -f ${i}
244
  done
245
};
246

    
247
# Function which stops all gmirrors before doing any disk manipulation
248
stop_all_gmirror()
249
{
250
  DISK="${1}"
251
  GPROV="`gmirror list | grep ". Name: mirror/" | cut -d '/' -f 2`"
252
  for gprov in $GPROV 
253
  do
254
    gmirror list | grep "Name: ${DISK}" >/dev/null 2>/dev/null
255
    if [ "$?" = "0" ]
256
    then
257
      echo_log "Stopping mirror $gprov $DISK"
258
      rc_nohalt "gmirror remove $gprov $DISK"
259
      rc_nohalt "dd if=/dev/zero of=/dev/${DISK} count=4096"
260
    fi
261
  done
262
};
263

    
264
# Make sure we don't have any geli providers active on this disk
265
stop_all_geli()
266
{
267
  DISK="${1}"
268
  cd /dev
269

    
270
  for i in `ls ${DISK}*`
271
  do
272
    echo $i | grep '.eli' >/dev/null 2>/dev/null
273
    if [ "$?" = "0" ]
274
    then
275
      echo_log "Detaching GELI on ${i}"
276
      rc_halt "geli detach ${i}"
277
    fi
278
  done
279

    
280
};
281

    
282
# Function which reads in the disk slice config, and performs it
283
setup_disk_slice()
284
{
285

    
286
  # Cleanup any slice / mirror dirs
287
  rm -rf ${SLICECFGDIR} >/dev/null 2>/dev/null
288
  mkdir ${SLICECFGDIR}
289
  rm -rf ${MIRRORCFGDIR} >/dev/null 2>/dev/null
290
  mkdir ${MIRRORCFGDIR}
291

    
292
  # Start with disk0
293
  disknum="0"
294

    
295
  # Make sure all zpools are exported
296
  export_all_zpools
297

    
298
  # We are ready to start setting up the disks, lets read the config and do the actions
299
  while read line
300
  do
301
     echo $line | grep "^disk${disknum}=" >/dev/null 2>/dev/null
302
     if [ "$?" = "0" ]
303
     then
304

    
305
       # Found a disk= entry, lets get the disk we are working on
306
       get_value_from_string "${line}"
307
       strip_white_space "$VAL"
308
       DISK="$VAL"
309
     
310
       # Before we go further, lets confirm this disk really exists
311
       if [ ! -e "/dev/${DISK}" ]
312
       then
313
         exit_err "ERROR: The disk ${DISK} does not exist!"
314
       fi
315

    
316
       # Make sure we stop any gmirrors on this disk
317
       stop_all_gmirror ${DISK}
318

    
319
       # Make sure we stop any geli stuff on this disk
320
       stop_all_geli ${DISK}
321

    
322
       # Make sure we don't have any zpools loaded
323
       stop_all_zfs
324

    
325
     fi
326

    
327
     # Lets look if this device will be mirrored on another disk
328
     echo $line | grep "^mirror=" >/dev/null 2>/dev/null
329
     if [ "$?" = "0" ]
330
     then
331

    
332
       # Found a disk= entry, lets get the disk we are working on
333
       get_value_from_string "${line}"
334
       strip_white_space "$VAL"
335
       MIRRORDISK="$VAL"
336
     
337
       # Before we go further, lets confirm this disk really exists
338
       if [ ! -e "/dev/${MIRRORDISK}" ]
339
       then
340
         exit_err "ERROR: The mirror disk ${MIRRORDISK} does not exist!"
341
       fi
342
     fi
343

    
344
     # Lets see if we have been given a mirror balance choice
345
     echo $line | grep "^mirrorbal=" >/dev/null 2>/dev/null
346
     if [ "$?" = "0" ]
347
     then
348

    
349
       # Found a disk= entry, lets get the disk we are working on
350
       get_value_from_string "${line}"
351
       strip_white_space "$VAL"
352
       MIRRORBAL="$VAL"
353
     fi
354

    
355
     echo $line | grep "^partition=" >/dev/null 2>/dev/null
356
     if [ "$?" = "0" ]
357
     then
358
       # Found a partition= entry, lets read / set it 
359
       get_value_from_string "${line}"
360
       strip_white_space "$VAL"
361
       PTYPE="$VAL"
362

    
363
       # We are using free space, figure out the slice number
364
       if [ "${PTYPE}" = "free" -o "${PTYPE}" = "FREE" ]
365
       then
366
         # Lets figure out what number this slice will be
367
         LASTSLICE="`gpart show ${DISK} | grep -v ${DISK} | grep -v ' free' |tr -s '\t' ' ' | cut -d ' ' -f 4 | sed '/^$/d' | tail -n 1`"
368
         if [ -z "${LASTSLICE}" ]
369
         then
370
           LASTSLICE="1"
371
         else
372
           LASTSLICE="`expr $LASTSLICE + 1`"
373
         fi
374

    
375
         if [ $LASTSLICE -gt 4 ]
376
         then
377
           exit_err "ERROR: BSD only supports primary partitions, and there are none availble on $DISK"
378
         fi
379

    
380
       fi
381
     fi
382

    
383
     echo $line | grep "^bootManager=" >/dev/null 2>/dev/null
384
     if [ "$?" = "0" ]
385
     then
386
       # Found a bootManager= entry, lets read /set it
387
       get_value_from_string "${line}"
388
       strip_white_space "$VAL"
389
       BMANAGER="$VAL"
390
     fi
391

    
392
     echo $line | grep "^commitDiskPart" >/dev/null 2>/dev/null
393
     if [ "$?" = "0" ]
394
     then
395
       # Found our flag to commit this disk setup / lets do sanity check and do it
396
       if [ ! -z "${DISK}" -a ! -z "${PTYPE}" ]
397
       then
398
         case ${PTYPE} in
399
                   all|ALL) tmpSLICE="${DISK}p1"  
400
                        run_gpart_full "${DISK}" "${BMANAGER}" ;;
401
           s1|s2|s3|s4) tmpSLICE="${DISK}${PTYPE}" 
402
                        # Get the number of the slice we are working on
403
                        s="`echo ${PTYPE} | awk '{print substr($0,length,1)}'`" 
404
                        run_gpart_slice "${DISK}" "${BMANAGER}" "${s}" ;;
405
                 free|FREE) tmpSLICE="${DISK}s${LASTSLICE}"
406
                        run_gpart_free "${DISK}" "${LASTSLICE}" "${BMANAGER}" ;;
407
                     *) exit_err "ERROR: Unknown PTYPE: $PTYPE" ;;
408
         esac
409

    
410
         # Now save which disk<num> this is, so we can parse it later during slice partition setup
411
         echo "disk${disknum}" >${SLICECFGDIR}/$tmpSLICE
412

    
413
         # Save any mirror config
414
         if [ ! -z "$MIRRORDISK" ]
415
         then
416
           # Default to round-robin if the user didn't specify
417
           if [ -z "$MIRRORBAL" ]
418
           then
419
             MIRRORBAL="round-robin"
420
           fi
421
           echo "$MIRRORDISK:$MIRRORBAL" >${MIRRORCFGDIR}/$DISK
422
         fi
423

    
424

    
425
         # Increment our disk counter to look for next disk and unset
426
         unset BMANAGER PTYPE DISK MIRRORDISK MIRRORBAL
427
         disknum="`expr $disknum + 1`"
428
       else
429
         exit_err "ERROR: commitDiskPart was called without procceding disk<num>= and partition= entries!!!" 
430
       fi
431
     fi
432

    
433
  done <${CFGF}
434

    
435
};
436

    
437
# Stop all gjournals on disk / slice
438
stop_gjournal() {
439
  DISK="$1"
440
  # Check if we need to shutdown any journals on this drive
441
  ls /dev/${DISK}*.journal >/dev/null 2>/dev/null
442
  if [ "$?" = "0" ]
443
  then
444
    cd /dev
445
    for i in `ls ${DISK}*.journal`
446
    do
447
      rawjournal="`echo ${i} | cut -d '.' -f 1`"
448
      gjournal stop -f ${rawjournal} >>${LOGOUT} 2>>${LOGOUT}
449
      gjournal clear ${rawjournal} >>${LOGOUT} 2>>${LOGOUT}
450
    done
451
  fi
452
} ;
453

    
454
# Function which runs gpart and creates a single large slice
455
init_gpt_full_disk()
456
{
457
  DISK=$1
458
 
459
  # Set our sysctl so we can overwrite any geom using drives
460
  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
461

    
462
  # Stop any journaling
463
  stop_gjournal "${DISK}"
464

    
465
  # Remove any existing partitions
466
  delete_all_gpart "${DISK}"
467

    
468
  #Erase any existing bootloader
469
  echo_log "Cleaning up ${DISK}"
470
  rc_halt "dd if=/dev/zero of=/dev/${DISK} count=2048"
471

    
472
  sleep 2
473

    
474
  echo_log "Running gpart on ${DISK}"
475
  rc_halt "gpart create -s GPT ${DISK}"
476
  rc_halt "gpart add -s 128 -t freebsd-boot ${DISK}"
477
  
478
  echo_log "Stamping boot sector on ${DISK}"
479
  rc_halt "gpart bootcode -b /boot/pmbr ${DISK}"
480

    
481
}
482

    
483
# Function which runs gpart and creates a single large slice
484
run_gpart_full()
485
{
486
  DISK=$1
487

    
488
  init_gpt_full_disk "$DISK"
489

    
490
  slice="${DISK}-1-gpt"
491

    
492
  # Lets save our slice, so we know what to look for in the config file later on
493
  if [ -z "$WORKINGSLICES" ]
494
  then
495
    WORKINGSLICES="${slice}"
496
    export WORKINGSLICES
497
  else
498
    WORKINGSLICES="${WORKINGSLICES} ${slice}"
499
    export WORKINGSLICES
500
  fi
501
};
502

    
503
# Function which runs gpart on a specified s1-4 slice
504
run_gpart_slice()
505
{
506
  DISK=$1
507
  if [ ! -z "$2" ]
508
  then
509
    BMANAGER="$2"
510
  fi
511

    
512
  # Set the slice we will use later
513
  slice="${1}s${3}"
514
 
515
  # Set our sysctl so we can overwrite any geom using drives
516
  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
517

    
518
  # Get the number of the slice we are working on
519
  slicenum="$3"
520

    
521
  # Stop any journaling
522
  stop_gjournal "${slice}"
523

    
524
  # Make sure we have disabled swap on this drive
525
  if [ -e "${slice}b" ]
526
  then
527
   swapoff ${slice}b >/dev/null 2>/dev/null
528
   swapoff ${slice}b.eli >/dev/null 2>/dev/null
529
  fi
530

    
531
  # Modify partition type
532
  echo_log "Running gpart modify on ${DISK}"
533
  rc_halt "gpart modify -t freebsd -i ${slicenum} ${DISK}"
534
  sleep 2
535

    
536
  # Clean up old partition
537
  echo_log "Cleaning up $slice"
538
  rc_halt "dd if=/dev/zero of=/dev/${DISK}s${slicenum} count=1024"
539

    
540
  sleep 1
541

    
542
  if [ "${BMANAGER}" = "bsd" ]
543
  then
544
    echo_log "Stamping boot sector on ${DISK}"
545
    rc_halt "gpart bootcode -b /boot/boot0 ${DISK}"
546
  fi
547

    
548
  # Set the slice to the format we'll be using for gpart later
549
  slice="${1}-${3}-mbr"
550

    
551
  # Lets save our slice, so we know what to look for in the config file later on
552
  if [ -z "$WORKINGSLICES" ]
553
  then
554
    WORKINGSLICES="${slice}"
555
    export WORKINGSLICES
556
  else
557
    WORKINGSLICES="${WORKINGSLICES} ${slice}"
558
    export WORKINGSLICES
559
  fi
560
};
561

    
562
# Function which runs gpart and creates a new slice from free disk space
563
run_gpart_free()
564
{
565
  DISK=$1
566
  SLICENUM=$2
567
  if [ ! -z "$3" ]
568
  then
569
    BMANAGER="$3"
570
  fi
571

    
572
  # Set our sysctl so we can overwrite any geom using drives
573
  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
574

    
575
  slice="${DISK}s${SLICENUM}"
576
  slicenum="${SLICENUM}" 
577

    
578
  # Working on the first slice, make sure we have MBR setup
579
  gpart show ${DISK} >/dev/null 2>/dev/null
580
  if [ "$?" != "0" -a "$SLICENUM" = "1" ] ; then
581
    echo_log "Initializing disk, no existing MBR setup"
582
    rc_halt "gpart create -s mbr ${DISK}"
583
  fi
584

    
585
  # Lets get the starting block first
586
  if [ "${slicenum}" = "1" ]
587
  then
588
     startblock="63"
589
  else
590
     # Lets figure out where the prior slice ends
591
     checkslice="`expr ${slicenum} - 1`"
592

    
593
     # Get starting block of this slice
594
     sblk=`gpart show ${DISK} | grep -v ${DISK} | tr -s '\t' ' ' | sed '/^$/d' | grep " ${checkslice} " | cut -d ' ' -f 2`
595
     blksize=`gpart show ${DISK} | grep -v ${DISK} | tr -s '\t' ' ' | sed '/^$/d' | grep " ${checkslice} " | cut -d ' ' -f 3`
596
     startblock="`expr ${sblk} + ${blksize}`"
597
  fi
598

    
599
  # No slice after the new slice, lets figure out the free space remaining and use it
600
  # Get the cyl of this disk
601
  get_disk_cyl "${DISK}"
602
  cyl="${VAL}"
603

    
604
  # Get the heads of this disk
605
  get_disk_heads "${DISK}"
606
  head="${VAL}"
607

    
608
  # Get the tracks/sectors of this disk
609
  get_disk_sectors "${DISK}"
610
  sec="${VAL}"
611

    
612
  # Multiply them all together to get our total blocks
613
  totalblocks="`expr ${cyl} \* ${head}`"
614
  totalblocks="`expr ${totalblocks} \* ${sec}`"
615

    
616

    
617
  # Now set the ending block to the total disk block size
618
  sizeblock="`expr ${totalblocks} - ${startblock}`"
619

    
620
  # Install new partition setup
621
  echo_log "Running gpart on ${DISK}"
622
  rc_halt "gpart add -b ${startblock} -s ${sizeblock} -t freebsd -i ${slicenum} ${DISK}"
623
  sleep 2
624
  
625
  echo_log "Cleaning up $slice"
626
  rc_halt "dd if=/dev/zero of=/dev/${slice} count=1024"
627

    
628
  sleep 1
629

    
630
  if [ "${BMANAGER}" = "bsd" ]
631
  then
632
    echo_log "Stamping boot sector on ${DISK}"
633
    rc_halt "gpart bootcode -b /boot/boot0 ${DISK}"
634
  fi
635

    
636
  slice="${DISK}-${SLICENUM}-mbr"
637
  # Lets save our slice, so we know what to look for in the config file later on
638
  if [ -z "$WORKINGSLICES" ]
639
  then
640
    WORKINGSLICES="${slice}"
641
    export WORKINGSLICES
642
  else
643
    WORKINGSLICES="${WORKINGSLICES} ${slice}"
644
    export WORKINGSLICES
645
  fi
646
};
(3-3/18)