Удалите запись /dev/loopX после отключения устройства обратной связи.

Вопрос или проблема

Я создал устройство с циклическим доступом, используя losetup /dev/loop90 /tmp/disk1, где /tmp/disk1 — это файл размером 512M, который я создал.

Затем устройство было отсоединено с помощью losetup -d /dev/loop90.

Оно было удалено из вывода losetup -a, но запись в /dev и /sys/devices/virtual/block по-прежнему присутствует. Поскольку эта запись существует, каждый раз, когда выполняется сканирование udev, также перечисляются все удаленные устройства.

Как можно полностью удалить эти устройства с циклическим доступом и удалить все записи без перезагрузки?

Насколько я могу судить, экспериментально, это поведение является нормальным.

Программа на C, подобная этой:

#include <fcntl.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE);   \
    } while (0)

int
main(int argc, char *argv[])
{
    int loopctlfd;
    long devnr;
    char loopname[4096];

    (void)argc;
    (void)argv;
    loopctlfd = open("/dev/loop-control", O_RDWR);
    if (loopctlfd == -1)
        errExit("open: /dev/loop-control");

    devnr = ioctl(loopctlfd, LOOP_CTL_GET_FREE);
    if (devnr == -1)
        errExit("ioctl-LOOP_CTL_GET_FREE");
    sprintf(loopname, "/dev/loop%ld", devnr);
    printf("%s\n", loopname);
    return 0;
}

по-прежнему будет выводить имя используемого устройства в случае необходимости, хотя оно не будет повторно использовать устройства, что может быть недостатком.

Если вы абсолютно хотите очистить без перезагрузки, вы можете сделать это с помощью этой другой программы на C:

#include <errno.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char** argv)
{
    char *end;
    if (argc < 2) {
        printf("Необходим номер устройства в качестве первого аргумента\n");
        return 0;
    }
    long int dev_to_remove = strtol(argv[1], &end, 10);
    if (*end != '\0' || dev_to_remove < 0 || errno != 0) {
        printf("Недопустимый номер устройства\n");
        return 1;
    }
    const int fd = open("/dev/loop-control", O_RDWR);
    if (ioctl(fd, LOOP_CTL_REMOVE, dev_to_remove) < 0)
    {
        perror("Удаление устройства не удалось");
        return 1;
    }
    return 0;
}

Ответ или решение

Чтобы удалить запись о loop-устройстве, которая всё ещё присутствует в /dev и /sys/devices/virtual/block, после его отсоединения, можно использовать специальный подход, основанный на работе с контроллером loop-устройств Linux.

Понимание проблемы

Когда вы создаёте loop-устройство с помощью команды losetup, эта операция создает виртуальный блок устройства, который будет доступен для использования как обычное блочное устройство. После отсоединения устройства с помощью losetup -d, информация о loop-устройстве может оставаться в системе.

Причиной тому является то, что данные в /dev/loopX и /sys/devices/virtual/block/loopX могут не быть сразу удалены, даже если устройство уже отмонтировано и отключено. Это может привести к тому, что при следующем сканировании udev такие устройства будут по-прежнему отображаться.

Окончательная очистка

Если вам нужно полностью удалить эти записи без перезагрузки системы, вы можете воспользоваться включенным в ядро Linux управляющим интерфейсом для loop-устройств. Для этого необходимо использовать ioctl с командой LOOP_CTL_REMOVE.

Пример C-кода для удаления loop-устройства

Вот C-программа, которую вы можете использовать для удаления записи loop-устройства:

#include <errno.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char** argv) {
    char *end;
    if (argc < 2) {
        printf("Необходимо указать номер устройства как аргумент\n");
        return 0;
    }
    long int dev_to_remove = strtol(argv[1], &end, 10);
    if (*end != '\0' || dev_to_remove < 0 || errno != 0) {
        printf("Неверный номер устройства\n");
        return 1;
    }
    const int fd = open("/dev/loop-control", O_RDWR);
    if (fd < 0) {
        perror("Не удалось открыть /dev/loop-control");
        return 1;
    }
    if (ioctl(fd, LOOP_CTL_REMOVE, dev_to_remove) < 0) {
        perror("Удаление устройства не удалось");
        close(fd);
        return 1;
    }
    close(fd);
    return 0;
}

Как использовать программу

  1. Компиляция программы: Сохраните код в файл, например, remove_loop_device.c, и скомпилируйте его с помощью gcc:

    gcc remove_loop_device.c -o remove_loop_device
  2. Запуск программы: Запустите с передачей номера loop-устройства, которое вы хотите удалить. Например, для удаления устройства /dev/loop90:

    sudo ./remove_loop_device 90

Общие рекомендации

  • Убедитесь, что loop-устройство не используется перед удалением.
  • Тщательно проверяйте номера устройств, передаваемые в программу, чтобы избежать случайного удаления используемых устройств.

Используя вышеуказанные шаги, вы сможете полностью удалить записи о loop-устройствах из вашей системы без необходимости перезагрузки, что является важным для поддержки надёжности и доступности вашего серверного окружения.

Оцените материал
Добавить комментарий

Капча загружается...