You need to create a virtual device using the device-mapper utility during system boot.
To do this, I create my own copy of initramfs (initrd) using the mkinitcpio utility. I specify the following configuration file:
MODULES="dm-mod basic_target" BINARIES="dmsetup" FILES="/etc/udev/rules.d/61-local.rules /lib/udev/create_virtual.sh" HOOKS="base udev autodetect modconf block filesystems keyboard fsck" basic_target is a self-written kernel module, the source code of which is copied with minor changes from this article .
The contents of the file /etc/udev/rules.d/61-local.rules :
KERNEL=="sd*",SUBSYSTEM=="block",ACTION=="add",ENV{ID_FS_UUID}=="abe3b587-3a5f-47d6-8f66-2df758e70665",RUN+="/lib/udev/create_virtual.sh %k" Content /lib/udev/create_virtual.sh :
#!/bin/sh dmsetup create root_part --table "0 32359055360 basic_target /dev/$1 0" exit 0 The udev rules are executed and the script is launched. However, at the end of the execution of the device mapper target constructor (its code is described below), the download hangs for a while.
Here is the constructor code:
static int basic_target_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct my_dm_target *mdt; unsigned long long start; printk(KERN_CRIT "\n >>in function basic_target_ctr \n"); if (argc != 2) { printk(KERN_CRIT "\n Invalid no of arguments.\n"); ti->error = "Invalid argument count"; return -EINVAL; } mdt = kmalloc(sizeof(struct my_dm_target), GFP_KERNEL); if (mdt == NULL) { printk(KERN_CRIT "\n Mdt is null\n"); ti->error = "dm-basic_target: Cannot allocate linear context"; return -ENOMEM; } if (sscanf(argv[1], "%llu", &start) != 1) { ti->error = "dm-basic_target: Invalid device sector"; goto bad; } mdt->start = (sector_t)start; if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &mdt->dev)) { ti->error = "dm-basic_target: Device lookup failed"; goto bad; } ti->private = mdt; printk(KERN_CRIT "\n>>out function basic_target_ctr \n"); return 0; bad: kfree(mdt); printk(KERN_CRIT "\n>>out function basic_target_ctr with errorrrrrrrrrr \n"); return -EINVAL; } The string ">> out function basic_target_ctr" is output and nothing else happens.
At the same time, in the already loaded system, the script started manually, is triggered successfully. dmesg says that after completing the work of the constructor, two read requests are still being executed (the basic_target_map function from the article). These requests are not executed at system boot time.
Just in case, the function basic_target_map:
static int basic_target_map(struct dm_target *ti, struct bio *bio) { struct my_dm_target *mdt = (struct my_dm_target *) ti->private; printk(KERN_CRIT "\n<<in function basic_target_map \n"); bio->bi_bdev = mdt->dev->bdev; if((bio->bi_opf & WRITE) == WRITE) printk(KERN_CRIT "\n basic_target_map : bio is a write request.... \n"); else printk(KERN_CRIT "\n basic_target_map : bio is a read request.... \n"); submit_bio(bio); printk(KERN_CRIT "\n>>out function basic_target_map \n"); return DM_MAPIO_SUBMITTED; } After about a minute of waiting, the system will continue loading. At the same time, one more udev daemon that started up during the boot phase does not cease to "hang" in the system.
Tell me, what errors are present in this algorithm, and how to fix them!