Logical Volumes in AIX
James Santos
AIX provides the Logical Volume Manager (LVM) for managing disk storage. LVM gives administrators features that enhance system integrity, increase performance and, in some instances, simply make the administrator's life easier. This article reviews the fundamental features of LVM and explores two shell scripts that can aid in the management of LVM-based storage.
LVM Features Although LVM uses hardware-level storage in much the same manner as conventional UNIX file systems, LVM operates at a higher level of abstraction and provides considerably more flexibility in how those physical resources are used. For simplicity, LVM's features fit conveniently into integrity-enhancing features, performance-enhancing features, and the traditional catch-all, other features.
Some of the LVM features that enhance integrity are:
- Disk mirroring
- Reallocation of bad blocks
- Read after write verification
Some of the features of the LVM that can enhance performance are:
- Disk striping
- Placement of logical volumes (where filesystems are created; much like disk partitions in other UNIX systems) into specific regions of the disk (i.e., center region of the disk gives the highest performance by minimizing the disk read/write head movement)
- Disk defragmentation
Other features include:
- Dynamic expansion of filesystems (dynamic method minimizes downtime)
- Placement of filesystems over multiple disks
Listings 1 and 2 are shell programs that help you manage physical and logical volumes. The second program (crmklvall.ksh) uses the output of the first program (listpvlv.ksh). Both have been tested with AIX 4.1.4.0 and AIX 4.2.0.0. (All listings for this article can be found at ftp.mfi.com in /pub/sysadmin/.)
listpvlv.ksh AIX provides various commands for managing logical and physical volumes that give the administrator a wealth of information. From my day-to-day experience with managing disks in AIX systems, I have found that there is some basic information that I use quite often. To get this information, though, I need to execute multiple commands. I wrote the listpvlv.ksh shell program (Listing 1) to address this problem by printing out the most useful information.
The program produces output similar to the following:
Host : dev01
Date : 11/11/97 16:45:58
Information for hdisk0
Part of Volume Group : rootvg
PP Size : 8 megabyte(s)
Total PPs : 537 (4296 megabytes)
Free PPs : 57 (456 megabytes)
Size (No Size (No
C D LV Name Distribution of LPs) of PPs) FS Name
1 1 lnts 97..53..00..34..00 184 184 /lnts
1 1 hd5 01..00..00..00..00 1 1 N/A
1 1 hd2 10..54..75..57..49 245 245 /usr
1 1 hd6 00..00..32..00..00 32 32 N/A
1 1 hd1 00..00..00..06..00 6 6 /home
1 1 hd3 00..00..00..04..00 4 4 /tmp
1 1 hd9var 00..00..00..03..00 3 3 /var
1 1 hd4 00..00..00..00..04 4 4 /
1 1 hd8 00..00..00..00..01 1 1 N/A
. .
. .
. .
. .
Information for hdisk3
Part of Volume Group : testareavg
PP Size : 8 megabyte(s)
Total PPs : 537 (4296 megabytes)
Free PPs : 215 (1720 megabytes)
Size (No Size (No
C D LV Name Distribution of LPs) of PPs) FS Name
1 1 prd02_data01 47..25..85..53..00 210 210 N/A
1 1 prd02_data01 08..32..00..00..00 40 40 N/A
1 1 prd01_idx01 00..21..00..00..00 21 21 N/A
1 2 arealv2 00..05..00..00..00 5 5 N/A
1 2S arealv3 00..04..00..00..00 4 4 N/A
1 2S cabtest1 00..08..00..00..00 8 8 N/A
1 2S cabtest2 00..04..00..00..00 4 4 N/A
1 2 arealv4 00..08..17..00..00 25 25 /cabfs
2 2 arealv1 00..00..05..00..00 5 5 N/A
. .
. .
. .
. .
The report is organized by physical volume (PV). It provides summary information about each PV on the system and lists all the logical volumes (LV). It also provides information such as mirroring (the "C" column), the number of disks the LVs reside on (the "D" column), and whether or not the LV is striped. An "S" beside the number in the "D" column indicates a striped LV. The syntax of the program is as follows:
listpvlv.ksh [-p] [-o filename] [hdiskn]
-p displays the LV size as the number of physical partitions (PP) (default is in megabytes). -o filename sends the output of the program to the filename given (default output is stdout). hdiskn allows you to specify which PVs to display in the report (default is all PVs). All arguments are optional.
The program starts by parsing the command line options using getopts. getopts gives the program flexibility in handling arguments. Combine getopts with the case..esac construct within a "while" loop and you have a convenient way of validating arguments entered by the user. Notice that an exec 1>$OPTARG is called if the user entered -o filename as an argument. Running this command within a Korn shell script allows you to redirect file descriptors. In this case I am redirecting stdout to the value of the $OPTARG variable. This variable was initialized by getopts with the filename that the user entered with the -o argument. Finally, a shift $(($OPTIND -1)) is done after the "while" loop that contains the getopts. This shift is needed to point $1, $2 and so on to the hdisk(s) arguments.
If the user entered hdisk argument(s), the program checks for the validity of these parameters. If the user entered an invalid hdisk, then an error message is displayed.
The main "for" loop processes one PV at a time. Within the loop, all the corresponding LVs within each PV are processed. The first awk builds the PV information and prints out the volume group, the PP size, the total, and the free hdisk space (please refer to the sample output).
Next, the value of the PPSIZEMULT variable is set. This variable is used later as a multiplier in computing the LV size. If the user did not specify a -p as a parameter (-m is the default), then the multiplier is set equal to the PP size of the hdisk; otherwise, the multiplier is set to 1.
The second awk segment extracts the LV details. The BEGIN section of this awk segment prints out the headings, then computes the size of the LV. Note that it uses the awk getline function to execute an external command and save the output of the command to the COPY_STR_LINE variable. This variable would contain information indicating whether the LV is mirrored (multiple copies) or striped. The awk split function is then used to split the COPY_STR_LINE variable into the CSLARRAY array using the field separator (FS) as the delimiter. The size of the LV is then computed using the PPSIZEMULT variable discussed earlier.
The second element of the CSLARRAY[] array, CSLARRAY[2], contains the value of the "C" column in the report. A value of more than 1 indicates that the LV is mirrored. The fifth element of the array, CSLARRAY[5], indicates whether the LV is striped.
The getline function is used again to get the number of disks that the LV spans (the "D" column in the report). lslv -l "$1" ($1 contains the LV name) prints out all the PVs that the LV resides on. tail +3 removes the header section. wc -l gives you the number of lines, which, in this case, is the number of PVs that the LV is defined on. getline will assign this number to the NO_OF_DISKS variable. This variable, together with other variables initialized earlier, will be used by the printf function to print the various information for the LV.
crmklvall.ksh There are instances when you have to recreate logical volume definitions from one machine to another. One case is in disaster recovery. For example, at my client, we simulate a disaster by pretending that our data center has gone down. We then proceed to a predetermined site and start building our production environment. The crmklvall.ksh shell program (Listing 2) can help in this rebuilding. It reverse engineers the creation of LVs by creating a shell script (mklvall.sh) that contains mklv commands.
Going back to my example, we start building the environment by loading our mksysb tape on a machine that is identical to our production machine. We then run the mklvall.sh shell script. The actual mklvall.sh script that we use is edited to include only those LVs that we want to recreate. We then build our Sybase environment on top of these newly created LVs. This program is also useful when you need to duplicate the logical volume definitions from one machine to another. I often have to migrate a Sybase environment between machines, and the crmklvall.ksh shell program has become quite handy.
The program produces output similar to the following:
#*************************************************************
#* For Host : dev01
#* Date : 11/12/97 17:06:19
#* Description : This script contains mklv commands to create
#* the LVs that existed when crmklvall.ksh was
#* run on this host (dev01).
#*
#* crmklvall.ksh generates this script. All
#* existing LVs are included here (including
#* the LVs that are automatically created when
#* AIX is installed). For safety reasons, all
#* lines in this script are commented out.
#*
#* Uncomment only the lines that you need.
#*************************************************************
. .
. .
. .
. .
#mklv -y intradb01datlv -c 1 sybasevg 25 hdisk1
#mklv -y intradb01idxlv -c 1 sybasevg 6 hdisk1
#mklv -y intradb01loglv -c 1 sybasevg 6 hdisk1
#mklv -y intradb02datlv -c 1 sybasevg 15 hdisk1
#mklv -y intradb02idxlv -c 1 sybasevg 6 hdisk1
#mklv -y intradb02loglv -c 1 sybasevg 6 hdisk1
#mklv -y intraserv_mast -c 1 sybasevg 3 hdisk1
#mklv -y intraserv_proc -c 1 sybasevg 3 hdisk1
#mklv -y intraserv_secu -c 1 sybasevg 3 hdisk1
#mklv -y prd01_data01 -c 1 testareavg 155 hdisk2
#mklv -y prd01_idx01 -c 1 testareavg 21 hdisk3
#mklv -y prd01_log01 -c 1 sybasevg 21 hdisk1
#mklv -y prd01rms_mast01 -c 1 sybasevg 3 hdisk1
#mklv -y prd01rms_proc01 -c 1 sybasevg 3 hdisk1
#mklv -y prd02_data01 -c 1 testareavg 40 hdisk3
#extendlv prd02_data01 210 hdisk3
#mklv -y prd02_idx01 -c 1 sybasevg 79 hdisk1
#mklv -y prd02_log01 -c 1 testareavg 21 hdisk2
#mklv -y sybaselv -c 1 sybasevg 50 hdisk1
#mklv -y tempdblv -c 1 sybasevg 57 hdisk1
#mklv -y arealv2 -c 1 testareavg 7 hdisk2
#extendlv arealv2 5 hdisk3
#mklv -y arealv3 S64K testareavg 8 hdisk2 hdisk3
#mklv -y arealv4 -c 1 testareavg 10 hdisk2
#extendlv arealv4 25 hdisk3
#mklv -y cabtest1 -S128K testareavg 16 hdisk2 hdisk3
#mklv -y cabtest2 -S16K testareavg 8 hdisk2 hdisk3
#mklv -y arealv1 -c 2 testareavg 5 hdisk2 hdisk3
. .
. .
. .
. .
The output is a shell script with commands to create LVs. The mklv command that is generated takes into consideration whether the LVs are mirrored or striped or are extended to another PV. If it is striped, the correct stripe size is used. It does not, however, retain the original positioning of the LV within the PV (e.g., center, inner middle, etc.), and it was not designed for LVs created with a non-strict allocation policy (-s n option of mklv). The syntax of the program is as follows:
crmklvall.ksh [-o filename]
-o filename sends the output of the program to the filename given (default output file is mklvall.sh).
The program starts by parsing the command line using getopts. The user has the option of overriding the default output file by running the command with the -o filename argument. (For more information on getopts, please refer to the discussion of the listpvlv.ksh shell program.)
The first awk parses the $TMPFILE (which is the output of listpvlv -p). Next, the output of this awk is sorted with the primary sort key being the mirroring information (the "C" column in the listpvlv.ksh output). The output of the sort is processed by a second awk.
This next awk is where most of the processing takes place. The main if/else checks whether the LV currently being processed is mirrored or not. If it is not, then the program checks whether the LV is striped or not. Different processing occurs depending on this last test. For striped LVs, the program does not print the mklv command immediately. It builds two arrays. The first one, STR_ARRAY_SZ[], contains the number of PPs used in each of the PVs that are part of the striped set. The second one, STR_ARRAY_PV[], contains the names of all the hdisks that are part of the striped set. If the next record processed pertains to an LV that is no longer part of the previous striped set, then a break process occurs. Note that this break process occurs in the program if the if (STR_ARRAY_PV[1] != "") test evaluates to true. If so, then the print_strlv() function is called. (This test is done in four parts of the program.)
If the LV is not striped, the program prints the mklv (print_line() with 1dsk argument). An extendlv is printed by the program (print_line() with ext argument) if appropriate to the next LV being processed by awk. If the LV is mirrored, then the print_line() function is called. The parameter passed to this function depends on whether the number of LV copies is two or three. If there are two, it passes the 2mir argument; if there are three, it passes the 3mir argument.
Let's now turn our attention to the two functions mentioned in this discussion: print_line() and print_strlv().
Note that the print_line() function contains the different printf() routines for (a) a single-disk mklv, (b) an extendlv, (c) a two-copy mklv, and (d) a three-copy mklv. The function accepts different arguments (discussed in the previous paragraphs) that tell it which printf() routine to execute.
Within the print_strlv() function, the total size of the striped LV is computed. It adds the size (number of PPs) of the current LV being processed with all of the values stored in the STR_ARRAY_SZ[] array. As mentioned earlier, this array contains the number of PPs used in the other PVs that are part of the same striped set. Another way of computing the total size of the striped LV, without using the array, is by multiplying the size of the current LV by the number of hdisks that are a part of the same striped set. This method can be used since the number of PPs used should be the same in all of the PVs within the same stripe set.
Also, within the print_strlv() function, the awk getline() function is utilized to get the stripe size used to create the stripe set. lslv "STRLV" (STRLV contains the LV name) prints out a detailed report about the LV. tail -1 discards the output of the lslv except the last line. cut -c21-24 gives the stripe size. getline will assign this value to the STRIPE_SIZE variable that, together with other variables, is used by the printf() function when printing the mklv for the striped LV. The mklv that is printed does not yet contain all of the names of the PVs that are a part of the same stripe set. The next routine handles that. Notice that the printf() does not issue a line feed yet.
The next "for" loop processes the STR_ARRAY_PV[] array. As mentioned earlier, this array contains the names of all the other PVs that are part of the same stripe set. The printf() within this "for" loop takes care of printing the rest of the PV names within the same stripe set.
Conclusion Although the AIX graphical admin tool, smit, includes features for managing LVM, the two tools presented in this article augment smit. These shell scripts have become part of my regular toolkit for the management of AIX systems, and have served me well in that role. As a Sys Admin reader, you are free to use and modify these scripts as you see fit (at your own risk, of course), but you june not sell the code or incorporate it into a commercial product without my further consent.
Other Resources AIX Storage Management. IBM Publication GG24-4484-00
AIX Versions 3.2 and 4.1 Performance and Tuning Guide. IBM Publication SC23-2365-03.
Ess ential System Administration, Second Edition by AEleen Frisch. O'Reilly & Associates, Inc.
About the Author
James M. Santos is an indepentdent consultant specializing in systems administration and performance tuning. He is the President of his consulting company, Cornerstone Systems Solutions, Inc. He can be reached at: jamessantos@usa.net.
|