ASM disk header is probably the best known piece of ASM metadata. Chances are you learned about it when it was damaged or lost and hopefully Oracle Support was able to get you up and running. In this post I will try to explain why ASM disk header is important and what it contains.
Block zero
ASM disks are formatted into Allocation Units. Some Allocation units contain ASM metadata and some contain database data. Allocation units that contain ASM metadata are formatted into ASM metadata blocks. Allocation unit 0 is at the beginning of an ASM disk and it always contain ASM metadata. The very first block (block 0) of Allocation Unit 0 contains the ASM disk header.
ASM disk header contents
Most of the data in the ASM disk header is of interest to that disk only. But some information in the ASM disk header is relevant to the whole disk group and some is even relevant to the whole cluster!
Let's use kfed to have a closer look at block 0 of an ASMLIB disk on Linux.
$ kfed read /dev/oracleasm/disks/ASMD1
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt: 1 ; 0x003: 0x01
kfbh.block.blk: 0 ; 0x004: T=0 NUMB=0x0
kfbh.block.obj: 2147483648 ; 0x008: TYPE=0x8 NUMB=0x0
kfbh.check: 473773689 ; 0x00c: 0x1c3d3679
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
kfbh.spare1: 0 ; 0x018: 0x00000000
kfbh.spare2: 0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr: ORCLDISKASMD1 ; 0x000: length=13
kfdhdb.driver.reserved[0]: 1145918273 ; 0x008: 0x444d5341
kfdhdb.driver.reserved[1]: 49 ; 0x00c: 0x00000031
kfdhdb.driver.reserved[2]: 0 ; 0x010: 0x00000000
kfdhdb.driver.reserved[3]: 0 ; 0x014: 0x00000000
kfdhdb.driver.reserved[4]: 0 ; 0x018: 0x00000000
kfdhdb.driver.reserved[5]: 0 ; 0x01c: 0x00000000
kfdhdb.compat: 186646528 ; 0x020: 0x0b200000
kfdhdb.dsknum: 0 ; 0x024: 0x0000
kfdhdb.grptyp: 1 ; 0x026: KFDGTP_EXTERNAL
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname: ASMD1 ; 0x028: length=5
kfdhdb.grpname: DATA ; 0x048: length=4
kfdhdb.fgname: ASMD1 ; 0x068: length=5
...
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt: 1 ; 0x003: 0x01
kfbh.block.blk: 0 ; 0x004: T=0 NUMB=0x0
kfbh.block.obj: 2147483648 ; 0x008: TYPE=0x8 NUMB=0x0
kfbh.check: 473773689 ; 0x00c: 0x1c3d3679
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
kfbh.spare1: 0 ; 0x018: 0x00000000
kfbh.spare2: 0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr: ORCLDISKASMD1 ; 0x000: length=13
kfdhdb.driver.reserved[0]: 1145918273 ; 0x008: 0x444d5341
kfdhdb.driver.reserved[1]: 49 ; 0x00c: 0x00000031
kfdhdb.driver.reserved[2]: 0 ; 0x010: 0x00000000
kfdhdb.driver.reserved[3]: 0 ; 0x014: 0x00000000
kfdhdb.driver.reserved[4]: 0 ; 0x018: 0x00000000
kfdhdb.driver.reserved[5]: 0 ; 0x01c: 0x00000000
kfdhdb.compat: 186646528 ; 0x020: 0x0b200000
kfdhdb.dsknum: 0 ; 0x024: 0x0000
kfdhdb.grptyp: 1 ; 0x026: KFDGTP_EXTERNAL
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname: ASMD1 ; 0x028: length=5
kfdhdb.grpname: DATA ; 0x048: length=4
kfdhdb.fgname: ASMD1 ; 0x068: length=5
...
The result of the above kfed command shows us that this ASM block has two types of data - block header data - prefixed with kfbh, and ASM disk header data - prefixed with kfdhdb. In fact, every ASM metadata block will have the block header data plus the data specific to its block type.
Important ASM metadata block 0 header data
Data type | Value |
---|---|
kfbh.endian | System endianness. 0 - big endian, 1 - little endian. |
kfbh.type | ASM block type. KFBTYP_DISKHEAD tells us this is an ASM disk header block. |
kfbh.block.blk | ASM block number. Note the ASM disk header is block number 0. |
Important ASM disk header specific data
Data type | Value |
---|---|
kfdhdb.driver.provstr | ORCLDISK+[ASM disk name] for ASMLIB disks. ORCLDISK for non-ASMLIB disks. |
kfdhdb.dsknum | ASM disk number. |
kfdhdb.grptyp | Disk group redundancy. KFDGTP_EXTERNAL - external, KFDGTP_NORMAL - normal, KFDGTP_HIGH - high. |
kfdhdb.hdrsts | ASM disk header status. For possible values see V$ASM_DISK.HEADER_STATUS. |
kfdhdb.dskname | ASM disk name. |
kfdhdb.grpname | ASM disk group name. |
kfdhdb.fgname | ASM failgroup name. |
kfdhdb.crestmp.hi|lo | The date and time disk was added to the disk group. |
kfdhdb.mntstmp.hi|lo | Last time the disk was mounted. |
kfdhdb.secsize | Disk sector size (bytes). |
kfdhdb.blksize | ASM metadata block size (bytes). |
kfdhdb.ausize | Alloocation unit size (bytes). 1 MB is the default allocation unit size. |
kfdhdb.dsksize | Disk size (allocation units). In this case the disk size is 10239 MB. |
kfdhdb.fstlocn | Pointer to ASM Free Space Table. 1 = ASM block 1 in this allocation unit. |
kfdhdb.altlocn | Pointer to ASM Allocation Table. 2 = ASM block 2 in this allocation unit. |
kfdhdb.f1b1locn | Pointer to ASM File Directory. 2 = allocation unit 2. |
kfdhdb.dbcompat | Minimum database version. 0x0a100000 = 10.1. |
kfdhdb.grpstmp.hi|lo | The date and time the disk group was created. |
kfdhdb.vfstart|vfend | Start and end allocation unit number for the clusterware voting disk. If this is zero, the disk does not have voting disk data. Version 11.2 and later only. |
kfdhdb.spfile | Allocation unit number of the ASM spfile. Version 11.2 and later only. |
kfdhdb.spfflg | ASM spfile flag. If this is 1, the ASM spfile is on this disk in allocation unit kfdhdb.spfile. Version 11.2 and later only. |
ASM disk header backup
In ASM versions 11.1.0.7 and later, the ASM disk header block is backed up in the second last ASM metadata block in the allocation unit 1. To work out the second last block number we need to know the allocation unit size and ASM metadata block size.
I talked about this in my post on kfed, but let's do that again - get those values from the block header and calculate the second last block number in allocation unit 1:
$ ausize=`kfed read /dev/oracleasm/disks/ASMD1 | grep ausize | tr -s ' ' | cut -d' ' -f2`
$ blksize=`kfed read /dev/oracleasm/disks/ASMD1 | grep blksize | tr -s ' ' | cut -d' ' -f2`
$ let n=$ausize/$blksize-2
$ echo $n
254
$ kfed read /dev/oracleasm/disks/ASMD1 aun=1 blkn=254
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt: 1 ; 0x003: 0x01
kfbh.block.blk: 0 ; 0x004: T=0 NUMB=0x0
kfbh.block.obj: 2147483648 ; 0x008: TYPE=0x8 NUMB=0x0
kfbh.check: 473773689 ; 0x00c: 0x1c3d3679
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
kfbh.spare1: 0 ; 0x018: 0x00000000
kfbh.spare2: 0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr: ORCLDISKASMD1 ; 0x000: length=13
...
kfdhdb.dsknum: 0 ; 0x024: 0x0000
kfdhdb.grptyp: 1 ; 0x026: KFDGTP_EXTERNAL
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname: ASMD1 ; 0x028: length=5
kfdhdb.grpname: DATA ; 0x048: length=4
kfdhdb.fgname: ASMD1 ; 0x068: length=5
...
$ blksize=`kfed read /dev/oracleasm/disks/ASMD1 | grep blksize | tr -s ' ' | cut -d' ' -f2`
$ let n=$ausize/$blksize-2
$ echo $n
254
$ kfed read /dev/oracleasm/disks/ASMD1 aun=1 blkn=254
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt: 1 ; 0x003: 0x01
kfbh.block.blk: 0 ; 0x004: T=0 NUMB=0x0
kfbh.block.obj: 2147483648 ; 0x008: TYPE=0x8 NUMB=0x0
kfbh.check: 473773689 ; 0x00c: 0x1c3d3679
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
kfbh.spare1: 0 ; 0x018: 0x00000000
kfbh.spare2: 0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr: ORCLDISKASMD1 ; 0x000: length=13
...
kfdhdb.dsknum: 0 ; 0x024: 0x0000
kfdhdb.grptyp: 1 ; 0x026: KFDGTP_EXTERNAL
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname: ASMD1 ; 0x028: length=5
kfdhdb.grpname: DATA ; 0x048: length=4
kfdhdb.fgname: ASMD1 ; 0x068: length=5
...
So we see the same contents as in block 0 in allocation unit 0.
This can be very handy when the disk header is damaged or lost. All we have to do is run kfed repair [disk_name], and specify the allocation unit size if the value is not default (1MB). But as I said in the kfed post, please do not do this on your own - seek Oracle Support assistance if you suspect problems with ASM disk header.
ASM disk header in Exadata
ASM disks in Exadata are not exposed to the OS via device names. Instead they can be accessed via special name - "o/[IP address]
Let's have a look at the ASM disk header on an Exadata disk:
$ kfed read o/192.168.10.9/DBFS_DG_CD_03_exadatacel01
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
...
kfdhdb.dskname:DBFS_DG_CD_03_EXADATACEL01 ; 0x028: length=26
kfdhdb.grpname: DBFS_DG ; 0x048: length=7
kfdhdb.fgname: EXADATACEL01 ; 0x068: length=12
...
kfdhdb.ausize: 4194304 ; 0x0bc: 0x00400000
...
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
...
kfdhdb.dskname:DBFS_DG_CD_03_EXADATACEL01 ; 0x028: length=26
kfdhdb.grpname: DBFS_DG ; 0x048: length=7
kfdhdb.fgname: EXADATACEL01 ; 0x068: length=12
...
kfdhdb.ausize: 4194304 ; 0x0bc: 0x00400000
...
Some Exadata specific values in the ASM disk header are as follows:
- ASM disk name that consists of the disk group name (DBFS_DG), cell disk label (CD), cell disk number (3) and the storage cell name (exadatacel01)
- Failgroup name is the same as the storage cell name
- Default allocation unit size in Exadata is 4 MB
ASM disk header contains the metadata essential for the operation and availability of an ASM disk group. To prevent the loss and accidental damage of the ASM disk header, Oracle recommends to protect it by partitioning the disk - thus 'moving' it away from the physical beginning of the disk. The ASM disk header in Exadata is protected by not exposing it to the database server OS. In ASM version 11.1.0.7 and later, the ASM disk header is further protected by maintaining a copy in allocation unit 1.