TTY: make tty_add_file non-failing
[linux-2.6-block.git] / drivers / tty / tty_io.c
index 6913da8f202cd7fc4f82c33ead60c462dcf9e3a5..767ecbb4761a9b24eb1af90d58b72c83e8d14b05 100644 (file)
@@ -194,8 +194,7 @@ static inline struct tty_struct *file_tty(struct file *file)
        return ((struct tty_file_private *)file->private_data)->tty;
 }
 
-/* Associate a new file with the tty structure */
-int tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_alloc_file(struct file *file)
 {
        struct tty_file_private *priv;
 
@@ -203,15 +202,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file)
        if (!priv)
                return -ENOMEM;
 
+       file->private_data = priv;
+
+       return 0;
+}
+
+/* Associate a new file with the tty structure */
+void tty_add_file(struct tty_struct *tty, struct file *file)
+{
+       struct tty_file_private *priv = file->private_data;
+
        priv->tty = tty;
        priv->file = file;
-       file->private_data = priv;
 
        spin_lock(&tty_files_lock);
        list_add(&priv->list, &tty->tty_files);
        spin_unlock(&tty_files_lock);
+}
 
-       return 0;
+/**
+ * tty_free_file - free file->private_data
+ *
+ * This shall be used only for fail path handling when tty_add_file was not
+ * called yet.
+ */
+void tty_free_file(struct file *file)
+{
+       struct tty_file_private *priv = file->private_data;
+
+       file->private_data = NULL;
+       kfree(priv);
 }
 
 /* Delete file from its tty */
@@ -222,8 +242,7 @@ void tty_del_file(struct file *file)
        spin_lock(&tty_files_lock);
        list_del(&priv->list);
        spin_unlock(&tty_files_lock);
-       file->private_data = NULL;
-       kfree(priv);
+       tty_free_file(file);
 }
 
 
@@ -1812,6 +1831,10 @@ static int tty_open(struct inode *inode, struct file *filp)
        nonseekable_open(inode, filp);
 
 retry_open:
+       retval = tty_alloc_file(filp);
+       if (retval)
+               return -ENOMEM;
+
        noctty = filp->f_flags & O_NOCTTY;
        index  = -1;
        retval = 0;
@@ -1824,6 +1847,7 @@ retry_open:
                if (!tty) {
                        tty_unlock();
                        mutex_unlock(&tty_mutex);
+                       tty_free_file(filp);
                        return -ENXIO;
                }
                driver = tty_driver_kref_get(tty->driver);
@@ -1856,6 +1880,7 @@ retry_open:
                }
                tty_unlock();
                mutex_unlock(&tty_mutex);
+               tty_free_file(filp);
                return -ENODEV;
        }
 
@@ -1863,6 +1888,7 @@ retry_open:
        if (!driver) {
                tty_unlock();
                mutex_unlock(&tty_mutex);
+               tty_free_file(filp);
                return -ENODEV;
        }
 got_driver:
@@ -1874,6 +1900,7 @@ got_driver:
                        tty_unlock();
                        mutex_unlock(&tty_mutex);
                        tty_driver_kref_put(driver);
+                       tty_free_file(filp);
                        return PTR_ERR(tty);
                }
        }
@@ -1889,15 +1916,11 @@ got_driver:
        tty_driver_kref_put(driver);
        if (IS_ERR(tty)) {
                tty_unlock();
+               tty_free_file(filp);
                return PTR_ERR(tty);
        }
 
-       retval = tty_add_file(tty, filp);
-       if (retval) {
-               tty_unlock();
-               tty_release(inode, filp);
-               return retval;
-       }
+       tty_add_file(tty, filp);
 
        check_tty_count(tty, "tty_open");
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&