Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.4
btrfsprogs.24931
0006-btrfs-progs-add-enqueue-parameter-for-excl...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0006-btrfs-progs-add-enqueue-parameter-for-exclusive-ops.patch of Package btrfsprogs.24931
From e198c6674a440ec699e068c338e66b2632962197 Mon Sep 17 00:00:00 2001 From: David Sterba <dsterba@suse.com> Date: Thu, 5 Nov 2020 03:38:00 +0100 Subject: [PATCH] btrfs-progs: add enqueue parameter for exclusive ops The exclusive ops will not start if there's one already running. Now that we have the sysfs export (since kernel 5.10) to check if there's one already running, use it to allow enqueueing of the operations as a convenience. Supported enqueuing: btrfs balance start --enqueue btrfs filesystem resize --enqueue btrfs device add --enqueue btrfs device delete --enqueue btrfs replace start --enqueue This patch implements the functionality based on Goldwyn's patch https://lore.kernel.org/linux-btrfs/?q=20200825150338.32610-4-rgoldwyn%40suse.de but on top of previous preparatory patches. Note that 'filesystem resize' options could confuse getopt as the negative size change looks like a series of short options and there's no way to make getopt ignore the short options, so there's a custom option parser. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.de> Signed-off-by: David Sterba <dsterba@suse.com> --- Documentation/btrfs-balance.asciidoc | 2 + Documentation/btrfs-device.asciidoc | 9 ++++- Documentation/btrfs-filesystem.asciidoc | 7 +++- Documentation/btrfs-replace.asciidoc | 4 +- cmds-balance.c | 30 ++++++++++------- cmds-device.c | 56 ++++++++++++++++++++++++-------- cmds-filesystem.c | 35 +++++++++++++++----- cmds-replace.c | 30 ++++++++++++----- utils.c | 5 +- utils.h | 2 - 10 files changed, 134 insertions(+), 46 deletions(-) --- a/Documentation/btrfs-balance.asciidoc +++ b/Documentation/btrfs-balance.asciidoc @@ -105,6 +105,8 @@ --background|--bg:::: run the balance operation asynchronously in the background, uses `fork`(2) to start the process that calls the kernel ioctl +--enqueue:::: +wait if there's another exclusive operation running, otherwise continue *status* [-v] <path>:: Show status of running or paused balance. --- a/Documentation/btrfs-device.asciidoc +++ b/Documentation/btrfs-device.asciidoc @@ -61,8 +61,10 @@ do not perform discard (TRIM) by default -f|--force:::: force overwrite of existing filesystem on the given disk(s) +--enqueue:::: +wait if there's another exclusive operation running, otherwise continue -*remove* <device>|<devid> [<device>|<devid>...] <path>:: +*remove* [options] <device>|<devid> [<device>|<devid>...] <path>:: Remove device(s) from a filesystem identified by <path> + Device removal must satisfy the profile constraints, otherwise the command @@ -85,6 +87,11 @@ otherwise mount fails. If there are two or more devices missing (e.g. possible in RAID6), you need specify 'missing' as many times as the number of missing devices to remove all of them. ++ +`Options` ++ +--enqueue:::: +wait if there's another exclusive operation running, otherwise continue *delete* <device>|<devid> [<device>|<devid>...] <path>:: Alias of remove kept for backward compatibility --- a/Documentation/btrfs-filesystem.asciidoc +++ b/Documentation/btrfs-filesystem.asciidoc @@ -182,7 +182,7 @@ a newline. The trailing newline is stripped automatically. // Some wording are extracted by the resize2fs man page -*resize* [<devid>:][+/-]<size>[kKmMgGtTpPeE]|[<devid>:]max <path>:: +*resize* [options] [<devid>:][+/-]<size>[kKmMgGtTpPeE]|[<devid>:]max <path>:: Resize a mounted filesystem identified by 'path'. A particular device can be resized by specifying a 'devid'. + @@ -216,6 +216,11 @@ end. Relocation of the data takes time. + See also section 'EXAMPLES'. ++ +`Options` ++ +--enqueue:::: +wait if there's another exclusive operation running, otherwise continue *show* [options] [<path>|<uuid>|<device>|<label>]:: Show the btrfs filesystem with some additional info about devices and space --- a/Documentation/btrfs-replace.asciidoc +++ b/Documentation/btrfs-replace.asciidoc @@ -18,7 +18,7 @@ *cancel* <mount_point>:: Cancel a running device replace operation. -*start* [-Bfr] <srcdev>|<devid> <targetdev> <path>:: +*start* [options] <srcdev>|<devid> <targetdev> <path>:: Replace device of a btrfs filesystem. + On a live filesystem, duplicate the data to the target device which @@ -53,6 +53,8 @@ + -B:::: no background replace. +--enqueue:::: +wait if there's another exclusive operation running, otherwise continue *status* [-1] <mount_point>:: Print status and progress information of a running device replace operation. --- a/cmds-balance.c +++ b/cmds-balance.c @@ -427,12 +427,11 @@ }; static int do_balance(const char *path, struct btrfs_ioctl_balance_args *args, - unsigned flags) + unsigned flags, bool enqueue) { int fd; int ret; DIR *dirstream = NULL; - int exclop; fd = btrfs_open_dir(path, &dirstream, 1); if (fd < 0) @@ -456,11 +455,10 @@ printf("\nStarting balance without any filters.\n"); } - exclop = get_fs_exclop(fd); - if (exclop > 0 ) { - error( - "unable to start balance, another exclusive operation '%s' in progress", - get_fs_exclop_name(exclop)); + ret = check_running_fs_exclop(fd, BTRFS_EXCLOP_BALANCE, enqueue); + if (ret != 0) { + if (ret < 0) + error("unable to check status of exclusive operation: %m"); close_file_or_dir(fd, dirstream); return 1; } @@ -522,6 +520,8 @@ "--full-balance do not print warning and do not delay start", "--background|--bg", " run the balance as a background process", + "--enqueue wait if there's another exclusive operation running,", + " otherwise continue", NULL }; @@ -533,6 +533,7 @@ int force = 0; int verbose = 0; int background = 0; + bool enqueue = false; unsigned start_flags = 0; int i; @@ -541,7 +542,8 @@ optind = 0; while (1) { enum { GETOPT_VAL_FULL_BALANCE = 256, - GETOPT_VAL_BACKGROUND = 257 }; + GETOPT_VAL_BACKGROUND = 257, + GETOPT_VAL_ENQUEUE }; static const struct option longopts[] = { { "data", optional_argument, NULL, 'd'}, { "metadata", optional_argument, NULL, 'm' }, @@ -553,6 +555,7 @@ { "background", no_argument, NULL, GETOPT_VAL_BACKGROUND }, { "bg", no_argument, NULL, GETOPT_VAL_BACKGROUND }, + { "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE}, { NULL, 0, NULL, 0 } }; @@ -594,6 +597,9 @@ case GETOPT_VAL_BACKGROUND: background = 1; break; + case GETOPT_VAL_ENQUEUE: + enqueue = true; + break; default: usage(cmd_balance_start_usage); } @@ -681,7 +687,7 @@ } } - return do_balance(argv[optind], &args, start_flags); + return do_balance(argv[optind], &args, start_flags, enqueue); } static const char * const cmd_balance_pause_usage[] = { @@ -918,7 +924,8 @@ memset(&args, 0, sizeof(args)); args.flags |= BTRFS_BALANCE_TYPE_MASK; - return do_balance(argv[1], &args, BALANCE_START_NOWARN); + /* No enqueueing supported for the obsolete syntax */ + return do_balance(argv[1], &args, BALANCE_START_NOWARN, false); } static const char balance_cmd_group_info[] = @@ -945,7 +952,8 @@ memset(&args, 0, sizeof(args)); args.flags |= BTRFS_BALANCE_TYPE_MASK; - return do_balance(argv[1], &args, 0); + /* No enqueueing supported for the obsolete syntax */ + return do_balance(argv[1], &args, 0, false); } return handle_command_group(&balance_cmd_group, argc, argv); --- a/cmds-device.c +++ b/cmds-device.c @@ -45,6 +45,8 @@ "Add a device to a filesystem", "-K|--nodiscard do not perform whole device TRIM", "-f|--force force overwrite existing filesystem on the disk", + "--enqueue wait if there's another exclusive operation running,", + " otherwise continue", NULL }; @@ -56,14 +58,16 @@ int discard = 1; int force = 0; int last_dev; - int exclop; + bool enqueue = false; optind = 0; while (1) { int c; + enum { GETOPT_VAL_ENQUEUE = 256 }; static const struct option long_options[] = { { "nodiscard", optional_argument, NULL, 'K'}, { "force", no_argument, NULL, 'f'}, + { "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE}, { NULL, 0, NULL, 0} }; @@ -77,6 +81,9 @@ case 'f': force = 1; break; + case GETOPT_VAL_ENQUEUE: + enqueue = true; + break; default: usage(cmd_device_add_usage); } @@ -92,11 +99,10 @@ if (fdmnt < 0) return 1; - exclop = get_fs_exclop(fdmnt); - if (exclop > 0) { - error( - "unable to start device add, another exclusive operation '%s' in progress", - get_fs_exclop_name(exclop)); + ret = check_running_fs_exclop(fdmnt, BTRFS_EXCLOP_DEV_ADD, enqueue); + if (ret != 0) { + if (ret < 0) + error("unable to check status of exclusive operation: %m"); close_file_or_dir(fdmnt, dirstream); return 1; } @@ -158,9 +164,28 @@ char *mntpnt; int i, fdmnt, ret = 0; DIR *dirstream = NULL; - int exclop; + bool enqueue = false; - clean_args_no_options(argc, argv, usagestr); + optind = 0; + while (1) { + int c; + enum { GETOPT_VAL_ENQUEUE = 256 }; + static const struct option long_options[] = { + { "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE}, + { NULL, 0, NULL, 0} + }; + + c = getopt_long(argc, argv, "", long_options, NULL); + if (c < 0) + break; + switch (c) { + case GETOPT_VAL_ENQUEUE: + enqueue = true; + break; + default: + usage(usagestr); + } + } if (check_argc_min(argc - optind, 2)) usage(usagestr); @@ -171,11 +196,10 @@ if (fdmnt < 0) return 1; - exclop = get_fs_exclop(fdmnt); - if (exclop > 0 ) { - error( - "unable to start device remove, another exclusive operation '%s' in progress", - get_fs_exclop_name(exclop)); + ret = check_running_fs_exclop(fdmnt, BTRFS_EXCLOP_DEV_REMOVE, enqueue); + if (ret != 0) { + if (ret < 0) + error("unable to check status of exclusive operation: %m"); close_file_or_dir(fdmnt, dirstream); return 1; } @@ -253,6 +277,9 @@ "Remove a device from a filesystem", "", COMMON_USAGE_REMOVE_DELETE, + "", + "--enqueue wait if there's another exclusive operation running,", + " otherwise continue", NULL }; @@ -266,6 +293,9 @@ "Remove a device from a filesystem (alias of \"btrfs device remove\")", "", COMMON_USAGE_REMOVE_DELETE, + "", + "--enqueue wait if there's another exclusive operation running,", + " otherwise continue", NULL }; --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -1075,11 +1075,14 @@ } static const char * const cmd_filesystem_resize_usage[] = { - "btrfs filesystem resize [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>", + "btrfs filesystem resize [options] [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>", "Resize a filesystem", "If 'max' is passed, the filesystem will occupy all available space", "on the device 'devid'.", "[kK] means KiB, which denotes 1KiB = 1024B, 1MiB = 1024KiB, etc.", + "", + "--enqueue wait if there's another exclusive operation running,", + " otherwise continue", NULL }; @@ -1089,10 +1092,27 @@ int fd, res, len, e; char *amount, *path; DIR *dirstream = NULL; + int ret; struct stat st; - int exclop; + bool enqueue = false; - clean_args_no_options_relaxed(argc, argv); + /* + * Simplified option parser, accept only long options, the resize value + * could be negative and is recognized as short options by getopt + */ + for (optind = 1; optind < argc; optind++) { + if (strcmp(argv[optind], "--enqueue") == 0) { + enqueue = true; + } else if (strcmp(argv[optind], "--") == 0) { + /* Separator: options -- non-options */ + } else if (strncmp(argv[optind], "--", 2) == 0) { + /* Emulate what getopt does on unkonwn option */ + optind++; + usage(cmd_filesystem_resize_usage); + } else { + break; + } + } if (check_argc_exact(argc - optind, 2)) usage(cmd_filesystem_resize_usage); @@ -1122,11 +1142,10 @@ if (fd < 0) return 1; - exclop = get_fs_exclop(fd); - if (exclop > 0) { - error( -"unable to start filesystem resize, nother exclusive operation '%s' in progress", - get_fs_exclop_name(exclop)); + ret = check_running_fs_exclop(fd, BTRFS_EXCLOP_RESIZE, enqueue); + if (ret != 0) { + if (ret < 0) + error("unable to check status of exclusive operation: %m"); close_file_or_dir(fd, dirstream); return 1; } --- a/cmds-replace.c +++ b/cmds-replace.c @@ -28,6 +28,7 @@ #include <assert.h> #include <inttypes.h> #include <sys/wait.h> +#include <getopt.h> #include "kerncompat.h" #include "ctree.h" @@ -111,6 +112,8 @@ " correct checksum. Devices which are currently mounted are", " never allowed to be used as the <targetdev>", "-B do not background", + "--enqueue wait if there's another exclusive operation running,", + " otherwise continue", NULL }; @@ -120,7 +123,6 @@ struct btrfs_ioctl_dev_replace_args status_args = {0}; int ret; int i; - int c; int fdmnt = -1; int fddstdev = -1; char *path; @@ -133,10 +135,20 @@ DIR *dirstream = NULL; u64 srcdev_size; u64 dstdev_size; - int exclop; + bool enqueue = false; optind = 0; - while ((c = getopt(argc, argv, "Brf")) != -1) { + while (1) { + int c; + enum { GETOPT_VAL_ENQUEUE = 256 }; + static const struct option long_options[] = { + { "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE}, + { NULL, 0, NULL, 0} + }; + + c = getopt_long(argc, argv, "Brf", long_options, NULL); + if (c < 0) + break; switch (c) { case 'B': do_not_background = 1; @@ -147,6 +159,9 @@ case 'f': force_using_targetdev = 1; break; + case GETOPT_VAL_ENQUEUE: + enqueue = true; + break; case '?': default: usage(cmd_replace_start_usage); @@ -258,11 +273,10 @@ } /* Check status before any potentially destructive operation */ - exclop = get_fs_exclop(fdmnt); - if (exclop > 0) { - error( - "unable to start device replace, another exclusive operation '%s' in progress", - get_fs_exclop_name(exclop)); + ret = check_running_fs_exclop(fdmnt, BTRFS_EXCLOP_DEV_REPLACE, enqueue); + if (ret != 0) { + if (ret < 0) + error("unable to check status of exclusive operation: %m"); close_file_or_dir(fdmnt, dirstream); goto leave_with_error; } --- a/utils.c +++ b/utils.c @@ -2693,7 +2693,7 @@ * 1 - another operation running * <0 - there was another error */ -int check_running_fs_exclop(int fd, const char *desc, bool enqueue) +int check_running_fs_exclop(int fd, enum exclusive_operation start, bool enqueue) { int sysfs_fd; int exclop; @@ -2715,7 +2715,8 @@ if (!enqueue) { error( "unable to start %s, another exclusive operation '%s' in progress", - desc, get_fs_exclop_name(exclop)); + get_fs_exclop_name(start), + get_fs_exclop_name(exclop)); ret = 1; goto out; } --- a/utils.h +++ b/utils.h @@ -124,7 +124,7 @@ int get_fsid(const char *path, u8 *fsid, int silent); int get_fsid_fd(int fd, u8 *fsid); int get_fs_exclop(int fd); -int check_running_fs_exclop(int fd, const char *desc, bool enqueue); +int check_running_fs_exclop(int fd, enum exclusive_operation start, bool enqueue); const char *get_fs_exclop_name(int op); int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]); --- a/Documentation/btrfs-balance.8 +++ b/Documentation/btrfs-balance.8 @@ -2,12 +2,12 @@ .\" Title: btrfs-balance .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 12/05/2018 +.\" Date: 12/10/2020 .\" Manual: Btrfs Manual .\" Source: Btrfs v4.19.1 .\" Language: English .\" -.TH "BTRFS\-BALANCE" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual" +.TH "BTRFS\-BALANCE" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -240,6 +240,11 @@ to run the balance operation asynchronously in the background, uses \fBfork\fR(2) to start the process that calls the kernel ioctl .RE +.PP +\-\-enqueue +.RS 4 +wait if there\(cqs another exclusive operation running, otherwise continue +.RE .RE .PP \fBstatus\fR [\-v] \fI<path>\fR --- a/Documentation/btrfs-device.8 +++ b/Documentation/btrfs-device.8 @@ -2,12 +2,12 @@ .\" Title: btrfs-device .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 12/05/2018 +.\" Date: 12/10/2020 .\" Manual: Btrfs Manual .\" Source: Btrfs v4.19.1 .\" Language: English .\" -.TH "BTRFS\-DEVICE" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual" +.TH "BTRFS\-DEVICE" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -78,9 +78,14 @@ do not perform discard (TRIM) by default .RS 4 force overwrite of existing filesystem on the given disk(s) .RE +.PP +\-\-enqueue +.RS 4 +wait if there\(cqs another exclusive operation running, otherwise continue +.RE .RE .PP -\fBremove\fR \fI<device>\fR|\fI<devid>\fR [\fI<device>\fR|\fI<devid>\fR\&...] \fI<path>\fR +\fBremove\fR [options] \fI<device>\fR|\fI<devid>\fR [\fI<device>\fR|\fI<devid>\fR\&...] \fI<path>\fR .RS 4 Remove device(s) from a filesystem identified by \fI<path>\fR @@ -114,6 +119,12 @@ In most cases, there is only one missing as many times as the number of missing devices to remove all of them\&. .sp .5v .RE +\fBOptions\fR +.PP +\-\-enqueue +.RS 4 +wait if there\(cqs another exclusive operation running, otherwise continue +.RE .RE .PP \fBdelete\fR \fI<device>\fR|\fI<devid>\fR [\fI<device>\fR|\fI<devid>\fR\&...] \fI<path>\fR --- a/Documentation/btrfs-filesystem.8 +++ b/Documentation/btrfs-filesystem.8 @@ -2,12 +2,12 @@ .\" Title: btrfs-filesystem .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 12/05/2018 +.\" Date: 12/10/2020 .\" Manual: Btrfs Manual .\" Source: Btrfs v4.19.1 .\" Language: English .\" -.TH "BTRFS\-FILESYSTEM" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual" +.TH "BTRFS\-FILESYSTEM" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -401,7 +401,7 @@ the maximum allowable length shall be le .RE .RE .PP -\fBresize\fR [\fI<devid>\fR:][+/\-]\fI<size>\fR[kKmMgGtTpPeE]|[\fI<devid>\fR:]max \fI<path>\fR +\fBresize\fR [options] [\fI<devid>\fR:][+/\-]\fI<size>\fR[kKmMgGtTpPeE]|[\fI<devid>\fR:]max \fI<path>\fR .RS 4 Resize a mounted filesystem identified by \fIpath\fR\&. A particular device can be resized by specifying a @@ -451,6 +451,13 @@ Growing is usually instant as it only up .sp See also section \fIEXAMPLES\fR\&. +.sp +\fBOptions\fR +.PP +\-\-enqueue +.RS 4 +wait if there\(cqs another exclusive operation running, otherwise continue +.RE .RE .PP \fBshow\fR [options] [\fI<path>\fR|\fI<uuid>\fR|\fI<device>\fR|\fI<label>\fR] --- a/Documentation/btrfs-replace.8 +++ b/Documentation/btrfs-replace.8 @@ -2,12 +2,12 @@ .\" Title: btrfs-replace .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 12/05/2018 +.\" Date: 12/10/2020 .\" Manual: Btrfs Manual .\" Source: Btrfs v4.19.1 .\" Language: English .\" -.TH "BTRFS\-REPLACE" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual" +.TH "BTRFS\-REPLACE" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -42,7 +42,7 @@ btrfs-replace \- replace devices managed Cancel a running device replace operation\&. .RE .PP -\fBstart\fR [\-Bfr] \fI<srcdev>\fR|\fI<devid>\fR \fI<targetdev>\fR \fI<path>\fR +\fBstart\fR [options] \fI<srcdev>\fR|\fI<devid>\fR \fI<targetdev>\fR \fI<path>\fR .RS 4 Replace device of a btrfs filesystem\&. .sp @@ -92,6 +92,11 @@ A valid filesystem is assumed if a btrfs .RS 4 no background replace\&. .RE +.PP +\-\-enqueue +.RS 4 +wait if there\(cqs another exclusive operation running, otherwise continue +.RE .RE .PP \fBstatus\fR [\-1] \fI<mount_point>\fR --- a/Documentation/btrfs.5 +++ b/Documentation/btrfs.5 @@ -2,12 +2,12 @@ .\" Title: btrfs-man5 .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 12/05/2018 +.\" Date: 12/10/2020 .\" Manual: Btrfs Manual .\" Source: Btrfs v4.19.1 .\" Language: English .\" -.TH "BTRFS\-MAN5" "5" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual" +.TH "BTRFS\-MAN5" "5" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" -----------------------------------------------------------------
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor