Может кто-нибудь помочь мне заменить "lock_kernel" на драйвере блочного устройства? - PullRequest
6 голосов
/ 11 мая 2011

Спасибо за просмотр этого поста.Я пытаюсь исправить драйвер сетевого устройства.Если вам нужно увидеть источники, они находятся по адресу http: / / code.ximeta.com.

Я заметил, что lock_kernel () кажется устаревшим с Linux 2.6.37.Я прочитал «Новый способ 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. Похоже ли это на правильную процедуру?

  2. Правильно ли я понимаю, чтобы переместить блокировку в функцию io?

  3. На основании включений в crtrldev.c, можете ли вы порекомендоватьзаблокировать макушку?(Я пытался исследовать некоторые другие драйверы, связанные с filp и lock_kernel, но я слишком много новичков, чтобы сразу найти ответ.)

Ответы [ 2 ]

6 голосов
/ 16 мая 2011

Big Kernel Lock (BKL) более чем устарел - с 2.6.39 он больше не существует.

Способ, которым было выполнено преобразование lock_kernel(), состоял в том, чтобы заменить его на драйвермьютексы.Если драйвер достаточно прост, вы можете просто создать мьютекс для драйвера и заменить все варианты использования lock_kernel() и unlock_kernel() вызовами блокировки / разблокировки мьютекса.Обратите внимание, однако, что некоторые функции раньше вызывались с удерживаемым BKL (блокировка lock_kernel() использовалась для блокировки);вам также придется добавить вызовы блокировки / разблокировки для этих функций.

Это не будет работать, если драйвер может рекурсивно получить BKL;в этом случае вам придется отслеживать его самостоятельно, чтобы избежать взаимных блокировок (это было сделано при преобразовании reiserfs, что в некоторой степени зависело как от рекурсивного поведения BKL, так и от того, что оно было отброшено во время сна).

Следующим шагом после преобразования в мьютекс для каждого драйвера будет изменение его на использование мьютекса для каждого устройства вместо мьютекса для каждого драйвера.

5 голосов
/ 30 декабря 2011

Вот решение.

#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. Спасибо за проверку и за помощь.

...