1 package Mogstored
::ChildProcess
::IOStat
;
3 use base
'Mogstored::ChildProcess';
7 my $iostat_cmd = $ENV{MOG_IOSTAT_CMD
} || "iostat -dx 1 30";
8 if ($^O
=~ /darwin/) { $iostat_cmd =~ s/x// }
17 my $iostat_pipe_w = Mogstored
->get_iostat_writer_pipe;
19 # We may not be able to see errors beyond this point
20 open STDIN
, '<', '/dev/null' or die "Couldn't open STDIN for reading from /dev/null";
21 open STDOUT
, '>&', $iostat_pipe_w or die "Couldn't dup pipe for use as STDOUT";
22 open STDERR
, '>', '/dev/null' or die "Couldn't open STDOUT for writing to /dev/null";
24 $ENV{MOG_DOCROOT
} = Perlbal
->service('mogstored')->{docroot
};
28 $docroot = $ENV{MOG_DOCROOT
};
29 die "\$ENV{MOG_DOCROOT} not set" unless $docroot;
30 die "\$ENV{MOG_DOCROOT} not set to a directory" unless -d
$docroot;
32 # (runs in exec'd child process)
33 $0 = "mogstored [iostat]";
34 select((select(STDOUT
), $|++)[0]);
37 $SIG{TERM
} = $SIG{INT
} = sub {
38 kill 9, $iostat_pid if $iostat_pid;
42 my $check_for_parent = sub {
43 # shut ourselves down if our parent mogstored
46 unless ($ppid && kill(0,$ppid)) {
47 kill 9, $iostat_pid if $iostat_pid;
52 my $get_iostat_fh = sub {
54 if ($iostat_pid = open (my $fh, "$iostat_cmd|")) {
57 # TODO: try and find other paths to iostat
58 $check_for_parent->();
59 warn "Failed to open iostat: $!\n"; # this will just go to /dev/null, but will be straceable
65 my $iofh = $get_iostat_fh->();
66 my $mog_sysid = mog_sysid_map
(); # 5 (mogdevid) -> 2340 (os devid)
67 my $dev_sysid = {}; # hashref, populated lazily: { /dev/sdg => system dev_t }
68 my %devt_util; # dev_t => 52.55
71 if (m/^\s*(\S+)\s.*?([\d.]+)\s*$/) {
72 my ($devnode, $util) = ("/dev/$1", $2);
73 unless (exists $dev_sysid->{$devnode}) {
74 $dev_sysid->{$devnode} = (stat($devnode))[6]; # rdev
76 my $devt = $dev_sysid->{$devnode};
77 $devt_util{$devt} = $util;
80 # blank line is the end, or any other line we don't understand
81 # if we have stats, we print them, otherwise do nothing
85 foreach my $mogdevid (sort { $a <=> $b } keys %$mog_sysid) {
86 my $devt = $mog_sysid->{$mogdevid};
87 my $ut = defined $devt_util{$devt} ?
$devt_util{$devt} : "-";
88 $ret .= "$mogdevid\t$ut\n";
93 $check_for_parent->();
101 # returns hashref of { 5 => dev_t device } # mog_devid -> os_devid
106 # find all devices below us
107 my @devnum; # integer ids
108 opendir(my $d, $path) or die "Failed to open docroot: $path: $!";
109 @devnum = map { /^dev(\d+)$/ ?
$1 : () } readdir($d);
112 foreach my $mogdevid (@devnum) {
113 my ($osdevid) = (stat("$path/dev$mogdevid"))[0];
114 $map->{$mogdevid} = $osdevid;
117 if (lc($^O
) eq 'linux') {
118 # name_to_number and number_to_name are the data derived from /proc/partitions
119 my %name_to_number; # ( hda1 => 769, ... )
120 my %number_to_name; # ( 769 => hda1, ... )
122 if (open my $partitions, '<', '/proc/partitions') {
123 <$partitions>; <$partitions>; # First two lines are for humans
124 while (my $line = <$partitions>) {
125 next unless $line =~ m/^ \s* (\d+) \s+ (\d+) \s+ \d+ \s+ (\S+) \s* $/x;
126 my ($major, $minor, $devname) = ($1, $2, $3);
127 my $devno = ($major << 8) + $minor;
128 $name_to_number{$devname} = $devno;
129 $number_to_name{$devno} = $devname;
132 warn "Unable to open /proc/partitions: $!";
135 # Iterate over the hash { 1 => 768 } meaning (mogile device dev1 points to os device 768)
136 foreach my $mogdevid (keys %$map) {
137 # Look up the original device number
138 my $original = $map->{$mogdevid};
140 # See if there is a mapping to turn it into a device name (eg. hda1)
141 my $devname = $number_to_name{$original} or next;
143 # Pull off the new device name with a regex
144 if (my ($newname) = $devname =~ m/^([hs]d\w+)\d+$/) {
145 # Skip if we can't map it back to a device number
146 my $newnum = $name_to_number{$newname} or next;
147 $map->{$mogdevid} = $newnum;
148 } elsif (my ($newname, undef) = $devname =~ m/^(cciss\/c\d
+d\d
+)(\w
+)?
$/) {
149 my $newnum = $name_to_number{$newname} or next;
150 $map->{$mogdevid} = $newnum;