Commit e53677113e32e6f118e31b8391a2eab7ee52c0a7
Committed by
Linus Torvalds
1 parent
978ccaa8ea
Exists in
master
and in
7 other branches
fb: push down the BKL in the ioctl handler
Framebuffer is heavily BKL dependant at the moment so just wrap the ioctl handler in the driver as we push down. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Alan Cox <alan@redhat.com> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Cc: "Antonino A. Daplas" <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 86 additions and 55 deletions Side-by-side Diff
drivers/video/fbmem.c
... | ... | @@ -1002,101 +1002,132 @@ |
1002 | 1002 | return ret; |
1003 | 1003 | } |
1004 | 1004 | |
1005 | -static int | |
1006 | -fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |
1005 | +static long | |
1006 | +fb_ioctl(struct file *file, unsigned int cmd, | |
1007 | 1007 | unsigned long arg) |
1008 | 1008 | { |
1009 | + struct inode *inode = file->f_path.dentry->d_inode; | |
1009 | 1010 | int fbidx = iminor(inode); |
1010 | - struct fb_info *info = registered_fb[fbidx]; | |
1011 | - struct fb_ops *fb = info->fbops; | |
1011 | + struct fb_info *info; | |
1012 | + struct fb_ops *fb; | |
1012 | 1013 | struct fb_var_screeninfo var; |
1013 | 1014 | struct fb_fix_screeninfo fix; |
1014 | 1015 | struct fb_con2fbmap con2fb; |
1015 | 1016 | struct fb_cmap_user cmap; |
1016 | 1017 | struct fb_event event; |
1017 | 1018 | void __user *argp = (void __user *)arg; |
1018 | - int i; | |
1019 | - | |
1020 | - if (!fb) | |
1019 | + long ret = 0; | |
1020 | + | |
1021 | + lock_kernel(); | |
1022 | + info = registered_fb[fbidx]; | |
1023 | + fb = info->fbops; | |
1024 | + | |
1025 | + if (!fb) { | |
1026 | + unlock_kernel(); | |
1021 | 1027 | return -ENODEV; |
1028 | + } | |
1022 | 1029 | switch (cmd) { |
1023 | 1030 | case FBIOGET_VSCREENINFO: |
1024 | - return copy_to_user(argp, &info->var, | |
1031 | + ret = copy_to_user(argp, &info->var, | |
1025 | 1032 | sizeof(var)) ? -EFAULT : 0; |
1033 | + break; | |
1026 | 1034 | case FBIOPUT_VSCREENINFO: |
1027 | - if (copy_from_user(&var, argp, sizeof(var))) | |
1028 | - return -EFAULT; | |
1035 | + if (copy_from_user(&var, argp, sizeof(var))) { | |
1036 | + ret = -EFAULT; | |
1037 | + break; | |
1038 | + } | |
1029 | 1039 | acquire_console_sem(); |
1030 | 1040 | info->flags |= FBINFO_MISC_USEREVENT; |
1031 | - i = fb_set_var(info, &var); | |
1041 | + ret = fb_set_var(info, &var); | |
1032 | 1042 | info->flags &= ~FBINFO_MISC_USEREVENT; |
1033 | 1043 | release_console_sem(); |
1034 | - if (i) return i; | |
1035 | - if (copy_to_user(argp, &var, sizeof(var))) | |
1036 | - return -EFAULT; | |
1037 | - return 0; | |
1044 | + if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | |
1045 | + ret = -EFAULT; | |
1046 | + break; | |
1038 | 1047 | case FBIOGET_FSCREENINFO: |
1039 | - return copy_to_user(argp, &info->fix, | |
1048 | + ret = copy_to_user(argp, &info->fix, | |
1040 | 1049 | sizeof(fix)) ? -EFAULT : 0; |
1050 | + break; | |
1041 | 1051 | case FBIOPUTCMAP: |
1042 | 1052 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
1043 | - return -EFAULT; | |
1044 | - return (fb_set_user_cmap(&cmap, info)); | |
1053 | + ret = -EFAULT; | |
1054 | + else | |
1055 | + ret = fb_set_user_cmap(&cmap, info); | |
1056 | + break; | |
1045 | 1057 | case FBIOGETCMAP: |
1046 | 1058 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
1047 | - return -EFAULT; | |
1048 | - return fb_cmap_to_user(&info->cmap, &cmap); | |
1059 | + ret = -EFAULT; | |
1060 | + else | |
1061 | + ret = fb_cmap_to_user(&info->cmap, &cmap); | |
1062 | + break; | |
1049 | 1063 | case FBIOPAN_DISPLAY: |
1050 | - if (copy_from_user(&var, argp, sizeof(var))) | |
1051 | - return -EFAULT; | |
1064 | + if (copy_from_user(&var, argp, sizeof(var))) { | |
1065 | + ret = -EFAULT; | |
1066 | + break; | |
1067 | + } | |
1052 | 1068 | acquire_console_sem(); |
1053 | - i = fb_pan_display(info, &var); | |
1069 | + ret = fb_pan_display(info, &var); | |
1054 | 1070 | release_console_sem(); |
1055 | - if (i) | |
1056 | - return i; | |
1057 | - if (copy_to_user(argp, &var, sizeof(var))) | |
1058 | - return -EFAULT; | |
1059 | - return 0; | |
1071 | + if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | |
1072 | + ret = -EFAULT; | |
1073 | + break; | |
1060 | 1074 | case FBIO_CURSOR: |
1061 | - return -EINVAL; | |
1075 | + ret = -EINVAL; | |
1076 | + break; | |
1062 | 1077 | case FBIOGET_CON2FBMAP: |
1063 | 1078 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
1064 | - return -EFAULT; | |
1065 | - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | |
1066 | - return -EINVAL; | |
1067 | - con2fb.framebuffer = -1; | |
1068 | - event.info = info; | |
1069 | - event.data = &con2fb; | |
1070 | - fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); | |
1071 | - return copy_to_user(argp, &con2fb, | |
1079 | + ret = -EFAULT; | |
1080 | + else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | |
1081 | + ret = -EINVAL; | |
1082 | + else { | |
1083 | + con2fb.framebuffer = -1; | |
1084 | + event.info = info; | |
1085 | + event.data = &con2fb; | |
1086 | + fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, | |
1087 | + &event); | |
1088 | + ret = copy_to_user(argp, &con2fb, | |
1072 | 1089 | sizeof(con2fb)) ? -EFAULT : 0; |
1090 | + } | |
1091 | + break; | |
1073 | 1092 | case FBIOPUT_CON2FBMAP: |
1074 | - if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | |
1075 | - return - EFAULT; | |
1076 | - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | |
1077 | - return -EINVAL; | |
1078 | - if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) | |
1079 | - return -EINVAL; | |
1093 | + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) { | |
1094 | + ret = -EFAULT; | |
1095 | + break; | |
1096 | + } | |
1097 | + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) { | |
1098 | + ret = -EINVAL; | |
1099 | + break; | |
1100 | + } | |
1101 | + if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) { | |
1102 | + ret = -EINVAL; | |
1103 | + break; | |
1104 | + } | |
1080 | 1105 | if (!registered_fb[con2fb.framebuffer]) |
1081 | - request_module("fb%d", con2fb.framebuffer); | |
1082 | - if (!registered_fb[con2fb.framebuffer]) | |
1083 | - return -EINVAL; | |
1106 | + request_module("fb%d", con2fb.framebuffer); | |
1107 | + if (!registered_fb[con2fb.framebuffer]) { | |
1108 | + ret = -EINVAL; | |
1109 | + break; | |
1110 | + } | |
1084 | 1111 | event.info = info; |
1085 | 1112 | event.data = &con2fb; |
1086 | - return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | |
1113 | + ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | |
1087 | 1114 | &event); |
1115 | + break; | |
1088 | 1116 | case FBIOBLANK: |
1089 | 1117 | acquire_console_sem(); |
1090 | 1118 | info->flags |= FBINFO_MISC_USEREVENT; |
1091 | - i = fb_blank(info, arg); | |
1119 | + ret = fb_blank(info, arg); | |
1092 | 1120 | info->flags &= ~FBINFO_MISC_USEREVENT; |
1093 | 1121 | release_console_sem(); |
1094 | - return i; | |
1122 | + break;; | |
1095 | 1123 | default: |
1096 | 1124 | if (fb->fb_ioctl == NULL) |
1097 | - return -EINVAL; | |
1098 | - return fb->fb_ioctl(info, cmd, arg); | |
1125 | + ret = -ENOTTY; | |
1126 | + else | |
1127 | + ret = fb->fb_ioctl(info, cmd, arg); | |
1099 | 1128 | } |
1129 | + unlock_kernel(); | |
1130 | + return ret; | |
1100 | 1131 | } |
1101 | 1132 | |
1102 | 1133 | #ifdef CONFIG_COMPAT |
... | ... | @@ -1150,7 +1181,7 @@ |
1150 | 1181 | put_user(compat_ptr(data), &cmap->transp)) |
1151 | 1182 | return -EFAULT; |
1152 | 1183 | |
1153 | - err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); | |
1184 | + err = fb_ioctl(file, cmd, (unsigned long) cmap); | |
1154 | 1185 | |
1155 | 1186 | if (!err) { |
1156 | 1187 | if (copy_in_user(&cmap32->start, |
... | ... | @@ -1204,7 +1235,7 @@ |
1204 | 1235 | |
1205 | 1236 | old_fs = get_fs(); |
1206 | 1237 | set_fs(KERNEL_DS); |
1207 | - err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); | |
1238 | + err = fb_ioctl(file, cmd, (unsigned long) &fix); | |
1208 | 1239 | set_fs(old_fs); |
1209 | 1240 | |
1210 | 1241 | if (!err) |
... | ... | @@ -1231,7 +1262,7 @@ |
1231 | 1262 | case FBIOPUT_CON2FBMAP: |
1232 | 1263 | arg = (unsigned long) compat_ptr(arg); |
1233 | 1264 | case FBIOBLANK: |
1234 | - ret = fb_ioctl(inode, file, cmd, arg); | |
1265 | + ret = fb_ioctl(file, cmd, arg); | |
1235 | 1266 | break; |
1236 | 1267 | |
1237 | 1268 | case FBIOGET_FSCREENINFO: |
... | ... | @@ -1358,7 +1389,7 @@ |
1358 | 1389 | .owner = THIS_MODULE, |
1359 | 1390 | .read = fb_read, |
1360 | 1391 | .write = fb_write, |
1361 | - .ioctl = fb_ioctl, | |
1392 | + .unlocked_ioctl = fb_ioctl, | |
1362 | 1393 | #ifdef CONFIG_COMPAT |
1363 | 1394 | .compat_ioctl = fb_compat_ioctl, |
1364 | 1395 | #endif |