Raw Devices on Suse Linux

Three steps to create a logical volume

How can we make raw devices in Suse Linux? Is there an easy way to build chunks based on raw devices with something like a Logical Volume manager?
The answer is: yes. In this article we learn the basics of LVM2 (created by Heinz Mauelshagen) and how to use it to create raw devices for an informix instance. We will not go through the whole set of LVM-commands but only those which are necessary for handling raw devices.

First have a look on the version of your LVM.
The output of the command "lvm version" shows

libelle:/opt # lvm version
  LVM version:     2.02.02 (2006-02-07)
  Library version: 1.02.03 (2006-02-08)
  Driver version:  4.5.0

so we know that we have LVM2. It is important to know which version you use, because Logical Volumes (LV) are differently represented in LVM1 and LVM2.
LVM1 stores information about LVs in /proc/lvm/VGs which has changed to /dev/mapper in LVM2.
LVM2 is part of the OS since Suse 9.3. If it is not automatically installed, you can install LVM2 via yast2.

To create a logical volume we have to

  1. inititalize physical volumes (disks or partitions on disks)
  2. define Volume Groups (VGs) as sets of physical volumes
  3. define logical volumes (LVs) as subsets of VGs

The first two steps will be done with yast2, the GUI-based administration tool from Suse, but you can do it also with commands like 'pvcreate' and 'vgcreate'.
For example, if you want to make the whole disk /dev/hdb a physical volume, you should enter

pvcreate /dev/hdb

This creates a volume group descriptor at the start of disk.
Perhaps we get an error if there was a partition table on the disk. Then we have to delete this table explicitly with "dd":

dd if=/dev/zero of=/dev/hbd bs=1k count=1
blockdev --rereadpt /dev/hdb

Instead of the whole disk we can use a partition /dev/hdb1:

pvcreate /dev/hdb1

