LINUX.ORG.RU

Проблема при работе /proc на ядре 2.4.18


0

0

Здравствуйте,

Я пишу небольшой модуль уровня ядра. Столкнулся с проблемой, с которой бъюсь уже две недели...

Я работаю с /proc файловой системой следующим образом: сначала создаю файл стандартными средствами (create_proc_entry()) а потом открываю его, как файл с помощью (filp_open()).

На ядре 2.4.24 данный код работает без проблем. А вот на 2.4.18 (сменить версию ядра не могу по требованию заказчика) есть одна странность - у открытого файла поле fp->f_dentry->d_inode->u.generic_ip содержит NULL а не адрес proc_dir_entry как должно быть согласно описанию. Из-за этого мой драйвер не работает.

Проблема, очевидно скрыта где-то внутри filp_open либо create_proc_entry что-то не так создает.

Прошу помочь разобраться... Вот код примера:

<pre>

my_root = create_proc_entry("test_dir", (S_IFDIR | S_IRUGO | S_IXUGO), (struct proc_dir_entry*)0); if (my_root == NULL) { result = -ENOMEM; goto out; } my_root->owner = THIS_MODULE;

printk("<1>dir_iops: %p\n",my_root->proc_iops); printk("<1>dir_fops: %p\n",my_root->proc_fops);

file_entry = create_proc_entry("testname", (S_IRUGO | S_IWUGO), my_root); file_entry->owner = THIS_MODULE; file_entry->read_proc = vars_reader;

printk("<1>file_iops: %p\n",file_entry->proc_iops); printk("<1>file_fops: %p\n",file_entry->proc_fops); printk("<1>file_data: %p\n",file_entry->data); printk("<1>file_read_proc: %p\n",file_entry->read_proc); printk("<1>file_write_proc: %p\n",file_entry->write_proc);

fp = filp_open("/proc/test_dir/testname", O_RDONLY, 0); if (IS_ERR(fp)){ printk("<1>Error open file with code %ld\n",-PTR_ERR(fp)); } else{ printk("<1>vsfmnt: %p\n",fp->f_vfsmnt); printk("<1>fops: %p\n",fp->f_op); printk("<1>node: %p\n",fp->f_dentry->d_inode->u.generic_ip); filp_close(fp,0); } </pre>

Надеюсь, гуру помогут разобраться...

Станислав.

anonymous

Что насчет того, чтобы собрать UML или добавить KDB к ядру и попробовать прочесать, что там происходит?

Murr ★★
()
Ответ на: комментарий от Murr

Это результат diff -B ver18/fs/proc/generic.c ver24/fs/proc/generic.c

141c141
< proc_file_lseek(struct file * file, loff_t offset, int orig)
---
> proc_file_lseek(struct file * file, loff_t offset, int origin)
143,158c143,161
<     switch (orig) {
<     case 0:
< 	if (offset < 0)
< 	    return -EINVAL;    
< 	file->f_pos = offset;
< 	return(file->f_pos);
<     case 1:
< 	if (offset + file->f_pos < 0)
< 	    return -EINVAL;    
< 	file->f_pos += offset;
< 	return(file->f_pos);
<     case 2:
< 	return(-EINVAL);
<     default:
< 	return(-EINVAL);
<     }
---
> 	long long retval;
> 
> 	switch (origin) {
> 		case 2:
> 			offset += file->f_dentry->d_inode->i_size;
> 			break;
> 		case 1:
> 			offset += file->f_pos;
> 	}
> 	retval = -EINVAL;
> 	if (offset>=0 && (unsigned long long)offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
> 		if (offset != file->f_pos) {
> 			file->f_pos = offset;
> 			file->f_reada = 0;
> 		}
> 		retval = offset;
> 	}
> 	/* RED-PEN user can fake an error here by setting offset to >=-4095 && <0  */
> 	return retval;
457c460,464
< 			proc_register(parent, ent);
---
> 			if (proc_register(parent, ent) < 0) {
> 				kfree(ent->data);
> 				kfree(ent);
> 				ent = NULL;
> 			}
474c481,484
< 		proc_register(parent, ent);
---
> 		if (proc_register(parent, ent) < 0) {
> 			kfree(ent);
> 			ent = NULL;
> 		}
489c499,502
< 		proc_register(parent, ent);
---
> 		if (proc_register(parent, ent) < 0) {
> 			kfree(ent);
> 			ent = NULL;
> 		}
518c531,534
< 		proc_register(parent, ent);
---
> 		if (proc_register(parent, ent) < 0) {
> 			kfree(ent);
> 			ent = NULL;
> 		}

