Skip to content

Commit

Permalink
[PATCH] convert /proc/devices to use seq_file interface
Browse files Browse the repository at this point in the history
A Christoph suggested that the /proc/devices file be converted to use the
seq_file interface.  This patch does that.

I've obxerved one or two installation that had sufficiently large sans that
they overran the 4k limit on /proc/devices.

Signed-off-by: Neil Horman <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Neil Horman authored and Linus Torvalds committed Jan 15, 2006
1 parent faf3a98 commit 7170be5
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 53 deletions.
106 changes: 86 additions & 20 deletions block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,100 @@ static inline int major_to_index(int major)
return major % MAX_PROBE_HASH;
}

#ifdef CONFIG_PROC_FS
/* get block device names in somewhat random order */
int get_blkdev_list(char *p, int used)
struct blkdev_info {
int index;
struct blk_major_name *bd;
};

/*
* iterate over a list of blkdev_info structures. allows
* the major_names array to be iterated over from outside this file
* must be called with the block_subsys_sem held
*/
void *get_next_blkdev(void *dev)
{
struct blkdev_info *info;

if (dev == NULL) {
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
goto out;
info->index=0;
info->bd = major_names[info->index];
if (info->bd)
goto out;
} else {
info = dev;
}

while (info->index < ARRAY_SIZE(major_names)) {
if (info->bd)
info->bd = info->bd->next;
if (info->bd)
goto out;
/*
* No devices on this chain, move to the next
*/
info->index++;
info->bd = (info->index < ARRAY_SIZE(major_names)) ?
major_names[info->index] : NULL;
if (info->bd)
goto out;
}

out:
return info;
}

void *acquire_blkdev_list(void)
{
down(&block_subsys_sem);
return get_next_blkdev(NULL);
}

void release_blkdev_list(void *dev)
{
up(&block_subsys_sem);
kfree(dev);
}


/*
* Count the number of records in the blkdev_list.
* must be called with the block_subsys_sem held
*/
int count_blkdev_list(void)
{
struct blk_major_name *n;
int i, len;
int i, count;

len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n");
count = 0;

down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
for (n = major_names[i]; n; n = n->next) {
/*
* If the curent string plus the 5 extra characters
* in the line would run us off the page, then we're done
*/
if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
goto page_full;
len += sprintf(p+len, "%3d %s\n",
n->major, n->name);
}
for (n = major_names[i]; n; n = n->next)
count++;
}
page_full:
up(&block_subsys_sem);

return len;
return count;
}
#endif

/*
* extract the major and name values from a blkdev_info struct
* passed in as a void to *dev. Must be called with
* block_subsys_sem held
*/
int get_blkdev_info(void *dev, int *major, char **name)
{
struct blkdev_info *info = dev;

if (info->bd == NULL)
return 1;

*major = info->bd->major;
*name = info->bd->name;
return 0;
}


int register_blkdev(unsigned int major, const char *name)
{
Expand Down
96 changes: 73 additions & 23 deletions fs/char_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static struct char_device_struct {
unsigned int major;
unsigned int baseminor;
int minorct;
const char *name;
char name[64];
struct file_operations *fops;
struct cdev *cdev; /* will die */
} *chrdevs[MAX_PROBE_HASH];
Expand All @@ -46,34 +46,84 @@ static inline int major_to_index(int major)
return major % MAX_PROBE_HASH;
}

/* get char device names in somewhat random order */
int get_chrdev_list(char *page)
{
struct chrdev_info {
int index;
struct char_device_struct *cd;
int i, len;
};

len = sprintf(page, "Character devices:\n");
void *get_next_chrdev(void *dev)
{
struct chrdev_info *info;

if (dev == NULL) {
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
goto out;
info->index=0;
info->cd = chrdevs[info->index];
if (info->cd)
goto out;
} else {
info = dev;
}

while (info->index < ARRAY_SIZE(chrdevs)) {
if (info->cd)
info->cd = info->cd->next;
if (info->cd)
goto out;
/*
* No devices on this chain, move to the next
*/
info->index++;
info->cd = (info->index < ARRAY_SIZE(chrdevs)) ?
chrdevs[info->index] : NULL;
if (info->cd)
goto out;
}

out:
return info;
}

void *acquire_chrdev_list(void)
{
down(&chrdevs_lock);
return get_next_chrdev(NULL);
}

void release_chrdev_list(void *dev)
{
up(&chrdevs_lock);
kfree(dev);
}


int count_chrdev_list(void)
{
struct char_device_struct *cd;
int i, count;

count = 0;

for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
for (cd = chrdevs[i]; cd; cd = cd->next) {
/*
* if the current name, plus the 5 extra characters
* in the device line for this entry
* would run us off the page, we're done
*/
if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
goto page_full;


len += sprintf(page+len, "%3d %s\n",
cd->major, cd->name);
}
for (cd = chrdevs[i]; cd; cd = cd->next)
count++;
}
page_full:
up(&chrdevs_lock);

return len;
return count;
}

int get_chrdev_info(void *dev, int *major, char **name)
{
struct chrdev_info *info = dev;

if (info->cd == NULL)
return 1;

*major = info->cd->major;
*name = info->cd->name;
return 0;
}

/*
Expand Down Expand Up @@ -121,7 +171,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
cd->major = major;
cd->baseminor = baseminor;
cd->minorct = minorct;
cd->name = name;
strncpy(cd->name,name, 64);

i = major_to_index(major);

Expand Down
Loading

0 comments on commit 7170be5

Please sign in to comment.