read_proc issue
Hi everyone, hope I don't disturb too much.
I'm developping a module which uses an entry in /proc (read-only) Currently my (*read_proc) function just write a integer in my /proc entry and increments it. Here is the code:
static int number_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data)
{
int len = 0;
len = sprintf(buf, "%d\n", number_current++);
*eof = 1;
return len;
}the function is registered in init_module with this:create_proc_read_entry("number", 0, NULL, number_read_procmem, NULL);
Problem is:
when I 'cat /proc/number' multiple times, instead of getting 0
1
2
3
...
I get
0
2
4
6
...
I've searched the Net for an answer to this but in vain. I'm not sure I should post this to this list (and I'm very sorry if I indeed shouldn't have) but this list is my last hope :(
Please can you CC: me the answers to this post as I'm not on the list. Then again, sorry if I'm intruding and thanks for any help.
Regards,
Laurent Sinitambirivoutin
[email protected]
On Tue, 26 Feb 2002, Laurent wrote:
| I'm developping a module which uses an entry in /proc (read-only)
| Currently my (*read_proc) function just write a integer in my /proc entry
| and increments it. Here is the code:
|
| static int number_read_procmem(char *buf, char **start, off_t offset, int
| count, int *eof, void *data)
| {
| int len = 0;
|
| len = sprintf(buf, "%d\n", number_current++);
| *eof = 1;
| return len;
| }
|
| the function is registered in init_module with this:
| create_proc_read_entry("number", 0, NULL, number_read_procmem, NULL);
|
| Problem is:
| when I 'cat /proc/number' multiple times, instead of getting
| 0
| 1
| 2
| 3
| ...
|
| I get
| 0
| 2
| 4
| 6
| ...I was thinking that some part(s) of the proc-fs code might call fs/proc/generic.c::proc_file_read() multiple times (internally), but no, it's just the application (or libc) doing it AFAICT.
app. calls read() [Key data: with offset=0], which calls sys_read(), which calls proc_file_read(), which returns N bytes, and then proc_file_read() and sys_read() and read() return to the app.
When the app. gets N bytes of actual data on its read(), it doesn't know whether it was at EOF or not, so it tries another read() [with offset=N], and sys_read() calls proc_file_read() again, both of which return 0, so the app. knows that there is no more data.
Signature · 1 line
~Randy
Quoted 1 line · Randy.Dunlap
On Tue, 26 Feb 2002, Laurent wrote:
<snippety snippety>
Quoted 6 lines
| Problem is: | when I 'cat /proc/number' multiple times, instead of getting | 0 | 1 | 2 | 3
Quoted 8 lines
| ... | | I get | 0 | 2 | 4 | 6 | ...
<more snippage>
Quoted 9 lines
app. calls
read()[Key data: with offset=0], which callssys_read(), which callsproc_file_read(), which returns N bytes, and thenproc_file_read()andsys_read()andread()return to the app.When the app. gets N bytes of actual data on its
read(), it doesn't know whether it was at EOF or not, so it tries anotherread()[with offset=N], andsys_read()callsproc_file_read()again, both of which return 0, so the app. knows that there is no more data.
I've encountered this problem before, too. What is the "One True Way" to do this cleanly? In other words, if you want to do a calculation once every time someone runs "cat /proc/foo", what is the cleanest way to do that? The solution we came up with was to check the file offset and only do the calculation if offset == 0, which seems pretty hackish.
-VAL
Quoted 6 lines
I've encountered this problem before, too. What is the "One True Way" to do this cleanly? In other words, if you want to do a calculation once every time someone runs "cat
/proc/foo", what is the cleanest way to do that? The solution we came up with was to check the file offset and only do the calculation if offset == 0, which seems pretty hackish.
Another approach is to do the calculation open and remember it in per fd private data. You can recover that and free it on release. It could even be a buffer holding the actual "content"
That's a good solution in the general case but doesn't work for some of the proc entries that already exist. cpuinfo, for example. There seem to be a number of niche /proc methods already. A cache-on-open method would be very useful for files like cpuinfo and a number of other files for PPC.
It sure would make accessing /proc files less whacky for user-code.
} Another approach is to do the calculation open and remember it in per } fd private data. You can recover that and free it on release. It could } even be a buffer holding the actual "content"
Quoted 6 lines
I've encountered this problem before, too. What is the "One True Way" to do this cleanly? In other words, if you want to do a calculation once every time someone runs "cat
/proc/foo", what is the cleanest way to do that? The solution we came up with was to check the file offset and only do the calculation if offset == 0, which seems pretty hackish.
I've tried it and... it works ! :)
Many many thanks :)
In the meantime, I've also followed Tommy Reynolds' advice to not modify global state variables within read_procmem. I've intercepted a syscall which does the calculation (I've used the open syscall since it allowed me to increase the counter by just running vi on any file ;) ) and put it into a buffer which is dumped when the /proc entry is read. Works great that way too. By the way, as the final module will intercept syscalls like open, creat, close, link, unlink, mkdir, etc. , I'm wondering if there'll be a dramatic negative impact on file operations performance. Is there any efficient method to measure this ?
In any case, thanks for all the help you gave me :)
Regards,
Laurent Sinitambirivoutin
[email protected]
Quoted 10 lines · Alan Cox
Quoted 6 lines
I've encountered this problem before, too. What is the "One True Way" to do this cleanly? In other words, if you want to do a calculation once every time someone runs "cat
/proc/foo", what is the cleanest way to do that? The solution we came up with was to check the file offset and only do the calculation if offset == 0, which seems pretty hackish.Another approach is to do the calculation open and remember it in per fd private data. You can recover that and free it on release. It could even be a buffer holding the actual "content"
It might also be an idea to export proc_calc_metrics() from fs/proc/proc_misc.c because quite a lot of code actually tries to do exactly the same.
Erik
Signature · 5 lines
J.A.K. (Erik) Mouw, Information and Communication Theory Group, Faculty of Information Technology and Systems, Delft University of Technology, PO BOX 5031, 2600 GA Delft, The Netherlands Phone: +31-15-2783635 Fax: +31-15-2781843 Email: [email protected] WWW: http://www-ict.its.tudelft.nl/~erik/
Quoted 8 lines · Erik Mouw
Quoted 7 lines · Alan Cox
Quoted 6 lines
I've encountered this problem before, too. What is the "One True Way" to do this cleanly? In other words, if you want to do a calculation once every time someone runs "cat
/proc/foo", what is the cleanest way to do that? The solution we came up with was to check the file offset and only do the calculation if offset == 0, which seems pretty hackish.
Quoted 7 lines
Quoted 3 lines
Another approach is to do the calculation open and remember it in per fd private data. You can recover that and free it on release. It could even be a buffer holding the actual "content"
It might also be an idea to export
proc_calc_metrics()fromfs/proc/proc_misc.cbecause quite a lot of code actually tries to do exactly the same.
Look at all the parameters, they're trying to be a struct. How about cleaning it up before exporting?
Signature · 1 line
Daniel
Quoted 7 lines · Daniel Phillips
Quoted 3 lines · Erik Mouw
It might also be an idea to export
proc_calc_metrics()fromfs/proc/proc_misc.cbecause quite a lot of code actually tries to do exactly the same.Look at all the parameters, they're trying to be a struct. How about cleaning it up before exporting?
Look at all the parameters of a procfs read() function and compare them with the parameters of proc_calc_metrics(). See why cleaning up would make things only more complicated?
Erik
Signature · 5 lines
J.A.K. (Erik) Mouw, Information and Communication Theory Group, Faculty of Information Technology and Systems, Delft University of Technology, PO BOX 5031, 2600 GA Delft, The Netherlands Phone: +31-15-2783635 Fax: +31-15-2781843 Email: [email protected] WWW: http://www-ict.its.tudelft.nl/~erik/
Quoted 6 lines · Erik Mouw
Quoted 5 lines · Daniel Phillips
Quoted 3 lines · Erik Mouw
It might also be an idea to export
proc_calc_metrics()fromfs/proc/proc_misc.cbecause quite a lot of code actually tries to do exactly the same.
Quoted 6 lines
Quoted 2 lines
Look at all the parameters, they're trying to be a struct. How about cleaning it up before exporting?
Look at all the parameters of a procfs
read()function and compare them with the parameters ofproc_calc_metrics(). See why cleaning up would make things only more complicated?
Oh, for fsck sake...
We already have better mechanism. Let ->proc_read() die, it's an ugly kludge, breeding overcomplicated code and buffer overflows.
Quoted 4 lines · Laurent
Quoted 2 lines
We already have better mechanism. Let ->proc_read() die, it's an ugly kludge, breeding overcomplicated code and buffer overflows.
What better mechanism ??
seq_file.c and seq_file.h. Grep around for stuff using it.
Quoted 2 lines
We already have better mechanism. Let ->proc_read() die, it's an ugly kludge, breeding overcomplicated code and buffer overflows.
What better mechanism ??
Signature · 2 lines
Laurent Sinitambirivoutin [email protected]
Yes, please kill it! seq files are much better and don't give people as much of a chance to do things the wrong way. Fewer interfaces to /proc would be vast improvement.
} Oh, for fsck sake...
}
} We already have better mechanism. Let ->proc_read() die, it's an ugly } kludge, breeding overcomplicated code and buffer overflows.
}
} -
} To unsubscribe from this list: send the line "unsubscribe linux-kernel" in } the body of a message to [email protected]
} More majordomo info at http://vger.kernel.org/majordomo-info.html
} Please read the FAQ at http://www.tux.org/lkml/