/* * Copyright (C) International Business Machines Corp., 2006 * Author: Dan Smith * * This file is subject to the terms and conditions of the GNU Lesser * General Public License. See the file COPYING in the main directory * of this archive for more details. * */ /* * This example program demonstrates a trivial use of the dmu pieces * of the libdevmapper library for userspace orchestration of a * device-mapper pseudo-device. To compile: * * # gcc -ldevmapper -o dmu-example dmu-example.c * * Here, we simply map all reads and writes to the device given as the * first argument to the program. For example: * * # ./dmu-example /dev/ram0 * * will create a device /dev/mapper/foo in which all accesses are * redirected to /dev/ram0. */ #include #include #include #include #include #include #include #define VERBOSE 0 dev_t destination_dev; int count = 0; unsigned int total = 0; struct dmu_context *c; int map_handler(void *data, struct dmu_map_data *map_data) { /* We leave block pointing to the original location, but * change the destination device */ dmu_map_set_dest_dev(map_data, destination_dev); #if VERBOSE printf("[%llu] Mapping %llu -> 0x%llx\n", dmu_map_get_id(map_data), dmu_map_get_block(map_data), destination_dev); #endif count++; total++; /* Return 1 to signal that the mapping has been performed and * should be sent to the kernel */ return 1; } int map_done_handler(void *data, struct dmu_map_data *map_data) { #if VERBOSE printf("[%llu] Completing IO to block %llu\n", dmu_map_get_id(map_data), dmu_map_get_block(map_data)); #endif /* Return 1 to signal that the IO can be completed */ return 1; } int main(int argc, char **argv) { struct stat s; char cmd[256]; if (argc != 2) { printf("Usage: %s \n", argv[0]); exit(1); } printf("I'm creating a device-mapper device called 'foo'. \n" "Be sure to remove it when you're done with this example\n" "program! (run 'dmsetup remove foo')\n"); /* Determine and record our destination device for mappings */ stat(argv[1], &s); destination_dev = s.st_rdev; /* Create a very simple device-mapper device with a small * section of sectors mapped to dm-userspace, at 512-byte * blocks */ sprintf(cmd, "echo 0 1048576 userspace foo 4096 %i:%i | dmsetup create foo", (unsigned)(destination_dev & 0xFF00) >> 8, (unsigned)(destination_dev & 0x00FF)); system(cmd); /* Open the control device for the device-mapper device 'foo' */ c = dmu_ctl_open("foo", 0); if (!c) { printf("Failed to get control device\n"); exit(1); } /* Register our callback function for handling map events */ dmu_register_map_handler(c, map_handler, NULL); dmu_register_map_done_handler(c, map_done_handler, NULL); while (1) { if (dmu_events_pending(c, 1000)) { //printf("Processing events...\n"); dmu_process_events(c); printf("Processed %i events\n", count); count = 0; } else { printf("Nothing to do\n"); } printf("Total: %u\n", total); } }