losetup: support ioctl cmd of LOOP_SET_DIRECT_IO
From v4.4, linux kernel starts to support direct I/O and AIO to backing file for loop driver, so allow losetup to enable the feature by using LOOP_SET_DIRECT_IO ioctl cmd. Signed-off-by: Ming Lei <tom.leiming@gmail.com>
This commit is contained in:
parent
710dd49239
commit
64c3bb3cb7
3 changed files with 45 additions and 2 deletions
|
@ -23,6 +23,7 @@
|
||||||
#define LOOP_GET_STATUS64 0x4C05
|
#define LOOP_GET_STATUS64 0x4C05
|
||||||
/* #define LOOP_CHANGE_FD 0x4C06 */
|
/* #define LOOP_CHANGE_FD 0x4C06 */
|
||||||
#define LOOP_SET_CAPACITY 0x4C07
|
#define LOOP_SET_CAPACITY 0x4C07
|
||||||
|
#define LOOP_SET_DIRECT_IO 0x4C08
|
||||||
|
|
||||||
/* /dev/loop-control interface */
|
/* /dev/loop-control interface */
|
||||||
#ifndef LOOP_CTL_ADD
|
#ifndef LOOP_CTL_ADD
|
||||||
|
@ -164,6 +165,7 @@ extern int loopcxt_next(struct loopdev_cxt *lc);
|
||||||
extern int loopcxt_setup_device(struct loopdev_cxt *lc);
|
extern int loopcxt_setup_device(struct loopdev_cxt *lc);
|
||||||
extern int loopcxt_delete_device(struct loopdev_cxt *lc);
|
extern int loopcxt_delete_device(struct loopdev_cxt *lc);
|
||||||
extern int loopcxt_set_capacity(struct loopdev_cxt *lc);
|
extern int loopcxt_set_capacity(struct loopdev_cxt *lc);
|
||||||
|
extern int loopcxt_set_dio(struct loopdev_cxt *lc, unsigned long use_dio);
|
||||||
|
|
||||||
int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset);
|
int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset);
|
||||||
int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit);
|
int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit);
|
||||||
|
|
|
@ -1315,6 +1315,24 @@ int loopcxt_set_capacity(struct loopdev_cxt *lc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int loopcxt_set_dio(struct loopdev_cxt *lc, unsigned long use_dio)
|
||||||
|
{
|
||||||
|
int fd = loopcxt_get_fd(lc);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Kernels prior to v4.4 don't support this ioctl */
|
||||||
|
if (ioctl(fd, LOOP_SET_DIRECT_IO, use_dio) < 0) {
|
||||||
|
int rc = -errno;
|
||||||
|
DBG(CXT, ul_debugobj(lc, "LOOP_SET_DIRECT_IO failed: %m"));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG(CXT, ul_debugobj(lc, "direct io set"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int loopcxt_delete_device(struct loopdev_cxt *lc)
|
int loopcxt_delete_device(struct loopdev_cxt *lc)
|
||||||
{
|
{
|
||||||
int fd = loopcxt_get_fd(lc);
|
int fd = loopcxt_get_fd(lc);
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum {
|
||||||
A_SHOW_ONE, /* print info about one device */
|
A_SHOW_ONE, /* print info about one device */
|
||||||
A_FIND_FREE, /* find first unused */
|
A_FIND_FREE, /* find first unused */
|
||||||
A_SET_CAPACITY, /* set device capacity */
|
A_SET_CAPACITY, /* set device capacity */
|
||||||
|
A_SET_DIRECT_IO, /* set accessing backing file by direct io */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -393,6 +394,7 @@ static void usage(FILE *out)
|
||||||
fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out);
|
fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out);
|
||||||
fputs(_(" -P, --partscan create a partitioned loop device\n"), out);
|
fputs(_(" -P, --partscan create a partitioned loop device\n"), out);
|
||||||
fputs(_(" -r, --read-only set up a read-only loop device\n"), out);
|
fputs(_(" -r, --read-only set up a read-only loop device\n"), out);
|
||||||
|
fputs(_(" --direct-io open backing file with O_DIRECT\n"), out);
|
||||||
fputs(_(" --show print device name after setup (with -f)\n"), out);
|
fputs(_(" --show print device name after setup (with -f)\n"), out);
|
||||||
fputs(_(" -v, --verbose verbose mode\n"), out);
|
fputs(_(" -v, --verbose verbose mode\n"), out);
|
||||||
|
|
||||||
|
@ -446,11 +448,13 @@ int main(int argc, char **argv)
|
||||||
int res = 0, showdev = 0, lo_flags = 0;
|
int res = 0, showdev = 0, lo_flags = 0;
|
||||||
char *outarg = NULL;
|
char *outarg = NULL;
|
||||||
int list = 0;
|
int list = 0;
|
||||||
|
unsigned long use_dio = 0, set_dio = 0;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPT_SIZELIMIT = CHAR_MAX + 1,
|
OPT_SIZELIMIT = CHAR_MAX + 1,
|
||||||
OPT_SHOW,
|
OPT_SHOW,
|
||||||
OPT_RAW
|
OPT_RAW,
|
||||||
|
OPT_DIO
|
||||||
};
|
};
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{ "all", 0, 0, 'a' },
|
{ "all", 0, 0, 'a' },
|
||||||
|
@ -468,6 +472,7 @@ int main(int argc, char **argv)
|
||||||
{ "sizelimit", 1, 0, OPT_SIZELIMIT },
|
{ "sizelimit", 1, 0, OPT_SIZELIMIT },
|
||||||
{ "partscan", 0, 0, 'P' },
|
{ "partscan", 0, 0, 'P' },
|
||||||
{ "read-only", 0, 0, 'r' },
|
{ "read-only", 0, 0, 'r' },
|
||||||
|
{ "direct-io", 1, 0, OPT_DIO },
|
||||||
{ "raw", 0, 0, OPT_RAW },
|
{ "raw", 0, 0, OPT_RAW },
|
||||||
{ "show", 0, 0, OPT_SHOW },
|
{ "show", 0, 0, OPT_SHOW },
|
||||||
{ "verbose", 0, 0, 'v' },
|
{ "verbose", 0, 0, 'v' },
|
||||||
|
@ -557,6 +562,10 @@ int main(int argc, char **argv)
|
||||||
case OPT_SHOW:
|
case OPT_SHOW:
|
||||||
showdev = 1;
|
showdev = 1;
|
||||||
break;
|
break;
|
||||||
|
case OPT_DIO:
|
||||||
|
set_dio = 1;
|
||||||
|
use_dio = strtoul_or_err(optarg, _("failed to parse dio"));
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
|
@ -609,8 +618,13 @@ int main(int argc, char **argv)
|
||||||
if (!act && optind + 1 == argc) {
|
if (!act && optind + 1 == argc) {
|
||||||
/*
|
/*
|
||||||
* losetup [--list] <device>
|
* losetup [--list] <device>
|
||||||
|
* OR
|
||||||
|
* losetup --direct-io DIO <device>
|
||||||
*/
|
*/
|
||||||
|
if (!set_dio)
|
||||||
act = A_SHOW_ONE;
|
act = A_SHOW_ONE;
|
||||||
|
else
|
||||||
|
act = A_SET_DIRECT_IO;
|
||||||
if (!is_loopdev(argv[optind]) ||
|
if (!is_loopdev(argv[optind]) ||
|
||||||
loopcxt_set_device(&lc, argv[optind]))
|
loopcxt_set_device(&lc, argv[optind]))
|
||||||
err(EXIT_FAILURE, _("%s: failed to use device"),
|
err(EXIT_FAILURE, _("%s: failed to use device"),
|
||||||
|
@ -695,6 +709,8 @@ int main(int argc, char **argv)
|
||||||
if (showdev)
|
if (showdev)
|
||||||
printf("%s\n", loopcxt_get_device(&lc));
|
printf("%s\n", loopcxt_get_device(&lc));
|
||||||
warn_size(file, sizelimit);
|
warn_size(file, sizelimit);
|
||||||
|
if (set_dio)
|
||||||
|
goto lo_set_dio;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -747,6 +763,13 @@ int main(int argc, char **argv)
|
||||||
warn(_("%s: set capacity failed"),
|
warn(_("%s: set capacity failed"),
|
||||||
loopcxt_get_device(&lc));
|
loopcxt_get_device(&lc));
|
||||||
break;
|
break;
|
||||||
|
case A_SET_DIRECT_IO:
|
||||||
|
lo_set_dio:
|
||||||
|
res = loopcxt_set_dio(&lc, use_dio);
|
||||||
|
if (res)
|
||||||
|
warn(_("%s: set direct io failed"),
|
||||||
|
loopcxt_get_device(&lc));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(stderr);
|
usage(stderr);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue