Я создаю очень простой блок RAM-диска на основе sbull.Невозможно прочитать/записать диск с блоком ram со смещением
Пока он работает нормально, если я читаю/записываю блоки данных с помощью dd, но всякий раз, когда я пытаюсь установить на него файловую систему (а иногда и создавать файловую систему), мой драйвер падает.
После долгих недель отладки я наконец выяснил, что не так, хотя я не могу найти способ решить проблему. Отсюда мой вопрос здесь:
Всякий раз, когда приложение пользовательского пространства создает запрос к устройству С СМЕЩЕНИЕМ, драйвер не работает! Позвольте мне показать вам исходный код для того, чтобы выяснить:
Прежде всего, я обработки запросов с использованием mk_request (не используя request_queue):
static void escsi_mk_request(struct request_queue *q, struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
struct escsi_dev *esd = bdev->bd_disk->private_data;
int rw;
struct bio_vec *bvec;
sector_t sector;
int i;
int err = -EIO;
printk("request received nr. sectors = %lu\n",bio_sectors(bio));
sector = bio->bi_sector;
if (bio_end_sector(bio) > get_capacity(bdev->bd_disk))
goto out;
if (unlikely(bio->bi_rw & REQ_DISCARD)) {
err = 0;
goto out;
}
rw = bio_rw(bio);
if (rw == READA)
rw = READ;
bio_for_each_segment(bvec, bio, i) {
unsigned int len = bvec->bv_len;
err = esd_do_bvec(esd, bvec->bv_page, len, bvec->bv_offset, rw, sector);
if (err) {
printk("err!\n");
break;
}
sector += len >> SECTOR_SHIFT;
}
out:
bio_endio(bio, err);
}
esd_do_bvec функция:
static int esd_do_bvec(struct escsi_dev *esd, struct page *page,
unsigned int len, unsigned int off, int rw,
sector_t sector)
{
void *mem;
int err = 0;
unsigned int offset;
int i;
offset = off + sector * 512;
printk("ESD RW=%d, len=%d, off=%d, offset=%d, sector=%lu\n",rw,len,off,offset,sector);
mem = kmap_atomic(page);
if (rw == READ) {
memcpy(mem,esd->data+offset,len);
} else {
memcpy(esd->data+offset,mem,len);
}
kunmap_atomic(mem);
out:
return err;
}
ОК, поэтому в основном, когда я читаю или записываю данные с использованием dd, переменная «off» в esd_do_bvec() всегда равна 0, независимо от того, где и сколько байтов я хочу записать. Файловая система, очевидно, всегда выполняет ввод-вывод в блоках 4 КБ и будет писать полный блок, даже если требуется заменить только один байт.
Я уверен, что чтение и запись корректно работают, когда нет смещения, потому что я создал файл размером с мой RAM-диск и выгрузил весь файл на свое устройство, используя dd, а затем получил вывод (также используя dd), а входные и выходные файлы - это то же самое. Я также написал тот же файл в brd (исходный блок ядра RAM RAM-диска), а выходы совпадают с моим устройством и устройством Brd.
BUT - В некоторых конкретных ситуациях я пытаюсь установить или создать новую файловую систему на своем устройстве, и как-то она получает запросы ввода-вывода со смещением, и в этот момент мой драйвер выходит из строя. Я предполагаю, что я неправильно обрабатываю смещение. Например, при попытке "установить -t ext2/DEV/ESDA":
linux-xjwl:/home/phil/escsi # mount /dev/esda -t ext2 /mnt/esda1/
mount: wrong fs type, bad option, bad superblock on /dev/esda,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so
linux-xjwl:/home/phil/escsi # dmesg|tail -n 10
[ 2239.275901] ESD RW=0, len=4096, off=0, offset=16384, sector=32
[ 2239.275947] request received nr. sectors = 8
[ 2239.275959] ESD RW=0, len=4096, off=0, offset=4096, sector=8
[ 2239.276516] request received nr. sectors = 8
[ 2239.276537] ESD RW=0, len=4096, off=0, offset=2097152, sector=4096
[ 2239.276606] request received nr. sectors = 8
[ 2239.276626] ESD RW=0, len=4096, off=0, offset=28672, sector=56
[ 2239.277535] request received nr. sectors = 2
[ 2239.277535] ESD RW=0, len=1024, off=1024, offset=2048, sector=2
[ 2239.277535] EXT4-fs (esda): VFS: Can't find ext4 filesystem
(PS: вывод показывает "EXT4", но я бегу с "-t ext2")
У меня есть проверил содержимое сектора n. 2 в моем устройстве, и он содержит метаданные ext2 (так как я запускал mkfs.ext2, прежде чем пытаться смонтировать, конечно). Поэтому я считаю, что есть проблема со смещением. Пока я не могу отлаживать свой драйвер, потому что не смог найти запрос, который вызовет запрос ввода-вывода со смещением (например, если я попытаюсь записать один байт в свое устройство, то Linux будет читать весь блок и переписать его только с одним другим байтом).
Надеюсь, это не слишком простой вопрос для вас.
Спасибо заранее, Фил
Пожалуйста, смотрите ответ предоставленный Peter ниже.
Если вам интересно, что функция esd_do_bvec() выглядит сейчас, здесь речь идет о:
static int esd_do_bvec(struct escsi_dev *esd, char *buf,
unsigned int len, int rw, sector_t sector)
{
int err = 0;
unsigned int offset;
// Please notice that we STILL have an offset to deal with, but
// this offset comes in sectors and needs to be converted to a
// a byte offset.
offset = sector << SECTOR_SHIFT; // or multiply by 512
//printk("ESD RW=%d, len=%d, off=%d, offset=%d, sector=%lu\n",rw,len,off,offset,sector);
if (rw == READ) {
memcpy(buf,esd->data+offset,len);
} else {
memcpy(esd->data+offset,buf,len);
}
return err;
}
Является ли 'data' в' struct escsi_dev' указателем char? На первый взгляд, похоже, что это может быть '_u32 *', что, конечно, объясняло бы проблемы смещения. –
Привет, это u8 *. – Phil