diff options
Diffstat (limited to 'drivers/char/misc.c')
-rw-r--r-- | drivers/char/misc.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index ffa97d2..190d442 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -114,7 +114,7 @@ static int misc_open(struct inode * inode, struct file * file) int minor = iminor(inode); struct miscdevice *c; int err = -ENODEV; - const struct file_operations *new_fops = NULL; + const struct file_operations *old_fops, *new_fops = NULL; mutex_lock(&misc_mtx); @@ -141,11 +141,17 @@ static int misc_open(struct inode * inode, struct file * file) } err = 0; - replace_fops(file, new_fops); + old_fops = file->f_op; + file->f_op = new_fops; if (file->f_op->open) { file->private_data = c; - err = file->f_op->open(inode,file); + err=file->f_op->open(inode,file); + if (err) { + fops_put(file->f_op); + file->f_op = fops_get(old_fops); + } } + fops_put(old_fops); fail: mutex_unlock(&misc_mtx); return err; @@ -187,8 +193,8 @@ int misc_register(struct miscdevice * misc) if (misc->minor == MISC_DYNAMIC_MINOR) { int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); if (i >= DYNAMIC_MINORS) { - err = -EBUSY; - goto out; + mutex_unlock(&misc_mtx); + return -EBUSY; } misc->minor = DYNAMIC_MINORS - i - 1; set_bit(i, misc_minors); @@ -197,8 +203,8 @@ int misc_register(struct miscdevice * misc) list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { - err = -EBUSY; - goto out; + mutex_unlock(&misc_mtx); + return -EBUSY; } } } |