1219019Sgabor#! /usr/bin/perl
2219019Sgabor#
3219019Sgabor# $FreeBSD$
4219019Sgabor
5219019Sgaboruse strict;
6219019Sgaboruse warnings;
7219019Sgaboruse Test::More tests => 19;
8219019Sgaboruse Fcntl qw(:DEFAULT :seek);
9219019Sgabor
10219019Sgaboruse constant BLK => 512;
11219019Sgaboruse constant BLKS_PER_MB => 2048;
12219019Sgabor
13219019Sgabormy $unit;
14219019SgaborEND { system "mdconfig -du$unit" if defined $unit };
15219019Sgabor
16219019Sgaborsub setsize {
17219019Sgabor    my ($partszMB, $unitszMB) = @_;
18219019Sgabor
19219019Sgabor    open my $fd, "|-", "disklabel -R md$unit /dev/stdin" or die;
20219019Sgabor    print $fd "a: ", ($partszMB * BLKS_PER_MB), " 0 4.2BSD 1024 8192\n";
21219019Sgabor    print $fd "c: ", ($unitszMB * BLKS_PER_MB), " 0 unused 0 0\n";
22219019Sgabor    close $fd;
23219019Sgabor}
24219019Sgabor
25219019Sgaborsub fill {
26219019Sgabor    my ($start, $size, $content) = @_;
27219019Sgabor
28219019Sgabor    my $content512 = $content x (int(512 / length $content) + 1);
29219019Sgabor    substr($content512, 512) = "";
30219019Sgabor    sysopen my $fd, "/dev/md$unit", O_RDWR or die "/dev/md$unit: $!";
31219019Sgabor    seek($fd, $start * BLK, SEEK_SET);
32219019Sgabor    while ($size) {
33219019Sgabor	syswrite($fd, $content512) == 512 or die "write: $!";
34219019Sgabor	$size--;
35219019Sgabor    }
36219019Sgabor}
37219019Sgabor
38219019SgaborSKIP: {
39219019Sgabor    skip "Cannot test without UID 0", 19 if $<;
40219019Sgabor
41219019Sgabor    chomp(my $md = `mdconfig -s40m`);
42219019Sgabor    like($md, qr/^md\d+$/, "Created $md with size 40m") or die;
43219019Sgabor    $unit = substr $md, 2;
44219019Sgabor
45219019Sgabor    for my $type (1..2) {
46219019Sgabor
47219019Sgabor	initialise: {
48219019Sgabor	    ok(setsize(10, 40), "Sized ${md}a to 10m");
49219019Sgabor	    system "newfs -O $type -U ${md}a >/dev/null";
50219019Sgabor	    is($?, 0, "Initialised the filesystem on ${md}a as UFS$type");
51219019Sgabor	    chomp(my @out = `fsck -tufs -y ${md}a`);
52219019Sgabor	    ok(!grep(/MODIFIED/, @out), "fsck says ${md}a is clean, " .
53219019Sgabor		scalar(@out) . " lines of output");
54219019Sgabor	}
55219019Sgabor
56219019Sgabor	extend20_zeroed: {
57219019Sgabor	    ok(setsize(20, 40), "Sized ${md}a to 20m");
58219019Sgabor	    diag "Filling the extent with zeros";
59219019Sgabor	    fill(10 * BLKS_PER_MB, 10 * BLKS_PER_MB, chr(0));
60219019Sgabor	    my $out = `growfs -y ${md}a`;
61219019Sgabor	    is($?, 0, "Extended the filesystem on ${md}a") or print $out;
62219019Sgabor
63219019Sgabor	    my ($unallocated) = $out =~ m{\d+ sectors cannot be allocated};
64219019Sgabor	    fill(30 * BLKS_PER_MB - $unallocated, $unallocated, chr(0))
65219019Sgabor		if $unallocated;
66219019Sgabor
67219019Sgabor	    chomp(my @out = `fsck -tufs -y ${md}a`);
68219019Sgabor	    ok(!grep(/MODIFIED/, @out), "fsck says ${md}a is clean, " .
69219019Sgabor		scalar(@out) . " lines of output");
70219019Sgabor	}
71219019Sgabor
72219019Sgabor	extend30_garbaged: {
73219019Sgabor	    ok(setsize(30, 40), "Sized ${md}a to 30m");
74219019Sgabor	    diag "Filling the extent with garbage";
75219019Sgabor	    fill(20 * BLKS_PER_MB, 10 * BLKS_PER_MB, chr(0xaa) . chr(0x55));
76219019Sgabor	    my $out = `growfs -y ${md}a`;
77219019Sgabor	    is($?, 0, "Extended the filesystem on ${md}a") or print $out;
78219019Sgabor
79219019Sgabor	    my ($unallocated) = $out =~ m{\d+ sectors cannot be allocated};
80219019Sgabor	    fill(30 * BLKS_PER_MB - $unallocated, $unallocated, chr(0))
81219019Sgabor		if $unallocated;
82219019Sgabor
83219019Sgabor	    chomp(my @out = `fsck -tufs -y ${md}a`);
84219019Sgabor	    ok(!grep(/MODIFIED/, @out), "fsck says ${md}a is clean, " .
85219019Sgabor		scalar(@out) . " lines of output");
86219019Sgabor	}
87219019Sgabor    }
88219019Sgabor
89219019Sgabor    system "mdconfig -du$unit";
90219019Sgabor    undef $unit;
91219019Sgabor}
92219019Sgabor