2011-05-10 10 views
5

Gracias por mirar esta publicación. Estoy tratando de arreglar un controlador de dispositivo de bloque de red. Si necesita ver las fuentes, están en http:// code.ximeta.com.¿Alguien me puede ayudar a reemplazar "lock_kernel" en un controlador de dispositivo de bloque?

Me di cuenta de que lock_kernel() parece obsoleto a partir de Linux 2.6.37. Leí "La nueva forma de ioctl()" y descubrí que los controladores de dispositivos ahora deben realizar un bloqueo específico antes de operar.

Así que me gustaría un consejo para reemplazar esto si es posible.

He encontrado dos secciones en el código actual que creo que están relacionadas, en la sección de la carpeta del bloque.

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

Puse fragmentos de cada uno para su consideración.

io.c contiene una llamada a 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; 
} 

Y ctrldev.c contiene la función principal 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; 
} 

función ndas_ctrldev_ioctl Más tarde se establece como el ex .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, 
}; 

Ahora quiero convertir esto para evitar el uso de lock_kernel();

Según mi entendimiento que será modificado las antiguas secciones de la siguiente manera:

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 
}; 

Por lo tanto, pediría el siguiente consejo.

  1. ¿Esto se parece al derecho proceder?

  2. ¿Entiendo que es correcto mover el bloqueo a la función io?

  3. Según lo incluido en crtrldev.c, ¿puedes recomendar cualquier bloqueo de la parte superior de tu cabeza? (Traté de investigar algunos otros conductores que se ocupan de filp y lock_kernel, pero yo soy demasiado un novato para encontrar la respuesta de inmediato.)

Respuesta

5

El Kernel Lock grande (BKL) es más que obsoleto - a partir de 2.6.39, ya no existe.

La forma en que se realizó la conversión lock_kernel() fue reemplazarla por mutexes por controlador. Si el controlador es lo suficientemente simple, puede simplemente crear un mutex para el controlador y reemplazar todos los usos de lock_kernel() y unlock_kernel() por las llamadas de bloqueo/desbloqueo de mutex. Sin embargo, tenga en cuenta que algunas funciones solían llamarse con el BKL (el bloqueo lock_kernel() utilizado para bloquear); También deberá agregar llamadas de bloqueo/desbloqueo a estas funciones.

Esto no funcionará si el controlador puede adquirir el BKL recursivamente; si ese es el caso, tendrías que rastrearlo tú mismo para evitar interbloqueos (esto se hizo en la conversión de reiserfs, que dependió bastante tanto del comportamiento recursivo de BKL como del hecho de que se cayó cuando dormía).

El siguiente paso después de la conversión a un mutex por controlador sería cambiarlo para usar un mutex por dispositivo en lugar de un mutex por controlador.

+0

Solo hay una instancia de lock_kernel en este controlador. Supongo que eso no implica recursividad y la probabilidad de que reemplazarla en io.c sea suficiente. En cuanto a reemplazar lock_kernel con el mutex, ¿significa que escribiría una pequeña función y luego la llamaría en lugar de lock_kernel? ¿O trato de vincular a un mutex existente en el dispositivo? Hay varias referencias a un bloqueo mutex en ctrldev.c. También hay un bloqueo de giro en el dispositivo, pero esto no se llama. ¿Se consideraría el estilo por dispositivo si uso arriba() y abajo() para cada operación posible dentro de la función ndas_ctrldev_ioctl? – ndasusers

5

Aquí está la solución.

#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 

Esto solo muestra la sustitución de la llamada de bloqueo. Las otras partes funcionó como lo supongo en la pregunta de la parte anterior sobre unlocked_ioctl. Gracias por verificar y por ayudar.

Cuestiones relacionadas