Skip to content

Commit 8a932f7

Browse files
lsgunthgregkh
authored andcommitted
char_dev: order /proc/devices by major number
Presently, the order of the char devices listed in /proc/devices is not entirely sequential. If a char device has a major number greater than CHRDEV_MAJOR_HASH_SIZE (255), it will be ordered as if its major were module 255. For example, 511 appears after 1. This patch cleans that up and prints each major number in the correct order, regardless of where they are stored in the hash table. In order to do this, we introduce CHRDEV_MAJOR_MAX as an artificial limit (chosen to be 511). It will then print all devices in major order number from 0 to the maximum. Signed-off-by: Logan Gunthorpe <logang@deltatee.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Alan Cox <alan@linux.intel.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent a5d31a3 commit 8a932f7

3 files changed

Lines changed: 18 additions & 9 deletions

File tree

fs/char_dev.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ static struct kobj_map *cdev_map;
2828

2929
static DEFINE_MUTEX(chrdevs_lock);
3030

31+
#define CHRDEV_MAJOR_HASH_SIZE 255
32+
3133
static struct char_device_struct {
3234
struct char_device_struct *next;
3335
unsigned int major;
@@ -49,12 +51,12 @@ void chrdev_show(struct seq_file *f, off_t offset)
4951
{
5052
struct char_device_struct *cd;
5153

52-
if (offset < CHRDEV_MAJOR_HASH_SIZE) {
53-
mutex_lock(&chrdevs_lock);
54-
for (cd = chrdevs[offset]; cd; cd = cd->next)
54+
mutex_lock(&chrdevs_lock);
55+
for (cd = chrdevs[major_to_index(offset)]; cd; cd = cd->next) {
56+
if (cd->major == offset)
5557
seq_printf(f, "%3d %s\n", cd->major, cd->name);
56-
mutex_unlock(&chrdevs_lock);
5758
}
59+
mutex_unlock(&chrdevs_lock);
5860
}
5961

6062
#endif /* CONFIG_PROC_FS */
@@ -117,6 +119,13 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
117119
major = ret;
118120
}
119121

122+
if (major >= CHRDEV_MAJOR_MAX) {
123+
pr_err("CHRDEV \"%s\" major requested (%d) is greater than the maximum (%d)\n",
124+
name, major, CHRDEV_MAJOR_MAX);
125+
ret = -EINVAL;
126+
goto out;
127+
}
128+
120129
cd->major = major;
121130
cd->baseminor = baseminor;
122131
cd->minorct = minorct;

fs/proc/devices.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ static int devinfo_show(struct seq_file *f, void *v)
77
{
88
int i = *(loff_t *) v;
99

10-
if (i < CHRDEV_MAJOR_HASH_SIZE) {
10+
if (i < CHRDEV_MAJOR_MAX) {
1111
if (i == 0)
1212
seq_puts(f, "Character devices:\n");
1313
chrdev_show(f, i);
1414
}
1515
#ifdef CONFIG_BLOCK
1616
else {
17-
i -= CHRDEV_MAJOR_HASH_SIZE;
17+
i -= CHRDEV_MAJOR_MAX;
1818
if (i == 0)
1919
seq_puts(f, "\nBlock devices:\n");
2020
blkdev_show(f, i);
@@ -25,15 +25,15 @@ static int devinfo_show(struct seq_file *f, void *v)
2525

2626
static void *devinfo_start(struct seq_file *f, loff_t *pos)
2727
{
28-
if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
28+
if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_MAX))
2929
return pos;
3030
return NULL;
3131
}
3232

3333
static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
3434
{
3535
(*pos)++;
36-
if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
36+
if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_MAX))
3737
return NULL;
3838
return pos;
3939
}

include/linux/fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2470,7 +2470,7 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev,
24702470
#endif
24712471

24722472
/* fs/char_dev.c */
2473-
#define CHRDEV_MAJOR_HASH_SIZE 255
2473+
#define CHRDEV_MAJOR_MAX 512
24742474
/* Marks the bottom of the first segment of free char majors */
24752475
#define CHRDEV_MAJOR_DYN_END 234
24762476
/* Marks the top and bottom of the second segment of free char majors */

0 commit comments

Comments
 (0)