X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fchar_dev.c;h=f3418f7a6e9d9da9bf894840cd23eba9be77d5b7;hb=bbb1747d4e44ce49acc73daa8d66e5f6bd546f1b;hp=3b1b1eefdbb01686f127df582143f922bf87c193;hpb=ef88b7dba2b47c70037a34a599d383462bb74bd3;p=linux-2.6 diff --git a/fs/char_dev.c b/fs/char_dev.c index 3b1b1eefdb..f3418f7a6e 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -15,10 +15,12 @@ #include #include #include +#include #include #include #include +#include #ifdef CONFIG_KMOD #include @@ -26,56 +28,40 @@ static struct kobj_map *cdev_map; -#define MAX_PROBE_HASH 255 /* random */ - -static DECLARE_MUTEX(chrdevs_lock); +static DEFINE_MUTEX(chrdevs_lock); static struct char_device_struct { struct char_device_struct *next; 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]; +} *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; /* index in the above */ static inline int major_to_index(int major) { - return major % MAX_PROBE_HASH; + return major % CHRDEV_MAJOR_HASH_SIZE; } -/* get char device names in somewhat random order */ -int get_chrdev_list(char *page) +#ifdef CONFIG_PROC_FS + +void chrdev_show(struct seq_file *f, off_t offset) { struct char_device_struct *cd; - int i, len; - - len = sprintf(page, "Character devices:\n"); - - down(&chrdevs_lock); - 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); - } + if (offset < CHRDEV_MAJOR_HASH_SIZE) { + mutex_lock(&chrdevs_lock); + for (cd = chrdevs[offset]; cd; cd = cd->next) + seq_printf(f, "%3d %s\n", cd->major, cd->name); + mutex_unlock(&chrdevs_lock); } -page_full: - up(&chrdevs_lock); - - return len; } +#endif /* CONFIG_PROC_FS */ + /* * Register a single major with a specified minor range. * @@ -95,13 +81,11 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, int ret = 0; int i; - cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL); + cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL); if (cd == NULL) return ERR_PTR(-ENOMEM); - memset(cd, 0, sizeof(struct char_device_struct)); - - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); /* temporary */ if (major == 0) { @@ -121,7 +105,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); @@ -136,10 +120,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, } cd->next = *cp; *cp = cd; - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); return cd; out: - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); kfree(cd); return ERR_PTR(ret); } @@ -150,7 +134,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) struct char_device_struct *cd = NULL, **cp; int i = major_to_index(major); - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) if ((*cp)->major == major && (*cp)->baseminor == baseminor && @@ -160,7 +144,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) cd = *cp; *cp = cd->next; } - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); return cd; } @@ -201,7 +185,7 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, } int register_chrdev(unsigned int major, const char *name, - struct file_operations *fops) + const struct file_operations *fops) { struct char_device_struct *cd; struct cdev *cdev; @@ -357,7 +341,7 @@ static void cdev_purge(struct cdev *cdev) * is contain the open that then fills in the correct operations * depending on the special file... */ -struct file_operations def_chr_fops = { +const struct file_operations def_chr_fops = { .open = chrdev_open, }; @@ -415,9 +399,8 @@ static struct kobj_type ktype_cdev_dynamic = { struct cdev *cdev_alloc(void) { - struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL); + struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); if (p) { - memset(p, 0, sizeof(struct cdev)); p->kobj.ktype = &ktype_cdev_dynamic; INIT_LIST_HEAD(&p->list); kobject_init(&p->kobj); @@ -425,7 +408,7 @@ struct cdev *cdev_alloc(void) return p; } -void cdev_init(struct cdev *cdev, struct file_operations *fops) +void cdev_init(struct cdev *cdev, const struct file_operations *fops) { memset(cdev, 0, sizeof *cdev); INIT_LIST_HEAD(&cdev->list);