return 0;
}
+int loopcxt_remove_device(struct loopdev_cxt *lc)
+{
+ int rc = -EINVAL;
+ int ctl, nr = -1;
+ const char *p, *dev = loopcxt_get_device(lc);
+
+ if (!dev)
+ goto done;
+
+ if (!(lc->flags & LOOPDEV_FL_CONTROL)) {
+ rc = -ENOSYS;
+ goto done;
+ }
+
+ p = strrchr(dev, '/');
+ if (!p || (sscanf(p, "/loop%d", &nr) != 1 && sscanf(p, "/%d", &nr) != 1)
+ || nr < 0)
+ goto done;
+
+ ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC);
+ if (ctl >= 0) {
+ DBG(CXT, ul_debugobj(lc, "remove_device %d", nr));
+ rc = ioctl(ctl, LOOP_CTL_REMOVE, nr);
+ close(ctl);
+ }
+ lc->control_ok = rc >= 0 ? 1 : 0;
+done:
+ DBG(CXT, ul_debugobj(lc, "remove_device done [rc=%d]", rc));
+ return rc;
+}
+
int loopcxt_add_device(struct loopdev_cxt *lc)
{
int rc = -EINVAL;
*losetup* *-c* _loopdev_
+Remove a loop device:
+
+*losetup* *-R* _loopdev_ ...
+
== DESCRIPTION
*losetup* is used to associate loop devices with regular files or block devices, to detach loop devices, and to query the status of a loop device. If only the _loopdev_ argument is given, the status of the corresponding loop device is shown. If no option is given, all loop devices are shown.
*-J*, *--json*::
Use JSON format for *--list* output.
+*-R*, *--remove* _loopdev_...::
+The parameter is not recommended for direct use.
+*-d* or *-D* option to disconnect the file from the loop device, we can see a loop device
+of size 0 by running 'lsblk -a'. At this point, the loop device will still in the system.
+This parameter can truly remove the loop device, and there is no command or interface to view it.
+
include::man-common/help-version.adoc[]
== ENCRYPTION
A_SET_CAPACITY, /* set device capacity */
A_SET_DIRECT_IO, /* set accessing backing file by direct io */
A_SET_BLOCKSIZE, /* set logical block size of the loop device */
+ A_REMOVE, /* remove given device */
};
enum {
return res;
}
+static int remove_loop(struct loopdev_cxt *lc)
+{
+ if (loopcxt_remove_device(lc))
+ return -1;
+ return 0;
+}
+
static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln)
{
size_t i;
fputs(_(" -c, --set-capacity <loopdev> resize the device\n"), out);
fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out);
fputs(_(" -L, --nooverlap avoid possible conflict between devices\n"), out);
+ fputs(_(" -R, --remove <loopdev>... remove one or more devices\n"), out);
/* commands options */
fputs(USAGE_SEPARATOR, out);
{ "show", no_argument, NULL, OPT_SHOW },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
+ { "remove", required_argument, NULL, 'R' },
{ NULL, 0, NULL, 0 }
};
if (loopcxt_init(&lc, 0))
err(EXIT_FAILURE, _("failed to initialize loopcxt"));
- while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvV",
+ while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvVR:",
longopts, NULL)) != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
case 'V':
print_version(EXIT_SUCCESS);
+ case 'R':
+ act = A_REMOVE;
+ if (loopcxt_set_device(&lc, optarg))
+ err(EXIT_FAILURE, _("%s: failed to use device"),
+ optarg);
+ break;
+
default:
errtryhelp(EXIT_FAILURE);
}
warn(_("%s: set logical block size failed"),
loopcxt_get_device(&lc));
break;
+
+ case A_REMOVE:
+ res = remove_loop(&lc);
+ while (optind < argc) {
+ if (loopcxt_set_device(&lc, argv[optind]))
+ warn(_("%s: failed to use device"),
+ argv[optind]);
+ optind++;
+ res += remove_loop(&lc);
+ }
+ break;
+
default:
warnx(_("bad usage"));
errtryhelp(EXIT_FAILURE);