虚拟磁盘的一些东东
如何让用户理解Linux下的挂载这个很重要的概念。因为这个他们使用的windows系统里是不存在的。
同时也要让他们掌握如何使用fdisk和mkfs这两个非常重要的工具。于是现场演示就极为重要了。
暂时我还没有发现谁的笔记本上搁上两个硬盘,即使我有,也不见得用户的机器上有。因此如何能够非常真实的现场演示这两个命令就是一个问题。
以前我的一个办法就是 采用iSCSI的方式,这样我想要多少个硬盘,就有多少个硬盘,完全真实环境,决不掺假,用户也看得真切。
但是,我如何给用户搭建这样的环境呢?所以自己用用挺好,给用户实验,等于加重我的负担。不能考虑。
还有一个方式是用ramdisk,他应该说没有什么缺点,因为他本身就是一个块设备--把内存当设备用。只是有点奢侈,同时呢,因为ramdisk不大,不设置ramdisk_size核心参数的情况下,不会超过64M。那这样如果我要演示分几个分区的话,恐怕有点力不从心。
另外一个常用的方式是用loop设备,不过这个只能用来演示mkfs命令的使用,因为loop设备是不具有分区功能的设备,所以演示fdisk也没戏。
今天快下班的时候,请教了这个问题,提出了两种可能性:
- 有没有可能在loop上搭建raid,或者LVM,或者直接md设备(dmsetup)
- linux设备驱动编程一书中提到了sbull设备驱动可以一用,不过默认只有512k,但是可以修改源代码而达到需求。
第一个方案我以前演示RAID,LVM的时候用过,当然也没有去做分区了。所以我暂时还不知道;而第二个方案我压根就考虑不到,虽然linux设备驱动编程一书我也看了前面两章,但毕竟我还没有到能看懂的水平,所以作罢了。
但是不管如何,今天我需要测试这两种方案。
对于一个方案,搭建raid,邹大侠提到可以用dmsetup,而我想到的是mdadm工具。我不太清楚如何用dmsetup的方式来作,我只是知道dmsetup是device-mapper的一个工具,我折腾了半天,也只会dmsetup create devicename /dev/loop1 ,接下来如何创建一个RAID就不得而知了。这篇 Right To Your Own Devices的文章提到了dmsetup的使用,也是用loop设备,但是却没有发现如何创建一个RAID设备,而单纯创建一个dmsetup设备,fdisk的时候还是会报错。
# dmsetup create new /dev/loop1
# dmsetup info new
Name: new
State: ACTIVE
Tables present: None
Open count: 0
Event number: 0
Major, minor: 253, 4
Number of targets: 0
#fdisk /dev/mapper/new
Unable to read /dev/mapper/new
所以还需要继续请教邹大侠,或者有哪位知道如何处理的,请给我留言。
dmsetup不会用,mdadm还是会一点的,所以记录下mdadm是如何做这件事情的。
用mdadm在loop设备上搭建raid
#dd if=/dev/zero of=hd1 bs=1M seek=299 count=1
#dd if=/dev/zero of=hd2 bs=1M seek=299 count=1
#dd if=/dev/zero of=hd3 bs=1M seek=299 count=1
#losetup /dev/loop1 hd1 && losetup /dev/loop2 hd2 && losetup /dev/loop3 hd3
# ls -lh hd*
-rw-r–r– 1 root root 300M 4月 6 17:44 hd1
-rw-r–r– 1 root root 300M 4月 6 17:44 hd2
-rw-r–r– 1 root root 300M 4月 6 17:44 hd3
[root@localhost tmp]# mdadm -C /dev/mdp0 –level=raid0 –raid-devices=3 –auto=m
dp /dev/loop1 /dev/loop2 /dev/loop3
mdadm: /dev/loop1 appears to be part of a raid array:
level=raid5 devices=3 ctime=Fri Apr 6 23:10:46 2007
mdadm: /dev/loop2 appears to be part of a raid array:
level=raid5 devices=3 ctime=Fri Apr 6 23:10:46 2007
mdadm: /dev/loop3 appears to be part of a raid array:
level=raid5 devices=3 ctime=Fri Apr 6 23:10:46 2007
Continue creating array? y
mdadm: array /dev/mdp0 started.
[root@localhost tmp]# ls -l /dev/mdp0*
mdp0p1 mdp0p2 mdp0p3 mdp0p4
[root@localhost tmp]# fdisk /dev/mdp0
[root@localhost tmp]# mkfs /dev/mdp0p1
[root@localhost tmp]# mount /dev/mdp0p1 /misc
[root@localhost tmp]# df
……………………..
/dev/mdp0p1 18909 166 17767 1% /misc
OK,到这里,mdadm可以得到我们的效果。注意两点:
1)创建md设备的时候,因为我的系统不支持raid5,所以我选择了raid0,你可以选择其他模式。
2)mdx设备并不具备分区(partition)功能,mdpx设备才具备。因此在创建设备的时候,–auto=mdp是必不可少的。
既然raid0可以,我想那最少我可以创建一个loop设备来达到这个效果,实验如下:
[root@localhost tmp]# dd if=/dev/zero of=hd4 bs=1M seek=19 count=1
[root@localhost tmp]# losetup /dev/loop4 hd4
[root@localhost tmp]# mdadm -C /dev/mdp1 -l raid0 -n 1 –auto=mdp /dev/loop4
mdadm: ’1′ is an unusual number of drives for an array, so it is probably
a mistake. If you really mean it you will need to specify –force before
setting the number of drives.
[root@localhost tmp]# mdadm -C /dev/mdp1 -l raid0 -n 1 –auto=mdp /dev/loop4 –force
mdadm: array /dev/mdp1 started.
[root@localhost tmp]# fdisk /dev/mdp1
[root@localhost tmp]# mkfs.ext3 /dev/mdp1p1
[root@localhost tmp]# mount /dev/mdp1p1 /misc
[root@localhost tmp]# df
………………..
/dev/mdp1p1 19762 1202 17540 7% /misc
使用sbull设备
首先下载 linux设备驱动编程中的实例代码
#tar -xzf example.tar.gz
#cd example/sbull
#make
#insmod -f sbull.ko
#dmesg
………….
EXT3-fs: mounted filesystem with ordered data mode.
sbulla: unknown partition table
sbullb: unknown partition table
sbullc: unknown partition table
sbulld: unknown partition table
注意两点
1)默认分配四个设备,每一个设备的大小是512个字节。我们可以修改它。打开sbull.c文件,第32行
static int nsectors = 1024; /* How big the drive is */
修改为
static int nsectors = 102400; /* How big the drive is */
默认的扇区大小在前面有定义为512byte。注意,这个设备的大小不要超过物理内存的大小。
2)如果编译的时候给出类似下面的错误
end_that_request_last too few arguments
则说明你的核心版本太高了,end_that_request_last由原来的一个参数增加了一个int的参数, 打开sbull.c,定位181类,找到类似这样一行
end_that_request_last(req);
修改为
end_that_request_last(req,0);
具体这个参数的含义,见下面的源代码:
#cat usr/src/linux/drivers/block/ll_rw_blk.c
void end_that_request_last(struct request *req)
{
struct gendisk *disk = req->rq_disk;
struct completion *waiting = req->waiting;
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
if (disk && blk_fs_request(req)) {
unsigned long duration = jiffies – req->start_time;
switch (rq_data_dir(req)) {
case WRITE:
disk_stat_inc(disk, writes);
disk_stat_add(disk, write_ticks, duration);
break;
case READ:
disk_stat_inc(disk, reads);
disk_stat_add(disk, read_ticks, duration);
break;
}
disk_round_stats(disk);
disk->in_flight–;
}
__blk_put_request(req->q, req);
/* Do this LAST! The structure may be freed immediately afterwards */
if (waiting)
complete(waiting);
}
后记:这个帖子是一边向邹大侠请教,一边写的。向他讨教了dmsetup的问题,他谦虚的说他也是对dmsetup一只半解。他觉得dm应该不支持 partition。dmsetup作为device-mapper软件包的工具,其功能应该和device-mapper联系在一起的。而“device-mapper在核心内部维护了一张设备映射表以及映射规则,每次块设备访问操作都通过查询这张表来向下面真正的块设备发起I/O请求。”
没有评论▼