#include <linux/major.h>
#include <linux/errno.h>
#include <linux/module.h>
-#include <linux/smp_lock.h>
#include <linux/seq_file.h>
#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/backing-dev.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
#include "internal.h"
/*
unsigned int baseminor;
int minorct;
char name[64];
- struct file_operations *fops;
struct cdev *cdev; /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
cd->major = major;
cd->baseminor = baseminor;
cd->minorct = minorct;
- strncpy(cd->name,name, 64);
+ strlcpy(cd->name, name, sizeof(cd->name));
i = major_to_index(major);
return -ENXIO;
new = container_of(kobj, struct cdev, kobj);
spin_lock(&cdev_lock);
+ /* Check i_cdev again in case somebody beat us to it while
+ we dropped the lock. */
p = inode->i_cdev;
if (!p) {
inode->i_cdev = p = new;
- inode->i_cindex = idx;
list_add(&inode->i_devices, &p->list);
new = NULL;
} else if (!cdev_get(p))
cdev_put(new);
if (ret)
return ret;
+
+ ret = -ENXIO;
filp->f_op = fops_get(p->ops);
- if (!filp->f_op) {
- cdev_put(p);
- return -ENXIO;
- }
+ if (!filp->f_op)
+ goto out_cdev_put;
+
if (filp->f_op->open) {
- lock_kernel();
ret = filp->f_op->open(inode,filp);
- unlock_kernel();
+ if (ret)
+ goto out_cdev_put;
}
- if (ret)
- cdev_put(p);
+
+ return 0;
+
+ out_cdev_put:
+ cdev_put(p);
return ret;
}
+int cdev_index(struct inode *inode)
+{
+ int idx;
+ struct kobject *kobj;
+
+ kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
+ if (!kobj)
+ return -1;
+ kobject_put(kobj);
+ return idx;
+}
+
void cd_forget(struct inode *inode)
{
spin_lock(&cdev_lock);
EXPORT_SYMBOL(cdev_alloc);
EXPORT_SYMBOL(cdev_del);
EXPORT_SYMBOL(cdev_add);
+EXPORT_SYMBOL(cdev_index);
EXPORT_SYMBOL(register_chrdev);
EXPORT_SYMBOL(unregister_chrdev);
EXPORT_SYMBOL(directly_mappable_cdev_bdi);