aboutsummaryrefslogtreecommitdiff
path: root/fs/ext2/genext2fs.sh
blob: c2049f56c3226e892f2c98fc16855a6105a4d9fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/bin/sh
# genext2fs wrapper calculating needed blocks/inodes values if not specified
set -e

export LC_ALL=C

CALC_BLOCKS=1
CALC_INODES=1
EXT_OPTS=
EXT_OPTS_O=

while getopts x:d:D:b:i:N:m:g:e:zfqUPhVv f
do
    case $f in
	b) CALC_BLOCKS=0 ;;
	N) CALC_INODES=0; INODES=$OPTARG ;;
	d) TARGET_DIR=$OPTARG ;;
    esac
done
eval IMG="\"\${${OPTIND}}\""

# calculate needed inodes
if [ $CALC_INODES -eq 1 ];
then
    INODES=$(find $TARGET_DIR | wc -l)
    INODES=$(expr $INODES + 400)
    set -- $@ -N $INODES
fi

# calculate needed blocks
if [ $CALC_BLOCKS -eq 1 ];
then
    # size ~= superblock, block+inode bitmaps, inodes (8 per block), blocks
    # we scale inodes / blocks with 10% to compensate for bitmaps size + slack
    BLOCKS=$(du -s -c -k $TARGET_DIR | grep total | sed -e "s/total//")
    BLOCKS=$(expr 500 + \( $BLOCKS + $INODES / 8 \) \* 11 / 10)
    # we add 1081 blocks (a bit more than 1 MiB, assuming 1KiB blocks) for
    # the journal if ext3/4
    # Note: I came to 1081 blocks after trial-and-error checks. With 1080 or
    # less additional blocks, and tune2fs would refuse to add the journal;
    # with 1081 additional blocks or above, tune2fs wil happily add a journal.
    # YMMV.
    if [ ${GEN} -ge 3 ]; then
        BLOCKS=$(expr 1081 + $BLOCKS )
    fi
    set -- $@ -b $BLOCKS
fi

e2tunefsck() {
    # Upgrade the file system
    if [ $# -ne 0 ]; then
        tune2fs "$@" "${IMG}"
    fi

    # After changing filesystem options, running fsck is required
    # (see: man tune2fs). Running e2fsck in other cases will ensure
    # coherency of the filesystem, although it is not required.
    # 'e2fsck -pDf' means:
    #  - automatically repair
    #  - optimise and check for duplicate entries
    #  - force checking
    # Sending output to oblivion, as e2fsck can be *very* verbose,
    # especially with filesystems generated by genext2fs.
    # Exit codes 1 & 2 are OK, it means fs errors were successfully
    # corrected, hence our little trick with $ret.
    ret=0
    e2fsck -pDf "${IMG}" >/dev/null || ret=$?
    case ${ret} in
       0|1|2) ;;
       *)   exit ${ret};;
    esac
    printf "\ne2fsck was successfully run on '%s' (ext%d)\n\n"  \
           "${IMG##*/}" "${GEN}"

    # e2fsck will force a *random* UUID, which is bad
    # for reproducibility, so we do not want it
    tune2fs -U clear "${IMG}"
}

# Check we know what generation to generate
case "${GEN}" in
    2|3|4)
	;;
    *)
	printf "%s: unknown ext generation to generate\n" "${0##*/}" >&2
	exit 1
	;;
esac

# Add a journal for ext3 and above
if [ ${GEN} -ge 3 ]; then
    EXT_OPTS="${EXT_OPTS} -j -J size=1"
fi

# Add ext4 specific features
if [ ${GEN} -ge 4 ]; then
    EXT_OPTS_O="${EXT_OPTS_O},extents,uninit_bg,dir_index"
fi

# Add our -O options (there will be at most one leading comma, remove it)
if [ -n "${EXT_OPTS_O}" ]; then
    EXT_OPTS="${EXT_OPTS} -O ${EXT_OPTS_O#,}"
fi

# Generate and upgrade the filesystem
genext2fs "$@"
e2tunefsck ${EXT_OPTS}