6

この投稿をご覧いただきありがとうございます。ネットワーク ブロック デバイス ドライバーにパッチを適用しようとしています。ソースを確認する必要がある場合は、http://code.ximeta.com にあります。

Linux 2.6.37 で lock_kernel() が非推奨になっていることに気付きました。「ioctl() の新しい方法」を読んだところ、デバイス ドライバは動作前に特定のロックを実行する必要があることがわかりました。

可能であれば、これに代わるアドバイスをお願いします。

ブロック フォルダー セクションで、関連していると思われる現在のコードの 2 つのセクションを見つけました。

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

ご参考までに、それぞれの抜粋を載せておきます。

io.c には、lock_kernel への 1 つの呼び出しが含まれています。

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 を扱う他のドライバーをいくつか調べてみましたが、初心者すぎてすぐに答えを見つけることができませんでした。)

4

2 に答える 2

6

Big Kernel Lock (BKL) は非推奨であり、2.6.39 の時点では存在しません。

変換が行われた方法は、lock_kernel()ドライバーごとのミューテックスに置き換えることでした。ドライバーが十分に単純な場合は、単純にドライバーのミューテックスを作成し、ミューテックスのロック/ロック解除呼び出しのすべての使用lock_kernel()を置き換えることができます。unlock_kernel()ただし、一部の関数は、BKL (ロックlock_kernel()に使用されるロック) を保持したまま呼び出されていたことに注意してください。これらの関数にもロック/ロック解除の呼び出しを追加する必要があります。

ドライバーが BKL を再帰的に取得できる場合、これは機能しません。その場合、デッドロックを回避するために自分で追跡する必要があります (これは の変換で行われreiserfs、再帰的な BKL の動作と、スリープ時にドロップされるという事実の両方に大きく依存していました)。

ドライバーごとのミューテックスへの変換後の次のステップは、ドライバーごとのミューテックスの代わりにデバイスごとのミューテックスを使用するように変更することです。

于 2011-05-16T10:10:59.940 に答える
6

これが解決策です。

#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

これは、ロック呼び出しの置き換えのみを示しています。ロックされていない_ioctlに関する上記の質問の部分で推測したように、他の部分はうまくいきました。チェックしていただき、ありがとうございます。

于 2011-12-29T22:05:49.227 に答える