Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alan Cox and committed by
Linus Torvalds
e5367711 978ccaa8

+86 -55
+86 -55
drivers/video/fbmem.c
··· 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 ··· 1181 1150 put_user(compat_ptr(data), &cmap->transp)) 1182 1151 return -EFAULT; 1183 1152 1184 - err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); 1153 + err = fb_ioctl(file, cmd, (unsigned long) cmap); 1185 1154 1186 1155 if (!err) { 1187 1156 if (copy_in_user(&cmap32->start, ··· 1235 1204 1236 1205 old_fs = get_fs(); 1237 1206 set_fs(KERNEL_DS); 1238 - err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); 1207 + err = fb_ioctl(file, cmd, (unsigned long) &fix); 1239 1208 set_fs(old_fs); 1240 1209 1241 1210 if (!err) ··· 1262 1231 case FBIOPUT_CON2FBMAP: 1263 1232 arg = (unsigned long) compat_ptr(arg); 1264 1233 case FBIOBLANK: 1265 - ret = fb_ioctl(inode, file, cmd, arg); 1234 + ret = fb_ioctl(file, cmd, arg); 1266 1235 break; 1267 1236 1268 1237 case FBIOGET_FSCREENINFO: ··· 1389 1358 .owner = THIS_MODULE, 1390 1359 .read = fb_read, 1391 1360 .write = fb_write, 1392 - .ioctl = fb_ioctl, 1361 + .unlocked_ioctl = fb_ioctl, 1393 1362 #ifdef CONFIG_COMPAT 1394 1363 .compat_ioctl = fb_compat_ioctl, 1395 1364 #endif