Як я можу визначити чергу запитів для блочного пристрою Linux


80

Я працюю над цим драйвером, який підключає жорсткий диск через мережу. Існує помилка, що якщо я ввімкну два чи більше жорстких дисків на комп’ютері, лише перший переглядає та ідентифікує розділи. Результат полягає в тому, що якщо у мене є 1 розділ на hda і 1 розділ на hdb, як тільки я підключаю hda, є розділ, який можна змонтувати. Тож hda1 отримує blkid xyz123, як тільки він підключається. Але коли я продовжую монтувати hdb1, він також випускає той самий blkid, і насправді драйвер читає його з hda, а не hdb.

Тож, думаю, я знайшов місце, де водій псує. Нижче наведено вивід налагодження, включаючи dump_stack, який я розмістив у першому місці, де, здається, він отримує доступ до неправильного пристрою.

Ось розділ коду:

/*basically, this is just the request_queue processor. In the log output that
  follows, the second device, (hdb) has just been connected, right after hda
  was connected and hda1 was mounted to the system. */

void nblk_request_proc(struct request_queue *q)
{
struct request *req;
ndas_error_t err = NDAS_OK;

dump_stack();

while((req = NBLK_NEXT_REQUEST(q)) != NULL)
{
    dbgl_blk(8,"processing queue request from slot %d",SLOT_R(req));

    if (test_bit(NDAS_FLAG_QUEUE_SUSPENDED, &(NDAS_GET_SLOT_DEV(SLOT_R(req))->queue_flags)))  {
        printk ("ndas: Queue is suspended\n");
        /* Queue is suspended */
#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) )
        blk_start_request(req);
#else
        blkdev_dequeue_request(req);
#endif

Ось висновок журналу. Я додав кілька коментарів, щоб допомогти зрозуміти, що відбувається і де, здається, надходить поганий дзвінок.

  /* Just below here you can see "slot" mentioned many times. This is the 
     identification for the network case in which the hd is connected to the 
     network. So you will see slot 2 in this log because the first device has 
     already been connected and mounted. */

  kernel: [231644.155503] BL|4|slot_enable|/driver/block/ctrldev.c:281|adding disk: slot=2, first_minor=16, capacity=976769072|nd/dpcd1,64:15:44.38,3828:10
  kernel: [231644.155588] BL|3|ndop_open|/driver/block/ops.c:233|ing bdev=f6823400|nd/dpcd1,64:15:44.38,3720:10
  kernel: [231644.155598] BL|2|ndop_open|/driver/block/ops.c:247|slot =0x2|nd/dpcd1,64:15:44.38,3720:10
  kernel: [231644.155606] BL|2|ndop_open|/driver/block/ops.c:248|dev_t=0x3c00010|nd/dpcd1,64:15:44.38,3720:10
  kernel: [231644.155615] ND|3|ndas_query_slot|netdisk/nddev.c:791|slot=2 sdev=d33e2080|nd/dpcd1,64:15:44.38,3696:10
  kernel: [231644.155624] ND|3|ndas_query_slot|netdisk/nddev.c:817|ed|nd/dpcd1,64:15:44.38,3696:10
  kernel: [231644.155631] BL|3|ndop_open|/driver/block/ops.c:326|mode=1|nd/dpcd1,64:15:44.38,3720:10
  kernel: [231644.155640] BL|3|ndop_open|/driver/block/ops.c:365|ed open|nd/dpcd1,64:15:44.38,3724:10
  kernel: [231644.155653] BL|8|ndop_revalidate_disk|/driver/block/ops.c:2334|gendisk=c6afd800={major=60,first_minor=16,minors=0x10,disk_name=ndas-44700486-0,private_data=00000002,capacity=%lld}|nd/dpcd1,64:15:44.38,3660:10
  kernel: [231644.155668] BL|8|ndop_revalidate_disk|/driver/block/ops.c:2346|ed|nd/dpcd1,64:15:44.38,3652:10

  /* So at this point the hard disk is added (gendisk=c6...) and the identifications
     all match the network device. The driver is now about to begin scanning the 
     hard drive for existing partitions. the little 'ed', at the end of the previous
     line indicates that revalidate_disk has finished it's job. 

     Also, I think the request queue is indicated by the output dpcd1 near the very
     end of the line. 

     Now below we have entered the function that is pasted above. In the function
     you can see that the slot can be determined by the queue. And the log output
     after the stack dump shows it is from slot 1. (The first network drive that was
     already mounted.) */

        kernel: [231644.155677]  ndas-44700486-0:Pid: 467, comm: nd/dpcd1 Tainted: P           2.6.32-5-686 #1
  kernel: [231644.155711] Call Trace:
  kernel: [231644.155723]  [<fc5a7685>] ? nblk_request_proc+0x9/0x10c [ndas_block]
  kernel: [231644.155732]  [<c11298db>] ? __generic_unplug_device+0x23/0x25
  kernel: [231644.155737]  [<c1129afb>] ? generic_unplug_device+0x1e/0x2e
  kernel: [231644.155743]  [<c1123090>] ? blk_unplug+0x2e/0x31
  kernel: [231644.155750]  [<c10cceec>] ? block_sync_page+0x33/0x34
  kernel: [231644.155756]  [<c108770c>] ? sync_page+0x35/0x3d
  kernel: [231644.155763]  [<c126d568>] ? __wait_on_bit_lock+0x31/0x6a
  kernel: [231644.155768]  [<c10876d7>] ? sync_page+0x0/0x3d
  kernel: [231644.155773]  [<c10876aa>] ? __lock_page+0x76/0x7e
  kernel: [231644.155780]  [<c1043f1f>] ? wake_bit_function+0x0/0x3c
  kernel: [231644.155785]  [<c1087b76>] ? do_read_cache_page+0xdf/0xf8
  kernel: [231644.155791]  [<c10d21b9>] ? blkdev_readpage+0x0/0xc
  kernel: [231644.155796]  [<c1087bbc>] ? read_cache_page_async+0x14/0x18
  kernel: [231644.155801]  [<c1087bc9>] ? read_cache_page+0x9/0xf
  kernel: [231644.155808]  [<c10ed6fc>] ? read_dev_sector+0x26/0x60
  kernel: [231644.155813]  [<c10ee368>] ? adfspart_check_ICS+0x20/0x14c
  kernel: [231644.155819]  [<c10ee138>] ? rescan_partitions+0x17e/0x378
  kernel: [231644.155825]  [<c10ee348>] ? adfspart_check_ICS+0x0/0x14c
  kernel: [231644.155830]  [<c10d26a3>] ? __blkdev_get+0x225/0x2c7
  kernel: [231644.155836]  [<c10ed7e6>] ? register_disk+0xb0/0xfd
  kernel: [231644.155843]  [<c112e33b>] ? add_disk+0x9a/0xe8
  kernel: [231644.155848]  [<c112dafd>] ? exact_match+0x0/0x4
  kernel: [231644.155853]  [<c112deae>] ? exact_lock+0x0/0xd
  kernel: [231644.155861]  [<fc5a8b80>] ? slot_enable+0x405/0x4a5 [ndas_block]
  kernel: [231644.155868]  [<fc5a8c63>] ? ndcmd_enabled_handler+0x43/0x9e [ndas_block]
  kernel: [231644.155874]  [<fc5a8c20>] ? ndcmd_enabled_handler+0x0/0x9e [ndas_block]
  kernel: [231644.155891]  [<fc54b22b>] ? notify_func+0x38/0x4b [ndas_core]
  kernel: [231644.155906]  [<fc561cba>] ? _dpc_cancel+0x17c/0x626 [ndas_core]
  kernel: [231644.155919]  [<fc562005>] ? _dpc_cancel+0x4c7/0x626 [ndas_core]
  kernel: [231644.155933]  [<fc561cba>] ? _dpc_cancel+0x17c/0x626 [ndas_core]
  kernel: [231644.155941]  [<c1003d47>] ? kernel_thread_helper+0x7/0x10

  /* here are the output of the driver debugs. They show that this operation is
     being performed on the first devices request queue. */

  kernel: [231644.155948] BL|8|nblk_request_proc|/driver/block/block26.c:494|processing queue request from slot 1|nd/dpcd1,64:15:44.38,3408:10
  kernel: [231644.155959] BL|8|nblk_handle_io|/driver/block/block26.c:374|struct ndas_slot sd = NDAS GET SLOT DEV(slot 1)
  kernel: [231644.155966] |nd/dpcd1,64:15:44.38,3328:10
  kernel: [231644.155970] BL|8|nblk_handle_io|/driver/block/block26.c:458|case READA call ndas_read(slot=1, ndas_req)|nd/dpcd1,64:15:44.38,3328:10
  kernel: [231644.155979] ND|8|ndas_read|netdisk/nddev.c:824|read io: slot=1, cmd=0, req=x00|nd/dpcd1,64:15:44.38,3320:10

Сподіваюсь, цього достатньо довідкової інформації. Можливо, очевидним питанням на даний момент є "Коли і де присвоюються черги запиту?"

Ну, це обробляється трохи перед функцією add_disk. додаючи диск, є першим рядком у вихідних даних журналу.

slot->disk = NULL;
spin_lock_init(&slot->lock);
slot->queue = blk_init_queue(
    nblk_request_proc, 
    &slot->lock
);

Наскільки мені відомо, це стандартна операція. Тож повернімось до мого початкового питання. Чи можу я десь знайти чергу запитів і переконатися, що вона збільшена або унікальна для кожного нового пристрою, або ядро ​​Linux використовує лише одну чергу для кожного основного номера? Я хочу дізнатися, чому цей драйвер завантажує одну і ту ж чергу в два різні сховища блоків, і визначити, чи не спричиняє це дублікат blkid під час процесу початкової реєстрації.

Дякую, що розглянули цю ситуацію для мене.


8
Можливо, ви захочете спробувати список розсилки Kernel Newbies .
dlitz

1
@ndasusers: Може мати сенс перевірити "тип" запиту перед початком нового xx_request (req). Можливо, вхідний запит стосується лише доступу для читання до вашого вже змонтованого hda, і ви обробляєте це як щось пов'язане зі свіжим підключеним hdb.
бото

1
Ви писали та монтували hdab1, він також з'являється, мабуть, ви маєте на увазі hdb1, так?
Ів Мартін

Я не думаю, що ви можете мати два пристрої з однаковими головними та другорядними номерами. Які ваші незначні та основні цифри для диска?
Ітан,

приємне запитання, але чи намагаєтесь ви повторно реалізувати nbd ?
IanNorton 02

Відповіді:



0

Я поділяю рішення помилки, яка змусила мене опублікувати це питання. Хоча це насправді не відповідає на питання про те, як визначити чергу запитів на пристрій.

У наведеному вище коді є наступне:

if (test_bit(NDAS_FLAG_QUEUE_SUSPENDED, 
       &(NDAS_GET_SLOT_DEV(SLOT_R(req))->queue_flags))) 

Що ж, "SLOT_R (req)" спричиняв проблеми. Це визначено в іншому місці, куди повернути пристрій gendisk.

#define SLOT_R(_request_) SLOT((_request_)->rq_disk)

Це повернуло диск, але не належне значення для різних операцій пізніше. Отож, оскільки додаткові блокові пристрої завантажувались, ця функція в основному продовжувала повертати 1. (Я думаю, вона оброблялася як логічна.) Тому всі запити були складені до черги запитів на диск 1.

Виправлення полягало у доступі до правильного значення ідентифікації диска, яке вже зберігалось у приватних даних диска, коли воно було додане до системи.

Correct identifier definition:
   #define SLOT_R(_request_) ( (int) _request_->rq_disk->private_data )

How the correct disk number was stored.
   slot->disk->queue = slot->queue;
   slot->disk->private_data = (void*) (long) s;  <-- 's' is the disk id
   slot->queue_flags = 0;

Тепер правильний ідентифікатор диска повертається із приватних даних, тому всі запити надходять у правильну чергу.

Як уже згадувалося, це не показує, як ідентифікувати чергу. Невихована здогадка може бути:

 x = (int) _request_->rq_disk->queue->id;

Посилання функція request_queue в linux http://lxr.free-electrons.com/source/include/linux/blkdev.h#L270 & 321

Дякуємо усім за допомогу!


У відповідь на попередні коментарі: -boto: Запити перевіряються далі в цій функції. помилка насправді траплялася в іншому місці, коли використовувався SLOT_R. -Йв: Дякую за виправлення. Це була моя помилка. -Етхан: Основний диск та неповнолітні будуть виходити правильно, майже у всіх випадках, коли вони були виявлені. -Іан: Це NDAS. Це схоже на nbd, забезпечуючи блокове зберігання в мережі. NDAS - це фактично апаратне забезпечення. Іншим наближеним впровадженням є AoE.
ndasusers
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.