Xen and loop devices continued

I created one more guest and that made them nine in total, but when I tried to power it on, I got the following error message:

# xm create node9
Using config file "/etc/xen/node9".
Error: Device 51712 (vbd) could not be connected. Failed to find an unused loop device

Once again problem with the disk image in combination with loop device but different than yesterday’s problem.
I checked which loop devices are used:

# losetup -a
/dev/loop0: [0811]:161693699 (/data/guests/node1.img)
/dev/loop1: [0811]:161693702 (/data/guests/node2.img)
/dev/loop2: [0811]:161693703 (/data/guests/node3.img)
/dev/loop3: [0811]:161693704 (/data/guests/node4.img)
/dev/loop4: [0811]:161693705 (/data/guests/node5.img)
/dev/loop5: [0811]:161693706 (/data/guests/node6.img)
/dev/loop6: [0811]:161693707 (/data/guests/node7.img)
/dev/loop7: [0811]:161693708 (/data/guests/node8.img)

And then how many are available in total:

# ls -l /dev/loop*
brw-r----- 1 root disk 7, 0 Mar  9 22:08 /dev/loop0
brw-r----- 1 root disk 7, 1 Mar  9 22:08 /dev/loop1
brw-r----- 1 root disk 7, 2 Mar  9 22:08 /dev/loop2
brw-r----- 1 root disk 7, 3 Mar  9 22:08 /dev/loop3
brw-r----- 1 root disk 7, 4 Mar  9 22:08 /dev/loop4
brw-r----- 1 root disk 7, 5 Mar  9 22:08 /dev/loop5
brw-r----- 1 root disk 7, 6 Mar  9 22:08 /dev/loop6
brw-r----- 1 root disk 7, 7 Mar  9 22:08 /dev/loop7

All eight loop devices are used. If each guest had a second disk image as well, I’d face the problem after node4. The problem resides to the fact that the default number of loop devices provided by the kernel are eight, and every Xen guest that doesn’t use the Xen blktp driver will use a loop device for every disk image it’s assigned with. The solution to this is to increase the number of loop devices. That can be done by editing /etc/modprobe.conf and adding a new definition for the maximum loop devices:

options loop max_loop=24

In order for that to take effect, you’ll need either to reboot the system or reload the loop kernel module. In order to reload the module, the current loop devices must be free, so every guest should be powered off. Then simply:

# rmmod loop
# modprobe loop
# ls -l /dev/loop*
brw-r----- 1 root disk 7,  0 Mar 24 12:25 /dev/loop0
brw-r----- 1 root disk 7,  1 Mar 24 12:25 /dev/loop1
brw-r----- 1 root disk 7, 10 Mar 24 12:27 /dev/loop10
brw-r----- 1 root disk 7, 11 Mar 24 12:27 /dev/loop11
brw-r----- 1 root disk 7, 12 Mar 24 12:27 /dev/loop12
brw-r----- 1 root disk 7, 13 Mar 24 12:27 /dev/loop13
brw-r----- 1 root disk 7, 14 Mar 24 12:27 /dev/loop14
brw-r----- 1 root disk 7, 15 Mar 24 12:27 /dev/loop15
brw-r----- 1 root disk 7, 16 Mar 24 12:27 /dev/loop16
brw-r----- 1 root disk 7, 17 Mar 24 12:27 /dev/loop17
brw-r----- 1 root disk 7, 18 Mar 24 12:27 /dev/loop18
brw-r----- 1 root disk 7, 19 Mar 24 12:27 /dev/loop19
brw-r----- 1 root disk 7,  2 Mar 24 12:25 /dev/loop2
brw-r----- 1 root disk 7, 20 Mar 24 12:27 /dev/loop20
brw-r----- 1 root disk 7, 21 Mar 24 12:27 /dev/loop21
brw-r----- 1 root disk 7, 22 Mar 24 12:27 /dev/loop22
brw-r----- 1 root disk 7, 23 Mar 24 12:27 /dev/loop23

