1*f603807bSTomohiro Kusumi /* $NetBSD: dm_target_linear.c,v 1.9 2010/01/04 00:14:41 haad Exp $ */ 2*f603807bSTomohiro Kusumi 3*f603807bSTomohiro Kusumi /* 4*f603807bSTomohiro Kusumi * Copyright (c) 2008 The NetBSD Foundation, Inc. 5*f603807bSTomohiro Kusumi * All rights reserved. 6*f603807bSTomohiro Kusumi * 7*f603807bSTomohiro Kusumi * This code is derived from software contributed to The NetBSD Foundation 8*f603807bSTomohiro Kusumi * by Adam Hamsik. 9*f603807bSTomohiro Kusumi * 10*f603807bSTomohiro Kusumi * Redistribution and use in source and binary forms, with or without 11*f603807bSTomohiro Kusumi * modification, are permitted provided that the following conditions 12*f603807bSTomohiro Kusumi * are met: 13*f603807bSTomohiro Kusumi * 1. Redistributions of source code must retain the above copyright 14*f603807bSTomohiro Kusumi * notice, this list of conditions and the following disclaimer. 15*f603807bSTomohiro Kusumi * 2. Redistributions in binary form must reproduce the above copyright 16*f603807bSTomohiro Kusumi * notice, this list of conditions and the following disclaimer in the 17*f603807bSTomohiro Kusumi * documentation and/or other materials provided with the distribution. 18*f603807bSTomohiro Kusumi * 19*f603807bSTomohiro Kusumi * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*f603807bSTomohiro Kusumi * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*f603807bSTomohiro Kusumi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*f603807bSTomohiro Kusumi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*f603807bSTomohiro Kusumi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*f603807bSTomohiro Kusumi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*f603807bSTomohiro Kusumi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*f603807bSTomohiro Kusumi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*f603807bSTomohiro Kusumi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*f603807bSTomohiro Kusumi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*f603807bSTomohiro Kusumi * POSSIBILITY OF SUCH DAMAGE. 30*f603807bSTomohiro Kusumi */ 31*f603807bSTomohiro Kusumi 32*f603807bSTomohiro Kusumi 33*f603807bSTomohiro Kusumi /* 34*f603807bSTomohiro Kusumi * This file implements initial version of device-mapper dklinear target. 35*f603807bSTomohiro Kusumi */ 36*f603807bSTomohiro Kusumi 37*f603807bSTomohiro Kusumi #include <sys/malloc.h> 38*f603807bSTomohiro Kusumi 39*f603807bSTomohiro Kusumi #include <dev/disk/dm/dm.h> 40*f603807bSTomohiro Kusumi MALLOC_DEFINE(M_DMLINEAR, "dm_linear", "Device Mapper Target Linear"); 41*f603807bSTomohiro Kusumi 42*f603807bSTomohiro Kusumi typedef struct target_linear_config { 43*f603807bSTomohiro Kusumi dm_pdev_t *pdev; 44*f603807bSTomohiro Kusumi uint64_t offset; 45*f603807bSTomohiro Kusumi } dm_target_linear_config_t; 46*f603807bSTomohiro Kusumi 47*f603807bSTomohiro Kusumi /* 48*f603807bSTomohiro Kusumi * Allocate target specific config data, and link them to table. 49*f603807bSTomohiro Kusumi * This function is called only when, flags is not READONLY and 50*f603807bSTomohiro Kusumi * therefore we can add things to pdev list. This should not a 51*f603807bSTomohiro Kusumi * problem because this routine is called only from dm_table_load_ioctl. 52*f603807bSTomohiro Kusumi * @argv[0] is name, 53*f603807bSTomohiro Kusumi * @argv[1] is physical data offset. 54*f603807bSTomohiro Kusumi */ 55*f603807bSTomohiro Kusumi static int 56*f603807bSTomohiro Kusumi dm_target_linear_init(dm_table_entry_t *table_en, int argc, char **argv) 57*f603807bSTomohiro Kusumi { 58*f603807bSTomohiro Kusumi dm_target_linear_config_t *tlc; 59*f603807bSTomohiro Kusumi dm_pdev_t *dmp; 60*f603807bSTomohiro Kusumi 61*f603807bSTomohiro Kusumi if (argc != 2) { 62*f603807bSTomohiro Kusumi kprintf("Linear target takes 2 args\n"); 63*f603807bSTomohiro Kusumi return EINVAL; 64*f603807bSTomohiro Kusumi } 65*f603807bSTomohiro Kusumi 66*f603807bSTomohiro Kusumi dmdebug("Linear target init function called %s--%s!!\n", 67*f603807bSTomohiro Kusumi argv[0], argv[1]); 68*f603807bSTomohiro Kusumi 69*f603807bSTomohiro Kusumi /* Insert dmp to global pdev list */ 70*f603807bSTomohiro Kusumi if ((dmp = dm_pdev_insert(argv[0])) == NULL) 71*f603807bSTomohiro Kusumi return ENOENT; 72*f603807bSTomohiro Kusumi 73*f603807bSTomohiro Kusumi if ((tlc = kmalloc(sizeof(dm_target_linear_config_t), M_DMLINEAR, M_WAITOK)) 74*f603807bSTomohiro Kusumi == NULL) 75*f603807bSTomohiro Kusumi return ENOMEM; 76*f603807bSTomohiro Kusumi 77*f603807bSTomohiro Kusumi tlc->pdev = dmp; 78*f603807bSTomohiro Kusumi tlc->offset = atoi64(argv[1]); 79*f603807bSTomohiro Kusumi 80*f603807bSTomohiro Kusumi dm_table_add_deps(table_en, dmp); 81*f603807bSTomohiro Kusumi 82*f603807bSTomohiro Kusumi dm_table_init_target(table_en, DM_LINEAR_DEV, tlc); 83*f603807bSTomohiro Kusumi 84*f603807bSTomohiro Kusumi return 0; 85*f603807bSTomohiro Kusumi } 86*f603807bSTomohiro Kusumi 87*f603807bSTomohiro Kusumi /* 88*f603807bSTomohiro Kusumi * Table routine is called to get params string, which is target 89*f603807bSTomohiro Kusumi * specific. When dm_table_status_ioctl is called with flag 90*f603807bSTomohiro Kusumi * DM_STATUS_TABLE_FLAG I have to sent params string back. 91*f603807bSTomohiro Kusumi */ 92*f603807bSTomohiro Kusumi static char * 93*f603807bSTomohiro Kusumi dm_target_linear_table(void *target_config) 94*f603807bSTomohiro Kusumi { 95*f603807bSTomohiro Kusumi dm_target_linear_config_t *tlc; 96*f603807bSTomohiro Kusumi char *params; 97*f603807bSTomohiro Kusumi tlc = target_config; 98*f603807bSTomohiro Kusumi 99*f603807bSTomohiro Kusumi dmdebug("Linear target table function called\n"); 100*f603807bSTomohiro Kusumi 101*f603807bSTomohiro Kusumi params = dm_alloc_string(DM_MAX_PARAMS_SIZE); 102*f603807bSTomohiro Kusumi 103*f603807bSTomohiro Kusumi ksnprintf(params, DM_MAX_PARAMS_SIZE, "%s %" PRIu64, 104*f603807bSTomohiro Kusumi tlc->pdev->udev_name, tlc->offset); 105*f603807bSTomohiro Kusumi 106*f603807bSTomohiro Kusumi return params; 107*f603807bSTomohiro Kusumi } 108*f603807bSTomohiro Kusumi 109*f603807bSTomohiro Kusumi /* 110*f603807bSTomohiro Kusumi * Do IO operation, called from dmstrategy routine. 111*f603807bSTomohiro Kusumi */ 112*f603807bSTomohiro Kusumi static int 113*f603807bSTomohiro Kusumi dm_target_linear_strategy(dm_table_entry_t *table_en, struct buf *bp) 114*f603807bSTomohiro Kusumi { 115*f603807bSTomohiro Kusumi dm_target_linear_config_t *tlc; 116*f603807bSTomohiro Kusumi 117*f603807bSTomohiro Kusumi tlc = table_en->target_config; 118*f603807bSTomohiro Kusumi 119*f603807bSTomohiro Kusumi /* kprintf("Linear target read function called %" PRIu64 "!!\n", 120*f603807bSTomohiro Kusumi tlc->offset);*/ 121*f603807bSTomohiro Kusumi 122*f603807bSTomohiro Kusumi bp->b_bio1.bio_offset += tlc->offset * DEV_BSIZE; 123*f603807bSTomohiro Kusumi 124*f603807bSTomohiro Kusumi vn_strategy(tlc->pdev->pdev_vnode, &bp->b_bio1); 125*f603807bSTomohiro Kusumi 126*f603807bSTomohiro Kusumi return 0; 127*f603807bSTomohiro Kusumi 128*f603807bSTomohiro Kusumi } 129*f603807bSTomohiro Kusumi 130*f603807bSTomohiro Kusumi static int 131*f603807bSTomohiro Kusumi dm_target_linear_dump(dm_table_entry_t *table_en, void *data, size_t length, off_t offset) 132*f603807bSTomohiro Kusumi { 133*f603807bSTomohiro Kusumi dm_target_linear_config_t *tlc; 134*f603807bSTomohiro Kusumi 135*f603807bSTomohiro Kusumi tlc = table_en->target_config; 136*f603807bSTomohiro Kusumi 137*f603807bSTomohiro Kusumi offset += tlc->offset * DEV_BSIZE; 138*f603807bSTomohiro Kusumi offset = dm_pdev_correct_dump_offset(tlc->pdev, offset); 139*f603807bSTomohiro Kusumi 140*f603807bSTomohiro Kusumi if (tlc->pdev->pdev_vnode->v_rdev == NULL) 141*f603807bSTomohiro Kusumi return ENXIO; 142*f603807bSTomohiro Kusumi 143*f603807bSTomohiro Kusumi return dev_ddump(tlc->pdev->pdev_vnode->v_rdev, data, 0, offset, length); 144*f603807bSTomohiro Kusumi } 145*f603807bSTomohiro Kusumi 146*f603807bSTomohiro Kusumi /* 147*f603807bSTomohiro Kusumi * Destroy target specific data. Decrement table pdevs. 148*f603807bSTomohiro Kusumi */ 149*f603807bSTomohiro Kusumi static int 150*f603807bSTomohiro Kusumi dm_target_linear_destroy(dm_table_entry_t *table_en) 151*f603807bSTomohiro Kusumi { 152*f603807bSTomohiro Kusumi dm_target_linear_config_t *tlc; 153*f603807bSTomohiro Kusumi 154*f603807bSTomohiro Kusumi /* 155*f603807bSTomohiro Kusumi * Destroy function is called for every target even if it 156*f603807bSTomohiro Kusumi * doesn't have target_config. 157*f603807bSTomohiro Kusumi */ 158*f603807bSTomohiro Kusumi 159*f603807bSTomohiro Kusumi if (table_en->target_config == NULL) 160*f603807bSTomohiro Kusumi return 0; 161*f603807bSTomohiro Kusumi 162*f603807bSTomohiro Kusumi tlc = table_en->target_config; 163*f603807bSTomohiro Kusumi 164*f603807bSTomohiro Kusumi /* Decrement pdev ref counter if 0 remove it */ 165*f603807bSTomohiro Kusumi dm_pdev_decr(tlc->pdev); 166*f603807bSTomohiro Kusumi 167*f603807bSTomohiro Kusumi kfree(table_en->target_config, M_DMLINEAR); 168*f603807bSTomohiro Kusumi 169*f603807bSTomohiro Kusumi return 0; 170*f603807bSTomohiro Kusumi } 171*f603807bSTomohiro Kusumi 172*f603807bSTomohiro Kusumi static int 173*f603807bSTomohiro Kusumi dmtl_mod_handler(module_t mod, int type, void *unused) 174*f603807bSTomohiro Kusumi { 175*f603807bSTomohiro Kusumi dm_target_t *dmt = NULL; 176*f603807bSTomohiro Kusumi int err = 0; 177*f603807bSTomohiro Kusumi 178*f603807bSTomohiro Kusumi switch(type) { 179*f603807bSTomohiro Kusumi case MOD_LOAD: 180*f603807bSTomohiro Kusumi if ((dmt = dm_target_lookup("linear")) != NULL) { 181*f603807bSTomohiro Kusumi dm_target_unbusy(dmt); 182*f603807bSTomohiro Kusumi return EEXIST; 183*f603807bSTomohiro Kusumi } 184*f603807bSTomohiro Kusumi dmt = dm_target_alloc("linear"); 185*f603807bSTomohiro Kusumi dmt->version[0] = 1; 186*f603807bSTomohiro Kusumi dmt->version[1] = 0; 187*f603807bSTomohiro Kusumi dmt->version[2] = 2; 188*f603807bSTomohiro Kusumi dmt->init = &dm_target_linear_init; 189*f603807bSTomohiro Kusumi dmt->destroy = &dm_target_linear_destroy; 190*f603807bSTomohiro Kusumi dmt->strategy = &dm_target_linear_strategy; 191*f603807bSTomohiro Kusumi dmt->table = &dm_target_linear_table; 192*f603807bSTomohiro Kusumi dmt->dump = &dm_target_linear_dump; 193*f603807bSTomohiro Kusumi 194*f603807bSTomohiro Kusumi err = dm_target_insert(dmt); 195*f603807bSTomohiro Kusumi if (err == 0) 196*f603807bSTomohiro Kusumi kprintf("dm_target_linear: Successfully initialized\n"); 197*f603807bSTomohiro Kusumi break; 198*f603807bSTomohiro Kusumi 199*f603807bSTomohiro Kusumi case MOD_UNLOAD: 200*f603807bSTomohiro Kusumi err = dm_target_remove("linear"); 201*f603807bSTomohiro Kusumi if (err == 0) 202*f603807bSTomohiro Kusumi kprintf("dm_target_linear: unloaded\n"); 203*f603807bSTomohiro Kusumi break; 204*f603807bSTomohiro Kusumi } 205*f603807bSTomohiro Kusumi 206*f603807bSTomohiro Kusumi return err; 207*f603807bSTomohiro Kusumi } 208*f603807bSTomohiro Kusumi 209*f603807bSTomohiro Kusumi DM_TARGET_MODULE(dm_target_linear, dmtl_mod_handler); 210