有人可以帮我替换块设备驱动程序上的“lock_kernel”吗?

时间:2011-05-10 20:35:55

标签: linux-kernel linux-device-driver ioctl

感谢您查看此帖子。我正在尝试修补网络块设备驱动程序。如果您需要查看源代码,请访问http:/ / code.ximeta.com。

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

所以如果可能的话,我想提出一些建议。

我在块文件夹部分找到了当前代码中我认为相关的两个部分。

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中的include,你能吗? 推荐顶部的任何锁定 你的头? (我试着研究一下 其他司机处理filp和 lock_kernel,但我太过分了 noob马上找到答案。)

2 个答案:

答案 0 :(得分:6)

大内核锁(BKL)已被弃用 - 从2.6.39开始,它不再存在。

lock_kernel()转换的方式是用每个驱动程序的互斥锁替换它。如果驱动程序足够简单,您只需为驱动程序创建互斥锁,并通过互斥锁定/解锁调用替换lock_kernel()unlock_kernel()的所有用途。但请注意,以前使用BKL(用于锁定的锁lock_kernel())调用的某些函数保持不变;您还必须为这些功能添加锁定/解锁调用。

如果驱动程序可以递归获取BKL,则无效;如果是这种情况,你必须自己跟踪以避免死锁(这是在reiserfs的转换中完成的,它在递归BKL行为和在睡眠时它被丢弃的事实上都有很大的依赖性。 )。

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

答案 1 :(得分: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的问题部分中所猜测的那样,其他部分已经解决了。感谢您的检查和帮助。