Powering the guests and running losetup -a:

# losetup -a
/dev/loop0: [0811]:161693699 (/data/guests/node1.img)
/dev/loop1: [0811]:161693702 (/data/guests/node2.img)
/dev/loop10: [0811]:161693703 (/data/guests/node3.img)
/dev/loop11: [0811]:161693704 (/data/guests/node4.img)
/dev/loop12: [0811]:161693705 (/data/guests/node5.img)
/dev/loop13: [0811]:161693706 (/data/guests/node6.img)
/dev/loop14: [0811]:161693707 (/data/guests/node7.img)
/dev/loop15: [0811]:161693708 (/data/guests/node8.img)
/dev/loop16: [0811]:161693709 (/data/guests/node9.img)

Paravirtualised guests can make use of the blktp driver to access the virtual block device directly, without using a loop device. To do so, the guest’s configuration file must specify ‘tap:aio:’ instead of of ‘file’ at the disk entry. This is not true for full virtualised guests. However, both paravirtualsied and full virtualised guests can make use of physical partitions (defined as ‘phy’) and that eliminates the use of loop devices among other advantages.

Xen guest and and loop device being busy

I had accidentally given the same UUID on two guests and I didn’t realise it until I tried to start the second one. I generated a new UUID but the guest was still failing, but this time with a different error, like its disk image was used by another guest.

# xm create node6
Using config file "/etc/xen/node6".
Error: Device 768 (vbd) could not be connected.
File /data/guests/node6.img is loopback-mounted through /dev/loop5,
which is mounted in a guest domain,
and so cannot be mounted now

A bit odd as I was sure that the disk image was not used by another guest. After a couple of tries, I used the ‘lsof’ command to check what processes are using the guests’ images. I have all the disk images under /data/guests:

# lsof +D /data/guests/ | grep node6
qemu-dm  6250 root    6u   REG   8,17 4194304000 161693706 /data/guests/node6.img
qemu-dm  7121 root    6u   REG   8,17 4194304000 161693706 /data/guests/node6.img
qemu-dm  8906 root    6u   REG   8,17 4194304000 161693706 /data/guests/node6.img
qemu-dm 11262 root    6u   REG   8,17 4194304000 161693706 /data/guests/node6.img

Four different processes pointing at the disk image of node6 guest. The first one being the first attempt to boot the guest with the wrong UUID and the other ones my attempts on trying to boot the guest after I changed the UUID. As none of these processes was corresponding to a running instance of the guest, I killed all of them:

# for i in `lsof +D /data/guests/ | grep node6 | awk {'print $2'}`;do kill -9 $i;done

As a side note ,if one of these was the last, and successful, attempt to run the guest, then I had to identify which one is the running instance by checking the PIDs. The following command would return the PIDs of the failed attempts to start the guest:

# lsof +D /data/guests/ | grep node6 | grep -v \
`ps aux | grep node6 | grep -v grep | awk {'print $2'}` | awk {'print $2'}

Once I killed the processes, I checked again with lsof and everything looked good:

# lsof +D /data/guests/
COMMAND  PID USER   FD   TYPE DEVICE       SIZE      NODE NAME
qemu-dm 3345 root    6u   REG   8,17 4194304000 161693699 /data/guests/node1.img
qemu-dm 3633 root    6u   REG   8,17 4194304000 161693702 /data/guests/node2.img
qemu-dm 3788 root    6u   REG   8,17 4194304000 161693703 /data/guests/node3.img
qemu-dm 3945 root    6u   REG   8,17 4194304000 161693704 /data/guests/node4.img
qemu-dm 4154 root    6u   REG   8,17 4194304000 161693705 /data/guests/node5.img
qemu-dm 4513 root    6u   REG   8,17 4194304000 161693708 /data/guests/node8.img
qemu-dm 4996 root    6u   REG   8,17 4194304000 161693707 /data/guests/node7.img