Next we create the Volume Group (if you didn't create it with Yast2):

vgcreate system  /dev/hdb1 

Next we want to see the results:

libelle:/home/f995440 # pvdisplay
  --- Physical volume ---
  PV Name               /dev/hda6
  VG Name               system
  PV Size               4,00 GB / not usable 0   
  Allocatable           yes 
  PE Size (KByte)       4096
  Total PE              1023
  Free PE               102
  Allocated PE          921
  PV UUID               RCHWtF-r1Kn-iwlc-oA13-RGwd-B2X3-GVoEfi
libelle:/etc # vgdisplay
  --- Volume group ---
  VG Name               system
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  49
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                16
  Open LV               15
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               4,00 GB
  PE Size               4,00 MB
  Total PE              1023
  Alloc PE / Size       921 / 3,60 GB
  Free  PE / Size       102 / 408,00 MB
  VG UUID               7hZSbH-JsM3-92au-OQ9C-jRuQ-y7Zp-xI453P

On my Suse Linux System the name of the volume group is "system", it's size is 4GB, and the size of PE=physical Extent is 4MB. Later we will see that Logical Volumes consist of Physical Extents (PE), which are mapped onto Physical Extents of the VG to which LV belongs.

Now we are ready to create the raw device for our Root DB space. We want to have about 50MB for the Root DBspace.

Create the Logical Volume (LV)

libelle:/home/f995440 # lvcreate -L 50M -n example system
  Rounding up size to full physical extent 52,00 MB
  Logical volume "example" created

Our "example" Volume was rounded up to full physical extent size of 52,00 MB, because the size must be a multiple of 4MB PE-Size.

From Logical Volume to Raw device


What is the result of the lvcreate command? "lvdisplay" gives a detailed description of the LV:

libelle:/etc # lvdisplay /dev/system/example
  --- Logical volume ---
  LV Name                /dev/system/example
  VG Name                system
  LV UUID                6J7uMK-0pwI-1olB-bESP-UtET-p94v-XkoDaZ
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                52,00 MB
  Current LE             13
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           253:16

You see, that the "name" of the LV is /dev/system/example. This is not a raw device but only a symbolic link to a block device:

libelle:/etc # ls -ail /dev/system/example
1986699 lrwxrwxrwx 1 root root 26 2006-11-02 15:51 /dev/system/example -> /dev/mapper/system-example
libelle:/etc # ls -ail /dev/mapper/system-example
1986698 brw------- 1 root root 253, 16 2006-11-02 15:51 /dev/mapper/system-example

We cannot change the block device somehow into a raw device but we can bind a raw device to this blockdevice. This will be done by a utility called raw (see man raw).

Raw devices are character devices with major number 162. The first minor number (i.e. 0) is reserved as a control interface and is usually found at /dev/rawctl. The control device /dev/rawctl can be generated with the command

/sbin/modprobe raw

Raw-devices are located in /dev/raw and can be created with "mknod":

cd /dev/raw
while  ((i<= 128))
       do
       mknod raw$i c 162 $i
       let i=i+1
done

Next we want to bind the block device /dev/system/example to raw device /dev/raw/raw50:

libelle$raw /dev/raw/raw50 /dev/system/example
/dev/raw/raw50: bound to major 253, minor 16

raw -qa
/dev/raw/raw50: bound to major 253, minor 16

The command raw -qa shows all raw devices which are bounded to other devices. The only method to identify the logical volume to which the raw device is bounded is to compare the major/minor numbers. It is important to put this information somewhere in a file so that you can rebind all your raw devices after a system crash. Usually this is the file /etc/raw. Here is an example of /etc/raw on my Suse system:

# /etc/raw
# 
# sample configuration to bind raw devices
# to block devices
#
# The format of this file is:
# raw: 
#
# example:
# ---------
# raw1:hdb1
#
# this means: bind /dev/raw/raw1 to /dev/hdb1
#
# ...
raw1:system/inf_0_001
raw10:system/physdbs_001
raw100:system/logdbs_001
raw103:system/perfdbs_001
raw104:system/perfdbs_002
raw107:system/tempdbs3_001
raw108:system/tempdbs1_001
raw109:system/tempdbs1_001
raw11:system/tempdbs2_001
raw110:system/testspace_001
raw111:system/datenspace1_001
raw112:system/sbspace_001
raw113:system/sbspace_default_001
raw101:system/logdbs_002
raw102:system/massendaten_001
raw105:system/s9_sbspc_001

After a reboot you must rebind your raw devices because they are not automatically bounded - may be that they do not exist so that you have to generate the control device and the other raw devices again. To do this you can extend the script /etc/init.d/raw. /usr/sbin/rcraw is a symbolic link to /etc/init.d/raw. With rcraw you can start raw devices and show the status (i.e. "raw -qa"):

rcraw start # start raw devices (i.e. binds...)
rcraw staus # status of raw devices

You cannot stop raw devices/unbound them. This can
only be done by a system shutdown!

Here is an example of /etc/init.d/raw on my system:

#!/bin/bash
# Copyright (c) 1995-2001 SuSE GmbH Nuernberg, Germany.
#
# Author: Dirk Lerner 
#
### BEGIN INIT INFO
# Provides:       raw
# Required-Start: $local_fs $remote_fs
# Required-Stop:
# Default-Start:  2 3 5
# Default-Stop:   0 1 6
# Description:    raw-devices
### END INIT INFO

myecho()
    {
    echo `date +%d-%m-%Y/%T` $* >> $PROTOKOLL
    return $?
}

genraw()
{
        # generate Raw-Devices, if the do not exist
        if [[ ! -d /dev/raw ]]
        then
                myecho "Directory /dev/raw do not exist"
                myecho "Directory /dev/raw will be generated"
                mkdir /dev/raw
        fi
        if [[ ! -f /dev/raw/raw* ]]
        then
                myecho "No raw devices, must create"
                cd /dev/raw
                while  ((i<= 128))
                do
                        mknod raw$i c 162 $i
                        let i=i+1
                done

        fi
}

i=1
PROTOKOLL=/db/inf/log/raw.log

. /etc/rc.status

CONFIG=/etc/raw
RAW_BIN=/usr/sbin/raw
RAW_MODULE=raw
test -x $RAW_BIN || exit 5

if [ ! -f $CONFIG ];then
 myecho "file: $CONFIG not found"
 exit 6
fi

rc_reset
case "$1" in
    start)
        # modprobe adds the Modul raw into Linux-kernel
        # and generates the control device
        myecho "starting genraw "
        genraw
        /sbin/modprobe $RAW_MODULE && sleep 2
        line=`cat $CONFIG | grep -v ^#`

        rawdev=`cat $CONFIG | cut -f1 -d:`
        rawbind=`cat $CONFIG | cut -f2 -d:`

        for i in $line;do
                rawdev=`echo $i | cut -f1 -d:`
                rawbind=`echo $i | cut -f2 -d:`
                myecho "rawdev=$rawdev, rawbind=$rawbind"
                myecho "bind /dev/raw/$rawdev to /dev/$rawbind..."
                $RAW_BIN /dev/raw/$rawdev /dev/$rawbind  >>$PROTOKOLL 1>> $PROTOKOLL 2>&1
                rc_status -v
        done
      ;;
    stop)
      myecho  "to unbind the rawdevice please perform a system shutdown"
      rc_failed 3
      rc_status -v
      ;;
    status)
      $RAW_BIN -qa 2> /dev/null
      rc_status -v
      ;;
    *)
      myecho "Usage: $0 {start|stop|status}"
      exit 1
      ;;
