Sarthak Kukreti | 6cd8322 | 2020-09-28 05:23:39 -0700 | [diff] [blame^] | 1 | #!/bin/sh |
| 2 | # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | # This script contains common helper functions to use with LVM-based stateful |
| 7 | # partitions. These helpers are useful for both install and startup |
| 8 | # scripts. |
| 9 | |
| 10 | # Fetches the volume group name on the device. Empty if the device is not a |
| 11 | # valid physical volume or if it doesn't have a volume group set up on it. |
| 12 | get_volume_group() { |
| 13 | local physical_volume="$1" |
| 14 | |
| 15 | pvdisplay -C --quiet --noheadings --separator '|' \ |
| 16 | -o vg_name "${physical_volume}" | tr -d '[:space:]' |
| 17 | } |
| 18 | |
| 19 | # Generate a random label, used for volume group name generation. |
| 20 | generate_random_label() { |
| 21 | local n |
| 22 | for n in $(od -A none -tu1 -N16 /dev/urandom); do |
| 23 | # 36 doesn't evenly divide 256 so there's slight bias here. |
| 24 | n=$(( n % 36 )) |
| 25 | if [ "${n}" -lt "10" ]; then |
| 26 | # shellcheck disable=SC2059 |
| 27 | printf "${n}" |
| 28 | else |
| 29 | # shellcheck disable=SC2059 |
| 30 | printf "\\$(printf '%03o' $((n - 10 + 0x41)))" |
| 31 | fi |
| 32 | done |
| 33 | } |
| 34 | |
| 35 | # Try to validate the volume group name: if another volume group exists with the |
| 36 | # same name, regenerate the volume group name. Bail out after 5 tries. |
| 37 | generate_random_vg_name() { |
| 38 | local vg_name |
| 39 | local _ |
| 40 | |
| 41 | for _ in 1 2 3 4 5; do |
| 42 | vg_name="$(generate_random_label)" |
| 43 | # If there is no volume group on the device with the generated vg name |
| 44 | # return. |
| 45 | if ! sudo vgdisplay "${vg_name}" >/dev/null; then |
| 46 | # shellcheck disable=SC2059 |
| 47 | printf "${vg_name}" |
| 48 | return |
| 49 | fi |
| 50 | done |
| 51 | } |
| 52 | |
| 53 | # Gets device size in bytes. |
| 54 | get_device_size() { |
| 55 | local device="$1" |
| 56 | blockdev --getsize64 "${device}" |
| 57 | } |
| 58 | |
| 59 | # With multiple logical volumes per user, we need more than 1 physical extent to |
| 60 | # store the physical volume metadata. Therefore, there may not be enough space |
| 61 | # to store the data for O(100) logical volumes. We set aside 4 physical extents |
| 62 | # (the default PE size is 4MB). Additionally, we need to set aside some space |
| 63 | # the thinpool's metadata. thin_metadata_size estimates the metadata size for |
| 64 | # storing a maximum of 200 logical volumes as <2% of the size of the thinpool. |
| 65 | get_thinpool_size() { |
| 66 | local physical_volume="$1" |
| 67 | echo $(( $(get_device_size "${physical_volume}") * 98 / (100 * 1024 * 1024) )) |
| 68 | } |
| 69 | |
| 70 | # Thin provisioning tools uses a util to calculate what the metadata size should |
| 71 | # for give a device and maximum number of thinpools associated with the device. |
| 72 | get_thinpool_metadata_size() { |
| 73 | local thinpool_size="$1" |
| 74 | |
| 75 | thin_metadata_size --block-size 4k --pool-size "${thinpool_size}M" \ |
| 76 | --max-thins 200 --numeric-only -u M |
| 77 | } |
| 78 | |
| 79 | # By default, create thin logical volumes at 95% of the size of the thinpool. |
| 80 | get_logical_volume_size() { |
| 81 | local physical_volume="$1" |
| 82 | local thinpool_size |
| 83 | |
| 84 | thinpool_size="$(get_thinpool_size "${physical_volume}")" |
| 85 | echo $(( thinpool_size * 95 / 100 )) |
| 86 | } |