But trying to boot the host again gives the same error. I then powered off all of the running guests (node1-5,7,8) and tried to to boot node6. It failed again with the same error. I was a bit puzzled as there was no zombie instance listed by ‘xm list’ and no zombie guest ID listed by XenStore when running ‘xenstore-list backend/vbd’. But weirdly enough, previous experience says that without any guests running, the backend/vbd shouldn’t be present but it was. I could thought only of a “ghost” zombie instance keeping busy the disk image as during my attempt to start node6 with the wrong UUID I got node6 to be zombie at some point. My last try before rebooting the whole system was to remove the whole backend/vbd:

# xenstore-rm backend/vbd

Once I did, I restarted the xend daemon and tried to start node6 once again. It worked! I then booted and the rest of the guests and every one of them was happy.

I still can’t determine what was the exact cause of that but I guess it was because of the “ghost” zombie guest due to its failed startup attempt with the wrong UUID while there was another guest instance running with the same UUID.

Note: It’s really funny how “kills”, “zombies”, “daemons” and “ghosts” go along with computers 😛

Ανακατασκευή του επιγωνίου

Το διάβασα εδώ και στα Ελληνικά εδώ.

Πραγματικά συναρπαστικό το πως η συνεργασία επιστημών (και επιστημόνων) εντελώς διαφορετικών κλάδων μπορεί να αποφέρει τόσο θετικά αποτελέσματα με τη χρήση της υπάρχουσας υψυλής απόδοσης τεχνολογίας για την αναγεννήση κομματιών του παρελθόντος.

Specifying number of CPUs and size of RAM on Linux SMP kernel

The Linux kernel boot parameters on SMP processor enable the user to define how many cores and what amount of RAM the system should use. For instance trying this with Grub, booting with 2 cores and 1,2GB of memory, we edit the /boot/grub/grub.conf file and we add the extra parameters:

kernel /boot/vmlinuz-2.6.18-128.1.1.el5 ro root=LABEL=/ rhgb quiet maxcpus=2 mem=1224M

‘man bootparam’ contains all the available parameters that can be set.

Shell script for standard deviation, arithmetic mean and median

I was looking for a Shell script that could calculate the standard deviation of a data set. I found the one at http://tldp.org/LDP/abs/html/contributed-scripts.html#STDDEV that returns the arithmetic mean as well. I added one more function for calculating the median of the data set. The modified script follows:

#!/bin/bash

# sttdev.sh: Standard Deviation

# Original version obtained from: http://tldp.org/LDP/abs/html/contributed-scripts.html#STDDEV

# 2009-03-09: Panagiotis Kritikakos
# Function stat_median() added for calculating the median value
# of the data set

# ------------------------------------------------------------
#  The Standard Deviation indicates how consistent a set of data is.
#  It shows to what extent the individual data points deviate from the
#+ arithmetic mean, i.e., how much they "bounce around" (or cluster).
#  It is essentially the average deviation-distance of the
#+ data points from the mean.

# =========================================================== #
#    To calculate the Standard Deviation:
#
# 1  Find the arithmetic mean (average) of all the data points.
# 2  Subtract each data point from the arithmetic mean,
#    and square that difference.
# 3  Add all of the individual difference-squares in # 2.
# 4  Divide the sum in # 3 by the number of data points.
#    This is known as the "variance."
# 5  The square root of # 4 gives the Standard Deviation.
# =========================================================== #

count=0         # Number of data points; global.
SC=9            # Scale to be used by bc. Nine decimal places.
E_DATAFILE=90   # Data file error.

# ----------------- Set data file ---------------------
if [ ! -z "$1" ]  # Specify filename as cmd-line arg?
then
  datafile="$1" #  ASCII text file,
else            #+ one (numerical) data point per line!
  datafile=sample.dat
fi              #  See example data file, below.

if [ ! -e "$datafile" ]
then
  echo "\""$datafile"\" does not exist!"
  exit $E_DATAFILE
fi
# -----------------------------------------------------
arith_mean ()
{
  local rt=0         # Running total.
  local am=0         # Arithmetic mean.
  local ct=0         # Number of data points.

  while read value   # Read one data point at a time.
  do
    rt=$(echo "scale=$SC; $rt + $value" | bc)
    (( ct++ ))
  done

  am=$(echo "scale=$SC; $rt / $ct" | bc)

  echo $am; return $ct   # This function "returns" TWO values!
  #  Caution: This little trick will not work if $ct > 255!
  #  To handle a larger number of data points,
  #+ simply comment out the "return $ct" above.
} <"$datafile"   # Feed in data file.

sd ()
{
  mean1=$1  # Arithmetic mean (passed to function).
  n=$2      # How many data points.
  sum2=0    # Sum of squared differences ("variance").
  avg2=0    # Average of $sum2.
  sdev=0    # Standard Deviation.

  while read value   # Read one line at a time.
  do
    diff=$(echo "scale=$SC; $mean1 - $value" | bc)
    # Difference between arith. mean and data point.
    dif2=$(echo "scale=$SC; $diff * $diff" | bc) # Squared.
    sum2=$(echo "scale=$SC; $sum2 + $dif2" | bc) # Sum of squares.
  done

    avg2=$(echo "scale=$SC; $sum2 / $n" | bc)  # Avg. of sum of squares.
    sdev=$(echo "scale=$SC; sqrt($avg2)" | bc) # Square root =
    echo $sdev                                 # Standard Deviation.

} <"$datafile"   # Rewinds data file.