esac
rc_exit

Add a symbolic link

ln -s /etc/rc.d/raw /etc/rc.d/rc2.d/S21raw

to start automatically raw devices after booting the system. Please note, that /etc/init.d/raw uses the content of Config-file /etc/raw to find logical volumes to be bound.

Let us summarize the steps for creating a raw device:

  • create a logical volume
  • create a raw device
  • bind this raw device to the logical volume
  • put an appropriate row in /etc/raw

Now we are able to create a sample informix instance. We assume, that we have enough raw devices in /dev/raw. Look at the following list of commands:

  • Create a logical volume (100MB) for the root Dbspace:
    lvcreate -L 100M -n inf_0_001 system
    
  • Bind a raw device to the LV:
    raw /dev/raw/raw1 /dev/mapper/system-inf_0_001
    
  • chmod 660 /dev/raw/raw1
    chown informix:informix /dev/raw/raw1
    
  • Put all links to chunks in a special directory: on my system it is /db/inf/dev/libelle. Then change ROOTPATH in your ONCONFIG file and create a symbolic link:
    ln -s /dev/raw/raw1 /db/inf/dev/libelle/inf_0_001
    ROOTPATH        /db/inf/dev/libelle/inf_0_001
    
  • Start initialization:
    oninit -ivy
    

A Python-Program for creating dbspaces und raw-devices

If you want to create more dbspaces it is recommended to write a program which can do for you the steps mentioned above. Take a look at inf_space, a python program wich can do the most used tasks for you:
  • inf_space -c -d dbspacename -m megabytes [-t]
    
           -c stands for "Create"
           -d dbspacename
           -m size in Megabyte 
           -t for temporary Dbspaces
    
  •  inf_space -c -S dbspacename -m megabytes [-t]
    
           -c stands for "Create"
           -S Smart Blobspacename
           -m size in Megabyte  
           -t for temporary Dbspaces
    
  •  inf_space -a -d dbspacename -m megabytes
    
           -a adds a chunk
           -d dbspacename
           -m size in Megabyte  
    
  •  inf_space -r -d dbspacename
    
           -d dbspacename
           -r remove dbspace
    
  •  inf_space -r -d dbspacename  -n chunknumber
    
           -d dbspacename
           -r remove dbspace
           -n Chunknumber
    

inf_space is only a low-level routine for the most common tasks when creating dbspaces. You can change or extend if you want.

Download inf_space.tar.gz

Adapting this for Ubuntu 5 years later

I have been trying to do some stuff on Ubuntu Linux.  However, some files/commands you use just don't exist there.

For example: rc.status, rc_status, rc_reset, rc_failed.

Are there equivalents to these in Ubuntu?  If I know what they do I could emulate them or decide to do without them altogether.

Suggestions?

Thanks

Why raw devices ?

Okay, this article is quite interesting and well written, but .. do I really
have to use raw devices mapped with "raw". I agree that it is crucial on
(other) unices, but as far as I understood, IDS 10.0 handles disks/partitions
like raw devices, if libaio.so is present - with the additional benfits of kaio.

cu
rok

Rok is right we open

Rok is right we open character and block devices in case of KAIO with the O_DIRECT flag.
This means the raw command on Linux is not needed since IDS 10.00

BTW - That's funny ...

because it was Sandor who told me as I met him at last year's Infobahn at Munich. I took the opportuninity and aske him JUST THAT .