diff options
author | Ming Lei <ming.lei@canonical.com> | 2015-08-16 22:31:50 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-09-23 13:01:16 -0400 |
commit | ab1cb278bc7027663adbfb0b81404f8398437e11 (patch) | |
tree | 9406e09aeb44e5caa2ee816a93124f966812f4f5 | |
parent | 2e5ab5f379f96a6207c45be40c357ebb1beb8ef3 (diff) |
block: loop: introduce ioctl command of LOOP_SET_DIRECT_IO
If loop block is mounted via 'mount -o loop', it isn't easy
to pass file descriptor opened as O_DIRECT, so this patch
introduces a new command to support direct IO for this case.
Cc: linux-api@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/loop.c | 19 | ||||
-rw-r--r-- | include/uapi/linux/loop.h | 1 |
2 files changed, 20 insertions, 0 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 06cad7edc0d3..75db3b98ec2b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -1228,6 +1228,20 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev) | |||
1228 | return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); | 1228 | return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); |
1229 | } | 1229 | } |
1230 | 1230 | ||
1231 | static int loop_set_dio(struct loop_device *lo, unsigned long arg) | ||
1232 | { | ||
1233 | int error = -ENXIO; | ||
1234 | if (lo->lo_state != Lo_bound) | ||
1235 | goto out; | ||
1236 | |||
1237 | __loop_update_dio(lo, !!arg); | ||
1238 | if (lo->use_dio == !!arg) | ||
1239 | return 0; | ||
1240 | error = -EINVAL; | ||
1241 | out: | ||
1242 | return error; | ||
1243 | } | ||
1244 | |||
1231 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, | 1245 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, |
1232 | unsigned int cmd, unsigned long arg) | 1246 | unsigned int cmd, unsigned long arg) |
1233 | { | 1247 | { |
@@ -1271,6 +1285,11 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1271 | if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) | 1285 | if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) |
1272 | err = loop_set_capacity(lo, bdev); | 1286 | err = loop_set_capacity(lo, bdev); |
1273 | break; | 1287 | break; |
1288 | case LOOP_SET_DIRECT_IO: | ||
1289 | err = -EPERM; | ||
1290 | if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) | ||
1291 | err = loop_set_dio(lo, arg); | ||
1292 | break; | ||
1274 | default: | 1293 | default: |
1275 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; | 1294 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; |
1276 | } | 1295 | } |
diff --git a/include/uapi/linux/loop.h b/include/uapi/linux/loop.h index 949851ce681f..c8125ec1f4f2 100644 --- a/include/uapi/linux/loop.h +++ b/include/uapi/linux/loop.h | |||
@@ -87,6 +87,7 @@ struct loop_info64 { | |||
87 | #define LOOP_GET_STATUS64 0x4C05 | 87 | #define LOOP_GET_STATUS64 0x4C05 |
88 | #define LOOP_CHANGE_FD 0x4C06 | 88 | #define LOOP_CHANGE_FD 0x4C06 |
89 | #define LOOP_SET_CAPACITY 0x4C07 | 89 | #define LOOP_SET_CAPACITY 0x4C07 |
90 | #define LOOP_SET_DIRECT_IO 0x4C08 | ||
90 | 91 | ||
91 | /* /dev/loop-control interface */ | 92 | /* /dev/loop-control interface */ |
92 | #define LOOP_CTL_ADD 0x4C80 | 93 | #define LOOP_CTL_ADD 0x4C80 |