stat_median() {
  NUMS=(`sort -n $1`)
  TOTALNUMS=${#NUMS[*]}
  MOD=$(($TOTALNUMS % 2))
  if [ $MOD -eq 0 ]; then
    ARRAYMIDDLE=$(echo "($TOTALNUMS / 2)-1" | bc)
    ARRAYNEXTMIDDLE=$(($ARRAYMIDDLE + 1))
    MEDIAN=$(echo "scale=$SC; ((${NUMS[$ARRAYMIDDLE]})+(${NUMS[$ARRAYNEXTMIDDLE]})) / 2" | bc)
  elif [ $MOD -eq 1 ]; then
    ARRAYMIDDLE=$(echo "($TOTALNUMS / 2)" | bc)
    MEDIAN=${NUMS[$ARRAYMIDDLE]}
  fi
  echo $MEDIAN
}

# ======================================================= #
mean=$(arith_mean); count=$?   # Two returns from function!
std_dev=$(sd $mean $count)
median=$(stat_median $1)

echo
echo "Number of data points in \""$datafile"\" = $count"
echo "Arithmetic mean (average) = $mean"
echo "Standard Deviation = $std_dev"
echo "Median number (middle) = $median"
echo
# ======================================================= #

exit

#  This script could stand some drastic streamlining,
#+ but not at the cost of reduced legibility, please.

# ++++++++++++++++++++++++++++++++++++++++ #
# A sample data file (sample1.dat):

# 18.35
# 19.0
# 18.88
# 18.91
# 18.64

# $ sh stddev.sh sample1.dat

# Number of data points in "sample1.dat" = 5
# Arithmetic mean (average) = 18.756000000
# Standard Deviation = .235338054
# Median number (middle) = 27.35
# ++++++++++++++++++++++++++++++++++++++++ #

I guess that could be done in Perl with fewer lines and using proper modules for the calculation, but I’m not in love with Perl… yet…

Package managers for OS X

Installing common *nix applications from source on OS X can be a real pain in the neck. It may even defeat Slackware in some occasions :p Tools provided by Macports and Fink make life much easier and productive. On the following example, Fink is used to install gnuplot by using the Debian-like apt-get:

panoskrt$ uname -rs
Darwin 9.6.0
panoskrt$ sudo apt-get install gnuplot
Reading Package Lists... Done
Building Dependency Tree... Done
The following extra packages will be installed:
  aquaterm aquaterm-shlibs gd2-shlibs libjpeg-bin pdflib-shlibs readline-shlibs texinfo
The following NEW packages will be installed:
  aquaterm aquaterm-shlibs gd2-shlibs gnuplot libjpeg-bin pdflib-shlibs readline-shlibs texinfo
0 packages upgraded, 8 newly installed, 0 to remove and 0  not upgraded.
Need to get 5461kB of archives. After unpacking 13.6MB will be used.
Do you want to continue? [Y/n] y
Get:1 http://bindist.finkmirrors.net 10.5/release/main aquaterm-shlibs 1.0.0-1003 [31.6kB]
Get:2 http://bindist.finkmirrors.net 10.5/release/main aquaterm 1.0.0-1003 [88.2kB]
Get:3 http://bindist.finkmirrors.net 10.5/release/main libjpeg-bin 6b-17 [130kB]
Get:4 http://bindist.finkmirrors.net 10.5/release/main gd2-shlibs 2.0.33-3 [130kB]
Get:5 http://bindist.finkmirrors.net 10.5/release/main texinfo 4.8-1002 [1013kB]
Get:6 http://bindist.finkmirrors.net 10.5/release/main readline-shlibs 4.3-1028 [108kB]
Get:7 http://bindist.finkmirrors.net 10.5/release/main pdflib-shlibs 5.0.1-2 [1827kB]
Get:8 http://bindist.finkmirrors.net 10.5/release/main gnuplot 4.0.0-1005 [2133kB]
Fetched 5461kB in 43s (126kB/s)
Selecting previously deselected package aquaterm-shlibs.
(Reading database ... 5617 files and directories currently installed.)
Unpacking aquaterm-shlibs (from .../aquaterm-shlibs_1.0.0-1003_darwin-i386.deb) ...
Selecting previously deselected package aquaterm.
Unpacking aquaterm (from .../aquaterm_1.0.0-1003_darwin-i386.deb) ...
Selecting previously deselected package libjpeg-bin.
Unpacking libjpeg-bin (from .../libjpeg-bin_6b-17_darwin-i386.deb) ...
Selecting previously deselected package gd2-shlibs.
Unpacking gd2-shlibs (from .../gd2-shlibs_2.0.33-3_darwin-i386.deb) ...
Selecting previously deselected package texinfo.
Unpacking texinfo (from .../texinfo_4.8-1002_darwin-i386.deb) ...
Selecting previously deselected package readline-shlibs.
Unpacking readline-shlibs (from .../readline-shlibs_4.3-1028_darwin-i386.deb) ...
Selecting previously deselected package pdflib-shlibs.
Unpacking pdflib-shlibs (from .../pdflib-shlibs_5.0.1-2_darwin-i386.deb) ...
Selecting previously deselected package gnuplot.
Unpacking gnuplot (from .../gnuplot_4.0.0-1005_darwin-i386.deb) ...
Setting up aquaterm-shlibs (1.0.0-1003) ...
Setting up aquaterm (1.0.0-1003) ...
Setting up libjpeg-bin (6b-17) ...

Setting up gd2-shlibs (2.0.33-3) ...
Setting up texinfo (4.8-1002) ...
* Texinfo: (texinfo).           The GNU documentation format.
install-info(/sw/share/info/texinfo): creating new section `Texinfo documentation system'
* info standalone: (info-stnd).            Read Info documents without Emacs.
* Info: (info). How to use the documentation browsing system.

Setting up readline-shlibs (4.3-1028) ...
Setting up pdflib-shlibs (5.0.1-2) ...
Setting up gnuplot (4.0.0-1005) ...
* GNUPLOT: (gnuplot). An Interactive Plotting Program
install-info(/sw/share/info/gnuplot.info): creating new section `Math'

panoskrt$ which gnuplot;
/sw/bin/gnuplot

Fink: http://www.finkproject.org
Macports: http://www.macports.org/