[kernel] 在release方法里,而不是flush方法里释放
做一个文件系统(姑且叫它“蝗虫文件系统“),需要在进程退出时自动删除它打开的文件。另外此文件还支持poll(我自己做的,一般的文件系统不支持),支持poll当然需要等待队列,所以我把一个等待队列放在文件对应的struct inode里,实现该文件struct file_operations里的flush方法,在flush时删除文件并释放该等待队列(kfree)。
在把多个文件句柄加入epoll里的时候,这些文件句柄对应的inode上的等待队列要被epoll挂在一个数据结构上(struct eppoll_entry),当进程退出,这些等待队列当然要从数据结构上拿掉,但是,这些等待队列已经被我kfree了,所以panic。看来把kfree放在flush是不行了,那放哪儿?有哪个调用是比eventpoll_release发生的更晚的?有!
这样做似乎一切顺利,直到应用程序开始使用epoll:先在蝗虫文件系统里创建几个文件,再把它们的fd放入epoll(epoll_ctl),然后进程退出,如此多来几次,内核就panic了。还好我用的是QEMU,可以清楚看见在什么地方panic的,结果是 __fput --> eventpoll_release --> eventpoll_release_file --> ep_remove --> ep_unregister_pollwait --> remove_wait_queue,看看ep_unregister_pollwait的代码:
[fs/eventpoll.c --> ep_unregister_pollwait]
1109 static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
1110 {
1111 int nwait;
1112 struct list_head *lsthead = &epi->pwqlist;
1113 struct eppoll_entry *pwq;
1114
1115 /* This is called without locks, so we need the atomic exchange */
1116 nwait = xchg(&epi->nwait, 0);
1117
1118 if (nwait) {
1119 while (!list_empty(lsthead)) {
1120 pwq = list_entry(lsthead->next, struct eppoll_entry, llink);
1121
1122 ep_list_del(&pwq->llink);
1123 remove_wait_queue(pwq->whead, &pwq->wait);
1124 kmem_cache_free(pwq_cache, pwq);
1125 }
1126 }
1127 }
[fs/file_table.c --> __fput]
153 void fastcall __fput(struct file *file)
154 {
155 struct dentry *dentry = file->f_dentry;
156 struct vfsmount *mnt = file->f_vfsmnt;
157 struct inode *inode = dentry->d_inode;
158
159 might_sleep();
160
161 fsnotify_close(file);
162 /*
163 * The function eventpoll_release() should be the first called
164 * in the file cleanup chain.
165 */
166 eventpoll_release(file);
167 locks_remove_flock(file);
168
169 if (file->f_op && file->f_op->release)
170 file->f_op->release(inode, file);
171 security_file_free(file);
172 if (unlikely(inode->i_cdev != NULL))
173 cdev_put(inode->i_cdev);
174 fops_put(file->f_op);
175 if (file->f_mode & FMODE_WRITE)
176 put_write_access(inode);
177 file_kill(file);
178 file->f_dentry = NULL;
179 file->f_vfsmnt = NULL;
180 file_free(file);
181 dput(dentry);
182 mntput(mnt);
183 }
struct file_operations里的release方法就是在epoll释放之后调用的,所以应该把kfree挪到release里去执行。
照此改之,没有panic了。
相关文章
- 解block层死锁 - 12 19, 2012
- EMC USD组 招聘 - 09 24, 2012
- hadoop集群上捉到linux kernel bug一个 (答读者提问) - 08 31, 2012
留言: