consolidate the reassignments of ->f_op in ->open() instances
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 22 Sep 2013 18:17:15 +0000 (14:17 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 25 Oct 2013 03:34:53 +0000 (23:34 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
drivers/char/misc.c
drivers/gpu/drm/drm_fops.c
drivers/media/dvb-core/dvbdev.c
drivers/usb/core/file.c
fs/char_dev.c
include/linux/fs.h
sound/core/sound.c
sound/sound_core.c

index 190d4423653f6b99690967ba3602915eda5463fb..fd0f7c4b4df9dd8503e7f8c788628a892f8bc2f1 100644 (file)
@@ -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 *old_fops, *new_fops = NULL;
+       const struct file_operations *new_fops = NULL;
 
        mutex_lock(&misc_mtx);
        
@@ -141,17 +141,11 @@ static int misc_open(struct inode * inode, struct file * file)
        }
 
        err = 0;
-       old_fops = file->f_op;
-       file->f_op = new_fops;
+       replace_fops(file, new_fops);
        if (file->f_op->open) {
                file->private_data = c;
-               err=file->f_op->open(inode,file);
-               if (err) {
-                       fops_put(file->f_op);
-                       file->f_op = fops_get(old_fops);
-               }
+               err = file->f_op->open(inode,file);
        }
-       fops_put(old_fops);
 fail:
        mutex_unlock(&misc_mtx);
        return err;
index 3f84277d7036b3f843120fb4145dc081010d3d0d..22d14ecbd3ec0621fd0f4d1ce61b895f224e4780 100644 (file)
@@ -148,7 +148,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
        struct drm_minor *minor;
        int minor_id = iminor(inode);
        int err = -ENODEV;
-       const struct file_operations *old_fops;
+       const struct file_operations *new_fops;
 
        DRM_DEBUG("\n");
 
@@ -163,18 +163,13 @@ int drm_stub_open(struct inode *inode, struct file *filp)
        if (drm_device_is_unplugged(dev))
                goto out;
 
-       old_fops = filp->f_op;
-       filp->f_op = fops_get(dev->driver->fops);
-       if (filp->f_op == NULL) {
-               filp->f_op = old_fops;
+       new_fops = fops_get(dev->driver->fops);
+       if (!new_fops)
                goto out;
-       }
-       if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
-               fops_put(filp->f_op);
-               filp->f_op = fops_get(old_fops);
-       }
-       fops_put(old_fops);
 
+       replace_fops(filp, new_fops);
+       if (filp->f_op->open)
+               err = filp->f_op->open(inode, filp);
 out:
        mutex_unlock(&drm_global_mutex);
        return err;
index 401ef64f92c66afb6be28a98b5c2e8b2308d4e5a..983db75de3503952545f88700858f7a24131a9f9 100644 (file)
@@ -74,22 +74,15 @@ static int dvb_device_open(struct inode *inode, struct file *file)
 
        if (dvbdev && dvbdev->fops) {
                int err = 0;
-               const struct file_operations *old_fops;
+               const struct file_operations *new_fops;
 
-               file->private_data = dvbdev;
-               old_fops = file->f_op;
-               file->f_op = fops_get(dvbdev->fops);
-               if (file->f_op == NULL) {
-                       file->f_op = old_fops;
+               new_fops = fops_get(dvbdev->fops);
+               if (!new_fops)
                        goto fail;
-               }
-               if(file->f_op->open)
+               file->private_data = dvbdev;
+               replace_fops(file, new_fops);
+               if (file->f_op->open)
                        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);
                up_read(&minor_rwsem);
                mutex_unlock(&dvbdev_mutex);
                return err;
index 7421888087a3b752a3915c0dc70bfcda640d9122..fe0d8365411aba387a37ad0ba678a785a488a2f1 100644 (file)
@@ -29,27 +29,19 @@ static DECLARE_RWSEM(minor_rwsem);
 
 static int usb_open(struct inode * inode, struct file * file)
 {
-       int minor = iminor(inode);
-       const struct file_operations *c;
        int err = -ENODEV;
-       const struct file_operations *old_fops, *new_fops = NULL;
+       const struct file_operations *new_fops;
 
        down_read(&minor_rwsem);
-       c = usb_minors[minor];
+       new_fops = fops_get(usb_minors[iminor(inode)]);
 
-       if (!c || !(new_fops = fops_get(c)))
+       if (!new_fops)
                goto done;
 
-       old_fops = file->f_op;
-       file->f_op = new_fops;
+       replace_fops(file, new_fops);
        /* Curiouser and curiouser... NULL ->open() as "no device" ? */
        if (file->f_op->open)
                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);
  done:
        up_read(&minor_rwsem);
        return err;
