Raid 磁盘阵列管理

更新时间:
2024-03-14
下载文档

Raid 磁盘阵列管理

磁盘阵列(Redundant Array of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意。磁盘阵列是由很多价格便宜的磁盘,组成一个容量巨大的磁盘组,利用个别磁盘提供数据所产生加成效果提升整个磁盘系统效能。SylixOS 实现了软件 RAID 功能,配置灵活、管理方便,可以实现将几个物理磁盘合并成一个更大的虚拟设备,从而达到性能改进和数据冗余的目的。

SylixOS 中关于软件 RAID 磁盘阵列管理的内容主要在“libsylixos/SylixOS/fs/diskRaid”目录下,实现了 RAID0 与 RAID1 级别。

RAID 0

RAID 0 是最早出现的 RAID 模式,即 Data Stripping 数据分条技术,把连续的数据分散到多个磁盘上存取。当系统有数据请求就可以被多个磁盘并行的执行,每个磁盘执行属于它自己的那部分数据请求。这种数据上的并行操作可以充分利用总线的带宽,显著提高磁盘整体存取性能。因为读取和写入是在设备上并行完成的,读取和写入性能将会提高,这通常是运行 RAID 0 的主要原因。但 RAID 0 没有数据冗余和容错,如果驱动器出现故障,那么将无法恢复任何数据。其存储结构如下图所示。

在 SylixOS 中创建 RAID 0 类型磁盘阵列块设备的函数接口如下:

#include <SylixOS.h>
ULONG  API_DiskRiad0Create (PLW_BLK_DEV  pblkd[],
                                 UINT          uiNDisks,
                                 size_t        stStripe,
                                 PLW_BLK_DEV *ppblkDiskRaid);

函数 API_DiskRiad0Create 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误码。
  • 参数 pblkd[] 是物理块设备列表。
  • 参数 uiNDisks 是物理磁盘数量,只能为 2 块或者 4 块,二者选其一。
  • 参数 stStripe 是磁盘条带数量,必须是扇区字节数的 2 的指数倍,最好为 32KB。
  • 参数 ppblkDiskRaid 是返回的 RAID 虚拟磁盘。

API_DiskRiad0Create 函数将多个物理磁盘合并成一个更大的虚拟设备,阵列中所有的物理磁盘参数必须完全一致,例如磁盘大小、扇区大小等参数必须相同。函数中最终返回的 RAID 虚拟磁盘设备类型使用 LW_DISKRAID0_CB 结构描述,其具体结构如下:

typedef struct {
    LW_BLK_DEV                  DISKR_blkdRaid;            /* DISK CACHE 的控制块           */
    PLW_BLK_DEV                *DISKR_ppblkdDisk;          /*  阵列物理磁盘列表               */
    UINT                        DISKR_uiNDisks;            /*  阵列磁盘数量                  */
    UINT                        DISKR_uiDiskShift;         /*  磁盘 shift                  */
    UINT                        DISKR_uiDiskMask;          /*  磁盘掩码                     */
    UINT                        DISKR_uiStripeShift;       /*  条带基于扇区的 2 指数次方       */
    UINT                        DISKR_uiStripeMask;        /*  条带掩码                     */
} LW_DISKRAID0_CB;
typedef LW_DISKRAID0_CB    *PLW_DISKRAID0_CB;

磁盘 shift 和磁盘掩码都与组成阵列的磁盘数量有关,RAID 阵列的 BLK IO 控制块为最终向上表现出的虚拟设备,其中的读接口函数的具体实现如下:

static INT  __raid0DevRd (PLW_DISKRAID0_CB     pdiskr,
                          VOID                *pvBuffer,
                          ULONG                ulStartSector,
                          ULONG                ulSectorCount)
{
    PUCHAR  pucBuffer        = (PUCHAR)pvBuffer;
    ULONG   ulNSecPerStripe  = (ULONG)(1 << pdiskr->DISKR_uiStripeShift);
    ULONG   ulRdCount;
    ULONG   ulStripe;
    ULONG   ulSector;
    UINT    uiDisk;
    while (ulSectorCount) {
        ulStripe = ulStartSector >> pdiskr->DISKR_uiStripeShift;
        uiDisk    = (UINT)(ulStripe & pdiskr->DISKR_uiDiskMask);
        if (ulStartSector & pdiskr->DISKR_uiStripeMask) {
            ulRdCount = ulStartSector & pdiskr->DISKR_uiStripeMask;
            if (ulRdCount >= ulSectorCount) {
                ulRdCount  = ulSectorCount;
            }
        } else {
            if (ulSectorCount >= ulNSecPerStripe) {
                ulRdCount = ulNSecPerStripe;
            } else {
                ulRdCount = ulSectorCount;
            }
        }
        ulSector = ulStartSector >> pdiskr->DISKR_uiDiskShift;
        if (RAID_BLK_READ(pdiskr, uiDisk, pucBuffer, ulSector, ulRdCount)) {
            return  (PX_ERROR);
        }
        ulStartSector += ulRdCount;
        ulSectorCount -= ulRdCount;
        pucBuffer     += (ulRdCount * pdiskr->DISKR_blkdRaid.BLKD_ulBytesPerSector);
    }
    return  (ERROR_NONE);
}

读块设备时,将连续的扇区分割成连续的条带,并根据磁盘数量确定条带所在的磁盘号,从相应的磁盘中读出。写设备时与此类似,确定条带号和磁盘号后,写入相应的磁盘。

RAID 0 类型磁盘阵列块设备的删除函数接口如下:

#include <SylixOS.h>
INT  API_DiskRiad0Delete (PLW_BLK_DEV  pblkDiskRaid);

函数 API_DiskRiad0Delete 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 pblkDiskRaid 是之前创建的 RAID 0 虚拟磁盘。

RAID 1

RAID 1 称为磁盘镜像(Mirroring),一个具有全冗余的模式,如下图所示。RAID 1 可以用于两个或 2xN 个磁盘,并使用 0 块或更多的备用磁盘,每次写数据时会同时写入镜像盘。这种阵列可靠性很高,但其有效容量减小到总容量的一半,同时这些磁盘的大小应该相等,否则总容量只具有最小磁盘的大小。

在 SylixOS 中创建 RAID 1 类型磁盘阵列块设备的函数接口如下:

#include <SylixOS.h>
ULONG  API_DiskRiad1Create (PLW_BLK_DEV         pblkd[],
                            UINT                uiNDisks,
                            PLW_BLK_DEV        *ppblkDiskRaid);

函数 API_DiskRiad0Create 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误码。
  • 参数 pblkd[] 是物理块设备列表。
  • 参数 uiNDisks 是物理磁盘数量,只能为 2 块或者 4 块,二者选其一。
  • 参数 ppblkDiskRaid 是返回的 RAID 虚拟磁盘。

API_DiskRiad1Create 函数将多个物理磁盘合并成一个更大的虚拟设备,阵列中所有的物理磁盘参数必须完全一致,例如磁盘大小、扇区大小等参数必须相同。函数中最终返回的 RAID 虚拟磁盘设备类型使用 LW_DISKRAID1_CB 结构描述,其具体结构如下:

typedef struct {
    LW_BLK_DEV                DISKR_blkdRaid;       /*  DISK CACHE 的 BLK IO 控制块      */
    PLW_BLK_DEV              *DISKR_ppblkdDisk;     /*  阵列物理磁盘列表                   */
    UINT                      DISKR_uiNDisks;       /*  阵列磁盘数量                      */
} LW_DISKRAID1_CB;
typedef LW_DISKRAID1_CB    *PLW_DISKRAID1_CB;

磁盘 shift 和磁盘掩码都与组成阵列的磁盘数量有关,RAID 阵列的 BLK IO 控制块为最终向上表现出的虚拟设备,其中的读接口函数如下:

static INT  __raid1DevRd (PLW_DISKRAID1_CB       pdiskr,
                          VOID                 *pvBuffer,
                          ULONG                 ulStartSector,
                          ULONG                 ulSectorCount)
{
    INT  i;
    INT  iRet = ERROR_NONE;
    for (i = 0; i < pdiskr->DISKR_uiNDisks; i++) {
        if (RAID_BLK_READ(pdiskr, i, pvBuffer, ulStartSector, ulSectorCount)) {
            _DebugFormat(__ERRORMESSAGE_LEVEL,
 "RAID-1 system block disk %u error.\r\n", i);
            iRet = PX_ERROR;
        } else {
            break;
        }
    }
    return  (iRet);
}

读块设备时,只要从任意一个磁盘中读出即可。与此对应,RAID 1 的写操作需要对每一个磁盘进行相同的写操作。

RAID 1 类型磁盘阵列块设备的删除函数接口如下:

#include <SylixOS.h>
INT  API_DiskRiad1Delete (PLW_BLK_DEV      pblkDiskRaid);

函数 API_DiskRiad0Delete 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 pblkDiskRaid 是之前创建的 RAID 1 虚拟磁盘。

此外 SylixOS 还提供了 RAID 1 的磁盘拷贝接口,用于备份数据或从镜像磁盘上恢复数据。其函数原型如下:

#include <SylixOS.h>
ULONG  API_DiskRiad1Ghost (PLW_BLK_DEV      pblkDest,
                           PLW_BLK_DEV      pblkSrc,
                           ULONG             ulStartSector,
                           ULONG             ulSectorNum);

函数 API_DiskRiad1Ghost 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 pblkDest 是目的磁盘。
  • 参数 pblkSrc 是源磁盘。
  • 参数 ulStartSector 是起始扇区。
  • 参数 ulSectorNum 是扇区数量。
文档内容是否对您有所帮助?
有帮助
没帮助