Это результат diff -B ver18/fs/proc/inode.c ver24/fs/proc/inode.c 

25c25
< struct proc_dir_entry * de_get(struct proc_dir_entry *de)
---
> static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
35c35
< void de_put(struct proc_dir_entry *de)
---
> static void de_put(struct proc_dir_entry *de)
188a189
> 	s->s_maxbytes = ~0UL;

anonymous
()

> file_entry->read_proc = vars_reader;

попробуйте прочитать этот файл из user-level.

если в generic_ip действительно 0, то у вас будет OOPS
в proc_file_read() и вы будете знать, что проблема в
create_proc_entry(). иначе что-то c filp_open().

в принципе вы забыли про S_IFREG в create_proc_entry(),
но по крайней мере в 4.26 он автоматически ставится если
!(mode & S_IFMT), так что дело вряд ли в этом.

idle ★★★★★
()
Ответ на: комментарий от idle

Попробовали прочитать этот файл из user-level:

#include <fcntl.h> #include <stdio.h>

int main(void) { char buffer[20]; int f = open("/proc/test_dir/testname", O_RDWR); if (f<0) { printf("ERROR!\n"); } else { printf("Open OK!\n"); buffer[5] = 0; read(f,buffer,5); printf("%s\n",buffer); }

return 0; }

Результат - читается нормально и в точности то, что туда подкладывает функция vars_reader(). Честно говоря, я озадачен такой двойственностью поведения...

Станислав.

anonymous
()
Ответ на: комментарий от idle

Не думаю. Я всегда заменяю /usr/include/linux /usr/include/asm /usr/include/asm-generic когда компилирую модули ядра.

Более того, при загрузке модуля выводится строка с ожидаемым номером версии.

С другой стороны, открывая файл из ядра я печатаю содержимое поля u.generic_ip и там лежит NULL! (см. в тексте модуля) Вот трасса: Dec 28 02:07:17 localhost kernel: dir_iops: c02c5e40 Dec 28 02:07:17 localhost kernel: dir_fops: c02c5de0 Dec 28 02:07:17 localhost kernel: file_iops: 00000000 Dec 28 02:07:17 localhost kernel: file_fops: c02c5d20 Dec 28 02:07:17 localhost kernel: file_data: 00000000 Dec 28 02:07:17 localhost kernel: file_read_proc: d08b317c Dec 28 02:07:17 localhost kernel: file_write_proc: 00000000 Dec 28 02:07:17 localhost kernel: vsfmnt: c138e320 Dec 28 02:07:17 localhost kernel: fops: c02c5d20 Dec 28 02:07:17 localhost kernel: node: 00000000

Есть ли какое-то различие между открытием файла из ядра и открытием файла из юзера?

Станислав.

anonymous
()
Ответ на: комментарий от anonymous

> Я всегда заменяю /usr/include/linux /usr/include/asm /usr/include/asm-generic

оффтопик, но этого делать не стоит. лучше -nostdinc,
а в /usr/include/ оставить то, что поставил glibc.

а вы уверены, что то ядро, на котором все исполняется
было собрано с этими же исходниками? лучше пересобрать
и снова проверить.

> Вот трасса: Dec 28 02:07:17 localhost kernel

ну отформатируйте, читать же невозможно...

> localhost kernel: fops: c02c5d20

совпадает с proc_file_operations в System.map?

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.