From 692c0509fd0719406f8f781d9a9f2e19aa6b7c0a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 21 Apr 2006 01:51:36 -0700 Subject: [PATCH] Simplify proc/devices and fix early termination regression Repair /proc/devices early-termination regression. 2.6.16 broke /proc/devices. An application often gets an EOF before the end of data is reached, if that application uses a series of short read(2)s to access the data. I have used read buffers of varying sizes with varying degrees of unsuccess (larger sizes get further into the data than smaller sizes, following a simple pattern). It appears that the only safe way to get the data is to use a single read buffer larger than all the data in /proc/devices. The following example demonstates the problem: # dd if=/proc/devices bs=1 Character devices: 1 mem 27+0 records in 27+0 records out This patch is a backport of the fix recently accepted to Linus's tree: commit 68eef3b4791572ecb70249c7fb145bb3742dd899 [PATCH] Simplify proc/devices and fix early termination regression It replaces the complex, state-machine algorithm introduced in 2.6.16 with a simple algorithm, modeled on the implementation of /proc/interrupts. [akpm@osdl.org: cleanups, simplifications] Signed-off-by: Joe Korty Signed-off-by: Greg Kroah-Hartman --- include/linux/fs.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index 128d0082522c..872042fd27e5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1383,6 +1383,7 @@ extern int bd_claim(struct block_device *, void *); extern void bd_release(struct block_device *); /* fs/char_dev.c */ +#define CHRDEV_MAJOR_HASH_SIZE 255 extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); extern int register_chrdev_region(dev_t, unsigned, const char *); extern int register_chrdev(unsigned int, const char *, @@ -1390,25 +1391,17 @@ extern int register_chrdev(unsigned int, const char *, extern int unregister_chrdev(unsigned int, const char *); extern void unregister_chrdev_region(dev_t, unsigned); extern int chrdev_open(struct inode *, struct file *); -extern int get_chrdev_list(char *); -extern void *acquire_chrdev_list(void); -extern int count_chrdev_list(void); -extern void *get_next_chrdev(void *); -extern int get_chrdev_info(void *, int *, char **); -extern void release_chrdev_list(void *); +extern void chrdev_show(struct seq_file *,off_t); /* fs/block_dev.c */ +#define BLKDEV_MAJOR_HASH_SIZE 255 #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ extern const char *__bdevname(dev_t, char *buffer); extern const char *bdevname(struct block_device *bdev, char *buffer); extern struct block_device *lookup_bdev(const char *); extern struct block_device *open_bdev_excl(const char *, int, void *); extern void close_bdev_excl(struct block_device *); -extern void *acquire_blkdev_list(void); -extern int count_blkdev_list(void); -extern void *get_next_blkdev(void *); -extern int get_blkdev_info(void *, int *, char **); -extern void release_blkdev_list(void *); +extern void blkdev_show(struct seq_file *,off_t); extern void init_special_inode(struct inode *, umode_t, dev_t); -- cgit v1.2.3