aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/loop.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-08-29 14:06:14 -0400
committerJens Axboe <axboe@nelson.home.kernel.dk>2006-09-30 14:52:27 -0400
commit863d5b822c02d0e7215fb84ca79e9f8c3e35f04e (patch)
tree86e2fd2507a78a1adc6a7126f26c38ebf2ee4d1d /drivers/block/loop.c
parentb71e8a4ce03b3098c7801ee5e6e08d1a39a226c2 (diff)
[PATCH] BLOCK: Move the loop device ioctl compat stuff to the loop driver [try #6]
Move the loop device ioctl compat stuff from fs/compat_ioctl.c to the loop driver so that the loop header file doesn't need to be included. Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r--drivers/block/loop.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 68b0471ad5a6..d6bb8da955a2 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -66,6 +66,7 @@
66#include <linux/swap.h> 66#include <linux/swap.h>
67#include <linux/slab.h> 67#include <linux/slab.h>
68#include <linux/loop.h> 68#include <linux/loop.h>
69#include <linux/compat.h>
69#include <linux/suspend.h> 70#include <linux/suspend.h>
70#include <linux/writeback.h> 71#include <linux/writeback.h>
71#include <linux/buffer_head.h> /* for invalidate_bdev() */ 72#include <linux/buffer_head.h> /* for invalidate_bdev() */
@@ -1165,6 +1166,162 @@ static int lo_ioctl(struct inode * inode, struct file * file,
1165 return err; 1166 return err;
1166} 1167}
1167 1168
1169#ifdef CONFIG_COMPAT
1170struct compat_loop_info {
1171 compat_int_t lo_number; /* ioctl r/o */
1172 compat_dev_t lo_device; /* ioctl r/o */
1173 compat_ulong_t lo_inode; /* ioctl r/o */
1174 compat_dev_t lo_rdevice; /* ioctl r/o */
1175 compat_int_t lo_offset;
1176 compat_int_t lo_encrypt_type;
1177 compat_int_t lo_encrypt_key_size; /* ioctl w/o */
1178 compat_int_t lo_flags; /* ioctl r/o */
1179 char lo_name[LO_NAME_SIZE];
1180 unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
1181 compat_ulong_t lo_init[2];
1182 char reserved[4];
1183};
1184
1185/*
1186 * Transfer 32-bit compatibility structure in userspace to 64-bit loop info
1187 * - noinlined to reduce stack space usage in main part of driver
1188 */
1189static noinline int
1190loop_info64_from_compat(const struct compat_loop_info *arg,
1191 struct loop_info64 *info64)
1192{
1193 struct compat_loop_info info;
1194
1195 if (copy_from_user(&info, arg, sizeof(info)))
1196 return -EFAULT;
1197
1198 memset(info64, 0, sizeof(*info64));
1199 info64->lo_number = info.lo_number;
1200 info64->lo_device = info.lo_device;
1201 info64->lo_inode = info.lo_inode;
1202 info64->lo_rdevice = info.lo_rdevice;
1203 info64->lo_offset = info.lo_offset;
1204 info64->lo_sizelimit = 0;
1205 info64->lo_encrypt_type = info.lo_encrypt_type;
1206 info64->lo_encrypt_key_size = info.lo_encrypt_key_size;
1207 info64->lo_flags = info.lo_flags;
1208 info64->lo_init[0] = info.lo_init[0];
1209 info64->lo_init[1] = info.lo_init[1];
1210 if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
1211 memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE);
1212 else
1213 memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
1214 memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE);
1215 return 0;
1216}
1217
1218/*
1219 * Transfer 64-bit loop info to 32-bit compatibility structure in userspace
1220 * - noinlined to reduce stack space usage in main part of driver
1221 */
1222static noinline int
1223loop_info64_to_compat(const struct loop_info64 *info64,
1224 struct compat_loop_info __user *arg)
1225{
1226 struct compat_loop_info info;
1227
1228 memset(&info, 0, sizeof(info));
1229 info.lo_number = info64->lo_number;
1230 info.lo_device = info64->lo_device;
1231 info.lo_inode = info64->lo_inode;
1232 info.lo_rdevice = info64->lo_rdevice;
1233 info.lo_offset = info64->lo_offset;
1234 info.lo_encrypt_type = info64->lo_encrypt_type;
1235 info.lo_encrypt_key_size = info64->lo_encrypt_key_size;
1236 info.lo_flags = info64->lo_flags;
1237 info.lo_init[0] = info64->lo_init[0];
1238 info.lo_init[1] = info64->lo_init[1];
1239 if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
1240 memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
1241 else
1242 memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
1243 memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
1244
1245 /* error in case values were truncated */
1246 if (info.lo_device != info64->lo_device ||
1247 info.lo_rdevice != info64->lo_rdevice ||
1248 info.lo_inode != info64->lo_inode ||
1249 info.lo_offset != info64->lo_offset ||
1250 info.lo_init[0] != info64->lo_init[0] ||
1251 info.lo_init[1] != info64->lo_init[1])
1252 return -EOVERFLOW;
1253
1254 if (copy_to_user(arg, &info, sizeof(info)))
1255 return -EFAULT;
1256 return 0;
1257}
1258
1259static int
1260loop_set_status_compat(struct loop_device *lo,
1261 const struct compat_loop_info __user *arg)
1262{
1263 struct loop_info64 info64;
1264 int ret;
1265
1266 ret = loop_info64_from_compat(arg, &info64);
1267 if (ret < 0)
1268 return ret;
1269 return loop_set_status(lo, &info64);
1270}
1271
1272static int
1273loop_get_status_compat(struct loop_device *lo,
1274 struct compat_loop_info __user *arg)
1275{
1276 struct loop_info64 info64;
1277 int err = 0;
1278
1279 if (!arg)
1280 err = -EINVAL;
1281 if (!err)
1282 err = loop_get_status(lo, &info64);
1283 if (!err)
1284 err = loop_info64_to_compat(&info64, arg);
1285 return err;
1286}
1287
1288static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1289{
1290 struct inode *inode = file->f_dentry->d_inode;
1291 struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
1292 int err;
1293
1294 lock_kernel();
1295 switch(cmd) {
1296 case LOOP_SET_STATUS:
1297 mutex_lock(&lo->lo_ctl_mutex);
1298 err = loop_set_status_compat(
1299 lo, (const struct compat_loop_info __user *) arg);
1300 mutex_unlock(&lo->lo_ctl_mutex);
1301 break;
1302 case LOOP_GET_STATUS:
1303 mutex_lock(&lo->lo_ctl_mutex);
1304 err = loop_get_status_compat(
1305 lo, (struct compat_loop_info __user *) arg);
1306 mutex_unlock(&lo->lo_ctl_mutex);
1307 break;
1308 case LOOP_CLR_FD:
1309 case LOOP_GET_STATUS64:
1310 case LOOP_SET_STATUS64:
1311 arg = (unsigned long) compat_ptr(arg);
1312 case LOOP_SET_FD:
1313 case LOOP_CHANGE_FD:
1314 err = lo_ioctl(inode, file, cmd, arg);
1315 break;
1316 default:
1317 err = -ENOIOCTLCMD;
1318 break;
1319 }
1320 unlock_kernel();
1321 return err;
1322}
1323#endif
1324
1168static int lo_open(struct inode *inode, struct file *file) 1325static int lo_open(struct inode *inode, struct file *file)
1169{ 1326{
1170 struct loop_device *lo = inode->i_bdev->bd_disk->private_data; 1327 struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
@@ -1192,6 +1349,9 @@ static struct block_device_operations lo_fops = {
1192 .open = lo_open, 1349 .open = lo_open,
1193 .release = lo_release, 1350 .release = lo_release,
1194 .ioctl = lo_ioctl, 1351 .ioctl = lo_ioctl,
1352#ifdef CONFIG_COMPAT
1353 .compat_ioctl = lo_compat_ioctl,
1354#endif
1195}; 1355};
1196 1356
1197/* 1357/*