Commit e53677113e32e6f118e31b8391a2eab7ee52c0a7

Authored by Alan Cox
Committed by Linus Torvalds
1 parent 978ccaa8ea

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