This patch breaks set_selection() into two functions so that when
called from kernel, copy_from_user() can be avoided. The two functions
are called set_selection_user() and set_selection_kernel() in order to
be explicit about their purposes. This also means updating any
references to set_selection() and fixing for name change. It also
exports set_selection_kernel() and paste_selection().

These changes are used the following patch where speakup's selection
functionality calls into the above functions, thereby doing away with
parallel implementation.

Signed-off-by: Okash Khawaja <okash.khaw...@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thiba...@ens-lyon.org>
Tested-by: Gregory Nowak <g...@gregn.net>
---
 drivers/tty/vt/selection.c | 46 ++++++++++++++++++++++++++++++----------------
 drivers/tty/vt/vt.c        |  7 ++++---
 include/linux/selection.h  |  7 ++++---
 3 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 07496c7..78732fe 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -2,7 +2,9 @@
 /*
  * This module exports the functions:
  *
- *     'int set_selection(struct tiocl_selection __user *, struct tty_struct 
*)'
+ *     'int set_selection_user(struct tiocl_selection __user *,
+ *                            struct tty_struct *)'
+ *     'int set_selection_kernel(struct tiocl_selection *, struct tty_struct 
*)'
  *     'void clear_selection(void)'
  *     'int paste_selection(struct tty_struct *)'
  *     'int sel_loadlut(char __user *)'
@@ -80,6 +82,7 @@ void clear_selection(void)
                sel_start = -1;
        }
 }
+EXPORT_SYMBOL_GPL(clear_selection);
 
 /*
  * User settable table: what characters are to be considered alphabetic?
@@ -154,7 +157,7 @@ static int store_utf8(u32 c, char *p)
 }
 
 /**
- *     set_selection           -       set the current selection.
+ *     set_selection_user      -       set the current selection.
  *     @sel: user selection info
  *     @tty: the console tty
  *
@@ -163,35 +166,44 @@ static int store_utf8(u32 c, char *p)
  *     The entire selection process is managed under the console_lock. It's
  *      a lot under the lock but its hardly a performance path
  */
-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct 
*tty)
+int set_selection_user(const struct tiocl_selection __user *sel,
+                      struct tty_struct *tty)
+{
+       struct tiocl_selection v;
+
+       if (copy_from_user(&v, sel, sizeof(*sel)))
+               return -EFAULT;
+
+       return set_selection_kernel(&v, tty);
+}
+
+int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
 {
        struct vc_data *vc = vc_cons[fg_console].d;
        int new_sel_start, new_sel_end, spc;
-       struct tiocl_selection v;
        char *bp, *obp;
        int i, ps, pe, multiplier;
        u32 c;
        int mode;
 
        poke_blanked_console();
-       if (copy_from_user(&v, sel, sizeof(*sel)))
-               return -EFAULT;
 
-       v.xs = min_t(u16, v.xs - 1, vc->vc_cols - 1);
-       v.ys = min_t(u16, v.ys - 1, vc->vc_rows - 1);
-       v.xe = min_t(u16, v.xe - 1, vc->vc_cols - 1);
-       v.ye = min_t(u16, v.ye - 1, vc->vc_rows - 1);
-       ps = v.ys * vc->vc_size_row + (v.xs << 1);
-       pe = v.ye * vc->vc_size_row + (v.xe << 1);
+       v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
+       v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
+       v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
+       v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
+       ps = v->ys * vc->vc_size_row + (v->xs << 1);
+       pe = v->ye * vc->vc_size_row + (v->xe << 1);
 
-       if (v.sel_mode == TIOCL_SELCLEAR) {
+       if (v->sel_mode == TIOCL_SELCLEAR) {
                /* useful for screendump without selection highlights */
                clear_selection();
                return 0;
        }
 
-       if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) {
-               mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys);
+       if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
+               mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
+                            v->ys);
                return 0;
        }
 
@@ -208,7 +220,7 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
        else
                use_unicode = 0;
 
-       switch (v.sel_mode)
+       switch (v->sel_mode)
        {
                case TIOCL_SELCHAR:     /* character-by-character selection */
                        new_sel_start = ps;
@@ -322,6 +334,7 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
        sel_buffer_lth = bp - sel_buffer;
        return 0;
 }
+EXPORT_SYMBOL_GPL(set_selection_kernel);
 
 /* Insert the contents of the selection buffer into the
  * queue of the tty associated with the current console.
@@ -367,3 +380,4 @@ int paste_selection(struct tty_struct *tty)
        tty_ldisc_deref(ld);
        return 0;
 }
+EXPORT_SYMBOL_GPL(paste_selection);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index d34984a..f3c369a 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1804,7 +1804,7 @@ void mouse_report(struct tty_struct *tty, int butt, int 
mrx, int mry)
        respond_string(buf, tty->port);
 }
 
-/* invoked via ioctl(TIOCLINUX) and through set_selection */
+/* invoked via ioctl(TIOCLINUX) and through set_selection_user */
 int mouse_reporting(void)
 {
        return vc_cons[fg_console].d->vc_report_mouse;
@@ -3008,7 +3008,7 @@ static struct tty_driver *vt_console_device(struct 
console *c, int *index)
  * There are some functions which can sleep for arbitrary periods
  * (paste_selection) but we don't need the lock there anyway.
  *
- * set_selection has locking, and definitely needs it
+ * set_selection_user has locking, and definitely needs it
  */
 
 int tioclinux(struct tty_struct *tty, unsigned long arg)
@@ -3028,7 +3028,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
        {
                case TIOCL_SETSEL:
                        console_lock();
-                       ret = set_selection((struct tiocl_selection __user 
*)(p+1), tty);
+                       ret = set_selection_user((struct tiocl_selection
+                                                __user *)(p+1), tty);
                        console_unlock();
                        break;
                case TIOCL_PASTESEL:
diff --git a/include/linux/selection.h b/include/linux/selection.h
index a8f5b97..e2c1f96 100644
--- a/include/linux/selection.h
+++ b/include/linux/selection.h
@@ -11,13 +11,14 @@
 #include <linux/tiocl.h>
 #include <linux/vt_buffer.h>
 
-struct tty_struct;
-
 extern struct vc_data *sel_cons;
 struct tty_struct;
 
 extern void clear_selection(void);
-extern int set_selection(const struct tiocl_selection __user *sel, struct 
tty_struct *tty);
+extern int set_selection_user(const struct tiocl_selection __user *sel,
+                             struct tty_struct *tty);
+extern int set_selection_kernel(struct tiocl_selection *v,
+                               struct tty_struct *tty);
 extern int paste_selection(struct tty_struct *tty);
 extern int sel_loadlut(char __user *p);
 extern int mouse_reporting(void);
-- 
1.8.3.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to