Linux device driver 내부에서 block device request 생성하는 방법
안녕하세요.
지금 제가 scsi high level 디바이스 드라이버 (driver/scsi/scsi_lib.c)에서 별도의 block request를 생성해서 보내려고 하고 있는데요..
환경은 SATA 디바이스가 연결된 상황이고, SATA는 block interface를 scsi device driver와 공유해서 사용하기 때문에 scsi_lib.c에서 작업을 진행하고 있습니다.
궁금한건, 제가 파일시스템을 통해 내려오지 않은 임의의 request를 생성해서 보내고 싶고, 해당 request는 일반적인 write function과 유사하며, 2 page 이상의 write를 보내게 되는데, 이러한 request를 device driver 내부에서 VFS와 파일시스템을 거치지 않고 생성하는 방법이 뭔지 궁금해서요..
일단 제가 찾아본바로는 blk_make_request란 함수가 별도의 request를 생성하게 해주는 거 같아서 해당 request를 사용해서 코드를 좀 짜봤는데,
코드는 개략적으로 다음과 같습니다.
bio = bio_kmalloc(GFP_KERNEL, 2); for(i=0; i < 2; i++) bio_add_pc_page(q, bio, virt_to_page((void *)buff), PAGE_SIZE, 0); bio->bi_end_io = bio_map_kern_endio; bio->bi_rw |= REQ_WRITE; req = blk_make_request(q, bio, GFP_KERNEL); block = addr; //sector address 입니다. this_count = 8 * 2; //8은 page 내 sector (512byte) 개수를 의미합니다. req->__sector = block; req->__data_len = this_count << 9; //cmd를 채우는 것은 sd.c (driver/scsi)를 참고해서 거기서 제가 실험하는 storage의 일반적인 write cmd를 만들 때 지나는 function을 그대로 따라했습니다. if (direction == WRITE) { req->cmd[0] = WRITE_6; } else if (direction == READ) { req->cmd[0] = READ_6; } req->cmd[0] += READ_10 - READ_6; req->cmd[1] = 0; req->cmd[2] = (unsigned char) (block >> 24) & 0xff; req->cmd[3] = (unsigned char) (block >> 16) & 0xff; req->cmd[4] = (unsigned char) (block >> 8) & 0xff; req->cmd[5] = (unsigned char) block & 0xff; req->cmd[6] = req->cmd[9] = 0; req->cmd[7] = (unsigned char) (this_count >> 8) & 0xff; req->cmd[8] = (unsigned char) this_count & 0xff; req->cmd_flags |= REQ_WRITE; req->retries = 5; req->timeout = 60; return req;
이런식으로 짜봤는데, 일단 기본적으로 제가 보기엔 일반적인 file system의 write request와 유사하다고 생각했는데, 구동을 해보니 SATA error를 뿜고 죽네요.. (일단 write request가 dispatch되서 send까지 된다음 interrupt 에러가 나는 것 같습니다.)
Error 메시지는 다음과 같습니다.
ata4.00: exception Emask 0x70 SAct 0x1e0 SErr 0x400900 action 0x6 frozen ata4.00: irq_stat 0x28000000, host bus error, interface fatal error ata4: SError: UnrecovData HostInt Handshk ata4.00: failed command: WRITE FPDMA QUEUED ata4.00: cmd61/10:28:00:00:c0/00:00:0d:00:00/40 tag 5 ncq 8192 out res 40/00:30:00:00:bf/00:00:0d:00:00/40 Emask 0x70 (host bus error) ata4.00: status: {DRDY} ...
혹시 blk request를 device driver 내부에서 독립적으로 생성하는 방법이나, 또는 해당 ata error에 대해서 솔루션이 있으신 분 있으신가요.. 혼자서 해결하기가 힘드네요.
감사합니다.
buffer_head
struct buffer_head
__getblk
set_buffer_uptodate
를 사용하면 안되나요?
buffer_head의 경우,
답변 감사합니다.
buffer_head를 사용하고, buffer_uptodate를 사용하는 경우, 당장 write request를 진행하는 것이 아니라, 추후에 flush thread에서 write 진행할 때 write가 되는 구조 아닌가요?
현재 제가 하고자 하는 것은 request를 만들어서 바로 I/O scheduler의 front에 추가한 다음, write request가 제일 먼저 처리되어야 하는 상황이거든요.. ordering이 중요한 상황이라..
안녕하세요 입문하는 학생입니다.
안녕하세요.
wangmir님께서 올려주신 부분을 저도 구현해서 공부해보려고 하는 중입니다.
돌아다녀보니 자료가 너무 없어서 부득이 이렇게 답글 남기게 되었습니다.
혹시 이 문제에 대하여 해결하셨다면 어떻게 해결하셨는지 알려주실 수 있으신가요?
정말 감사합니다..
댓글 달기