softraid—1

最近在linux上做软raid时,需要检测raid的相关事件的发生。比如:添加备用盘、移除磁盘、raid降级等事件。最开始的时候是采用定时器方式,每隔一段时间就扫描raid superblock的更新时间,如果发生变化就检测一次。先不说superblock的updatetime是否准确,单单使用定时器轮询方式就感觉不好,希望能找到一种类似于中断的方式来处理。最开始时是想到raid事件的发生,内核肯定会知道然后会改变/proc/mdstat。所以如果检测/proc/mdstat就可以实现这个功能。查看md驱动也发现有类似说明:/** We have a system wide ‘event count’ that is incremented on any ‘interesting’ event, and readers of /proc/mdstat can use ‘poll’ or ‘select’ to find out when the event* count increases.* Events are:* start array, stop array, error, add device, remove device,* start build, activate spare*/但是对于如何检测/proc/mdstat的改变。我最开始是想到inotify。一是我们的内核已经支持(2.6.13 and later);二是没有用过inotify想试试。所以我使用inotify来检测/proc/mdstat发现,进行raid事情发生,但是inotify却没有返回事件。于是我走读内核发现,inotify所谓的事件发生是基于用户空间访问、修改的动作。对于procfs/sysfs这种内存文件系统,如果用户程序不访问文件,那么inotify是不能实现。inotify为什么不实现procfs/sysfs的主动推的动作,诱发inotify事件的发生。查看代码发现(2.6.18)中sysfs实现了sysfs_update_file来主动诱发inotify,但是在最新内核中没有发现该函数。看来只能是使用poll或者select来完成这个功能了。例子如下:int main(){struct pollfd fds;int fd;char buff[4096];while(1){fd = open(“/proc/mdstat”,O_RDONLY);if(fd < 0){printf(“open error %s/n”,strerror(errno));return errno;}

memset(&fds,0,sizeof(struct pollfd));fds.fd = fd;fds.events = POLLERR;if(poll(&fds,fd+1,-1) == -1)printf(“poll error %s/n”,strerror(errno));else{printf(“poll return/n”);//memset(buff,0,sizeof(buff));//read(fd,buff,sizeof(buff));}close(fd);}return 0;

}对于events查看内核函数:mdstat_poll只能是POLLERR 和POLLPRI。顺便将poll/select的内核实现看了看,下面以mdstat_poll为例讲解:static unsigned int mdstat_poll(struct file *filp, poll_table *wait){struct seq_file *m = filp->private_data;struct mdstat_info *mi = m->private;int mask;//这句话必须有poll_wait(filp, &md_event_waiters, wait);

/* always allow read *///无论何时使用POLLIN都会返回mask = POLLIN | POLLRDNORM;//只有这个条件成立,才会返回POLLERR | POLLPRIif (mi->event != atomic_read(&md_event_count)){mask |= POLLERR | POLLPRI;}return mask;}如果执行mdstat_poll没有返回POLLERR那么线程会休眠,等待poll的时间结束或者等待有人wait_up。在函数:void md_new_event(mddev_t *mddev){atomic_inc(&md_event_count);wake_up(&md_event_waiters);sysfs_notify(&mddev->kobj, NULL, “sync_action”);}EXPORT_SYMBOL_GPL(md_new_event);

/* Alternate version that can be called from interrupts* when calling sysfs_notify isn’t needed.*/static void md_new_event_inintr(mddev_t *mddev){atomic_inc(&md_event_count);wake_up(&md_event_waiters);}只要有事件发生,调用上面两个函数,就会执行wake_up(&md_event_waiters);那么就会将等待POLLERR、POLLPRI事件的进程从休眠状态唤醒到可执行状态,进而返回用户控件。对于检测时间POLLIN,会立马返回的,因为没有任何条件需要。

对于检测procfs/sysfs中的文件的变化,目前看来只能是使用poll/select(没有实现的可以自己实现),使用inotify看来不行。在测试中发现对于添加备用盘和拔出备用盘(物理拔出),raid都不会检测到事件的发生。查看最新内核中的add_new_disk都没有调用md_new_event。这不知道是为什么?而且raid组成盘移除,如果没有读写操作,md是发现不了的,这也是个问题,不知道在最新内核中是否添加这个功能。

问题1:添加备用盘是没有事件发生的(在2.6.18内核中也不更新superblock,在后面内核中更新superblock)2:没有读写操作下,物理移除raid盘,md层驱动是不感知的3:查看最新内核中是否实现了procfs/sysfs中的主动推inotify动作,如果实现那么是如何实现的

漫无目的的生活就像出海航行而没有指南针

softraid—1

相关文章:

你感兴趣的文章:

标签云: