Làm cách nào để xác định hàng đợi yêu cầu cho một thiết bị khối linux


80

Tôi đang làm việc trên trình điều khiển này kết nối đĩa cứng qua mạng. Có một lỗi mà nếu tôi bật hai hoặc nhiều đĩa cứng trên máy tính, thì chỉ cái đầu tiên mới xem xét và xác định được các phân vùng. Kết quả là, nếu tôi có 1 phân vùng trên hda và 1 phân vùng trên hdb, ngay sau khi tôi kết nối hda, sẽ có một phân vùng có thể được gắn kết. Vì vậy, hda1 nhận được xyz123 blkid ngay sau khi nó được gắn kết. Nhưng khi tôi tiếp tục và gắn hdb1 nó cũng xuất hiện cùng một blkid và trên thực tế, trình điều khiển đang đọc nó từ hda, không phải hdb.

Vì vậy, tôi nghĩ rằng tôi đã tìm thấy nơi mà người lái xe đang lộn xộn. Dưới đây là đầu ra gỡ lỗi bao gồm một dump_stack mà tôi đã đặt ở vị trí đầu tiên nơi có vẻ như nó đang truy cập sai thiết bị.

Đây là phần mã:

/*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

Đây là đầu ra nhật ký. Tôi đã thêm một số nhận xét để giúp hiểu những gì đang xảy ra và nơi mà cuộc gọi xấu dường như xuất hiện.

  /* 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

Tôi hy vọng đây là đủ thông tin cơ bản. Có thể một câu hỏi rõ ràng tại thời điểm này là "Khi nào và ở đâu các request_queues được chỉ định?"

Điều đó được xử lý một chút trước khi hàm add_disk. thêm đĩa, là dòng đầu tiên trên đầu ra nhật ký.

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

Theo như tôi biết, đây là hoạt động tiêu chuẩn. Vì vậy, trở lại câu hỏi ban đầu của tôi. Tôi có thể tìm thấy hàng đợi yêu cầu ở đâu đó và đảm bảo rằng nó được tăng dần hoặc duy nhất cho mỗi thiết bị mới hay nhân Linux chỉ sử dụng một hàng đợi cho mỗi số Chính? Tôi muốn khám phá lý do tại sao trình điều khiển này đang tải cùng một hàng đợi trên hai kho lưu trữ khối khác nhau và xác định xem điều đó có gây ra blkid trùng lặp trong quá trình đăng ký ban đầu hay không.

Cảm ơn vì đã xem xét tình huống này cho tôi.


8
Bạn có thể muốn thử danh sách gửi thư của Kernel Newbies .
dlitz

1
@ndasusers: Có thể hữu ích khi kiểm tra 'loại' yêu cầu trước khi bắt đầu một xx_request (yêu cầu) mới. Có thể một yêu cầu đến chỉ liên quan đến quyền truy cập đọc vào hda đã được gắn của bạn và bạn xử lý điều đó như một thứ gì đó liên quan đến hdb mới được cắm.
boto

1
Bạn đã viết và gắn hdab1 nó cũng xuất hiện, tôi đoán bạn có nghĩa là hdb1 phải không?
Yves Martin

Tôi không nghĩ rằng bạn có thể có hai thiết bị có cùng số chính và số phụ. Con số chính và phụ của bạn cho ổ đĩa là gì?
Ethan

câu hỏi hay, nhưng bạn có đang cố triển khai lại nbd không?
IanNorton

Câu trả lời:



0

Tôi chia sẻ giải pháp cho lỗi khiến tôi đăng câu hỏi này. Mặc dù nó không thực sự trả lời câu hỏi về cách xác định hàng đợi yêu cầu thiết bị.

Trong đoạn mã trên là như sau:

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

Chà, "SLOT_R (req)" đó đã gây ra sự cố. Điều đó được xác định khác nơi trả lại thiết bị gendisk.

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

Điều này đã trả lại đĩa, nhưng không phải là giá trị thích hợp cho các hoạt động khác nhau sau này. Vì vậy, khi các thiết bị khối bổ sung được tải, hàm này về cơ bản tiếp tục trả về 1. (Tôi nghĩ rằng nó đang xử lý như một boolean.) Do đó, tất cả các yêu cầu đều được xếp chồng lên hàng đợi yêu cầu cho đĩa 1.

Cách khắc phục là truy cập vào đúng giá trị nhận dạng đĩa đã được lưu trữ trong private_data của đĩa khi nó được thêm vào hệ thống.

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;

Bây giờ id ổ đĩa chính xác được trả về từ dữ liệu riêng tư, vì vậy tất cả các yêu cầu đến đúng hàng đợi.

Như đã đề cập, điều này không hiển thị cách xác định hàng đợi. Một phỏng đoán không được đào tạo có thể là:

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

Tham chiếu hàm request_queue trong linux http://lxr.free-electrons.com/source/include/linux/blkdev.h#L270 & 321

Cảm ơn mọi người đã giúp đỡ!


Trả lời các bình luận trước: -boto: Các yêu cầu được kiểm tra thêm trong chức năng này. lỗi đã thực sự xảy ra ở một nơi khác là SLOT_R đang được sử dụng. -Yves: Cảm ơn đã sửa. Đó là sai lầm của tôi. -Ethan: Ổ đĩa lớn và ổ đĩa nhỏ sẽ đưa ra đúng, trong hầu hết các trường hợp chúng được phát hiện. -Ian: Đây là NDAS. Nó khá giống nbd, cung cấp khối lưu trữ trên lan. NDAS là phần cứng thực tế. Cách thực hiện gần khác là AoE.
ndasusers
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.