2011-05-10 48 views
5

谢谢你看这篇文章。我正在尝试修补网络块设备驱动程序。如果您需要查看http:// code.ximeta.com上的来源。有人可以帮我替换块设备驱动程序上的“lock_kernel”吗?

我注意到lock_kernel()从linux 2.6.37开始似乎不推荐使用。我读到“ioctl()的新方法”,并发现设备驱动程序现在应该在操作之前执行特定的锁定。

所以我想一些建议,如果可能的话取代这一点。

我在block文件夹部分找到了我认为相关的两段代码。

Source 
     block->io.c 
      ->ctrldev.c 

我把每个片段都考虑在内。

io.c中包含一个来电lock_kernel:

NDAS_SAL_API xbool  sal_file_get_size(sal_file file, xuint64* size) 
{ 
    definitions and declarations etc.. 

lock_kernel(); 

#ifdef HAVE_UNLOCKED_IOCTL 
    if (filp->f_op->unlocked_ioctl) { 
     some small statements 

     error = filp->f_op->unlocked_ioctl(filp, BLKGETSIZE64, (unsigned long)size); 

     actions if error or not etc. 
    } 
#endif 

    unlock_kernel(); 
    return ret; 
} 

而且ctrldev.c包含主IO功能:

#include <linux/spinlock.h> // spinklock_t 
#include <linux/semaphore.h> // struct semaphore 
#include <asm/atomic.h> // atomic 
#include <linux/interrupt.h> 
#include <linux/fs.h> 
#include <asm/uaccess.h> 
#include <linux/ide.h> 
#include <linux/smp_lock.h> 
#include <linux/time.h> 

...... 

int ndas_ctrldev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 
{ 
    lots of operations and functions. 

    return result; 
} 

后来ndas_ctrldev_ioctl功能被设置为前.ioctl。

static struct file_operations ndasctrl_fops = { 
    .write = ndas_ctrldev_write, 
    .read = ndas_ctrldev_read, 
    .open = ndas_ctrldev_open, 
    .release = ndas_ctrldev_release, 
    .ioctl = ndas_ctrldev_ioctl, 
}; 

现在我想转换这个以避免使用lock_kernel();

根据我的理解,我将修改前的部分如下:

NDAS_SAL_API xbool  sal_file_get_size(sal_file file, xuint64* size) 
{ 
    definitions and declarations etc.. 

#ifndef HAVE_UNLOCKED_IOCTL 
    lock_kernel(); 
#endif 

#ifdef HAVE_UNLOCKED_IOCTL 
    if (filp->f_op->unlocked_ioctl) { 
     some small statements 

     error = filp->f_op->unlocked_ioctl(filp, BLKGETSIZE64, (unsigned long)size); 

     actions if error or not etc. 
    } 
#endif 

#ifndef HAVE_UNLOCKED_IOCTL 
    unlock_kernel(); 
#endif 
    return ret; 

} 

#ifdef HAVE_UNLOCKED_IOCTL 
long ndas_ctrldev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 
#else 
int ndas_ctrldev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 
#endif 
{ 

#ifdef HAVE_UNLOCKED_IOCTL 
    ! add some sort of lock here ! 
#endif 

    lots of operations and functions. 

#ifdef HAVE_UNLOCKED_IOCTL 
    ! add unlock statement here ! 
#endif 
    return result; 
} 

static struct file_operations ndasctrl_fops = { 
    .write = ndas_ctrldev_write, 
    .read = ndas_ctrldev_read, 
    .open = ndas_ctrldev_open, 
    .release = ndas_ctrldev_release, 
#ifdef HAVE_UNLOCKED_IOCTL 
    .unlocked_ioctl = ndas_ctrldev_ioctl, 
#else 
    .ioctl = ndas_ctrldev_ioctl, 
#endif 
}; 

所以,我提出以下建议。

  1. 这是否看起来像右边 proceedure?

  2. 我理解将 锁移入io函数是否正确?

  3. 基于对crtrldev.c的包括,可你 推荐任何脱锁 你的头顶? (我想研究一些 其他司机处理的filp和 lock_kernel,但我太 小白找到答案的时候了。)

回答

5

大内核锁(BKL)超过弃用 - 截至2.6.39,它不再存在。

完成lock_kernel()转换的方式是将其替换为每个驱动程序互斥体。如果驱动程序足够简单,则可以简单地为驱动程序创建一个互斥锁,并用互斥锁/解锁调用替换lock_kernel()unlock_kernel()的所有用法。但是,请注意,BKL(用于锁定的锁lock_kernel())曾经被调用的一些函数被保留;您也必须为这些功能添加锁定/解锁呼叫。

如果驱动程序可以递归获取BKL,这将不起作用;如果是这样的话,你将不得不自己跟踪它,以避免死锁(这是在reiserfs的转换中完成的,这在转换BKL行为和它在睡眠时被丢弃的事实都有很大的依赖)。

转换为每个驱动程序互斥体之后的下一步是将其更改为使用每个设备互斥体而不是每个驱动程序互斥体。

+0

此驱动程序中只有一个lock_kernel实例。我想这意味着没有递归,并且在io.c中替换它的可能性就足够了。至于用互斥锁代替lock_kernel,是否意味着我会写一个小函数,然后调用它而不是lock_kernel?或者我尝试链接到设备中现有的互斥锁?在ctrldev.c中有几个对互斥锁的引用。设备上还有一个自旋锁,但未被调用。如果我为ndas_ctrldev_ioctl函数中的每个可能的操作使用up()和down(),它会被认为是按设备样式吗? – ndasusers 2011-05-19 01:48:35

5

这是解决方案。

#if HAVE_UNLOCKED_IOCTL 
    #include <linux/mutex.h> 
#else 
    #include <linux/smp_lock.h> 
#endif 

. 
. 
. 

#if HAVE_UNLOCKED_IOCTL 
    mutex_lock(&fs_mutex); 
#else 
    lock_kernel(); 
#endif 

这只显示替换锁定呼叫。其他部分是在我上面关于unlocked_ioctl的问题部分中猜出的。感谢您的检查和帮助。

相关问题