index afc2bb6917806e85ee916d8b2c25cb2183890055..94b5f60076daf7f41af7a87671e7bd17cf11925b 100644 (file)
@@ -368,6 +368,7 @@ void cdev_put(struct cdev *p)
  */
 static int chrdev_open(struct inode *inode, struct file *filp)
 {
+       const struct file_operations *fops;
        struct cdev *p;
        struct cdev *new = NULL;
        int ret = 0;
@@ -400,10 +401,11 @@ static int chrdev_open(struct inode *inode, struct file *filp)
                return ret;
 
        ret = -ENXIO;
-       filp->f_op = fops_get(p->ops);
-       if (!filp->f_op)
+       fops = fops_get(p->ops);
+       if (!fops)
                goto out_cdev_put;
 
+       replace_fops(filp, fops);
        if (filp->f_op->open) {
                ret = filp->f_op->open(inode, filp);
                if (ret)
index d80c2437d624d832d43c0756b3e5d0aae4ae50ad..b09e4e1d747a07d81c01840895e9a12a76ac69dd 100644 (file)
@@ -1875,6 +1875,17 @@ extern struct dentry *mount_pseudo(struct file_system_type *, char *,
        (((fops) && try_module_get((fops)->owner) ? (fops) : NULL))
 #define fops_put(fops) \
        do { if (fops) module_put((fops)->owner); } while(0)
+/*
+ * This one is to be used *ONLY* from ->open() instances.
+ * fops must be non-NULL, pinned down *and* module dependencies
+ * should be sufficient to pin the caller down as well.
+ */
+#define replace_fops(f, fops) \
+       do {    \
+               struct file *__file = (f); \
+               fops_put(__file->f_op); \
+               BUG_ON(!(__file->f_op = (fops))); \
+       } while(0)
 
 extern int register_filesystem(struct file_system_type *);
 extern int unregister_filesystem(struct file_system_type *);
index f002bd911dae21f102d114d97bace85b8f12190d..437c25ea640363b5d38d8214e873cb236f1aec43 100644 (file)
@@ -153,7 +153,7 @@ static int snd_open(struct inode *inode, struct file *file)
 {
        unsigned int minor = iminor(inode);
        struct snd_minor *mptr = NULL;
-       const struct file_operations *old_fops;
+       const struct file_operations *new_fops;
        int err = 0;
 
        if (minor >= ARRAY_SIZE(snd_minors))
@@ -167,24 +167,14 @@ static int snd_open(struct inode *inode, struct file *file)
                        return -ENODEV;
                }
        }
-       old_fops = file->f_op;
-       file->f_op = fops_get(mptr->f_ops);
-       if (file->f_op == NULL) {
-               file->f_op = old_fops;
-               err = -ENODEV;
-       }
+       new_fops = fops_get(mptr->f_ops);
        mutex_unlock(&sound_mutex);
-       if (err < 0)
-               return err;
+       if (!new_fops)
+               return -ENODEV;
+       replace_fops(file, new_fops);
 
-       if (file->f_op->open) {
+       if (file->f_op->open)
                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);
        return err;
 }
 
index 45759f4cca754488d38f15bcae85b161a85fb4a9..11e953a1fa45a06ab9243eca4d99d5b3f16ea9ef 100644 (file)
@@ -626,31 +626,20 @@ static int soundcore_open(struct inode *inode, struct file *file)
                if (s)
                        new_fops = fops_get(s->unit_fops);
        }
+       spin_unlock(&sound_loader_lock);
        if (new_fops) {
                /*
                 * We rely upon the fact that we can't be unloaded while the
-                * subdriver is there, so if ->open() is successful we can
-                * safely drop the reference counter and if it is not we can
-                * revert to old ->f_op. Ugly, indeed, but that's the cost of
-                * switching ->f_op in the first place.
+                * subdriver is there.
                 */
                int err = 0;
-               const struct file_operations *old_fops = file->f_op;
-               file->f_op = new_fops;
-               spin_unlock(&sound_loader_lock);
+               replace_fops(file, new_fops);
 
                if (file->f_op->open)
                        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);
                return err;
        }
-       spin_unlock(&sound_loader_lock);
        return -ENODEV;
 }