1/* $NetBSD: dm_target_linear.c,v 1.37 2020/01/21 16:27:53 tkusumi Exp $ */ 2 3/* 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Adam Hamsik. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31#include <sys/cdefs.h> 32__KERNEL_RCSID(0, "$NetBSD: dm_target_linear.c,v 1.37 2020/01/21 16:27:53 tkusumi Exp $"); 33 34/* 35 * This file implements initial version of device-mapper linear target. 36 */ 37 38#include <sys/types.h> 39#include <sys/param.h> 40#include <sys/buf.h> 41#include <sys/kmem.h> 42#include <sys/lwp.h> 43 44#include <machine/int_fmtio.h> 45 46#include "dm.h" 47 48/* 49 * Allocate target specific config data, and link them to table. 50 * This function is called only when, flags is not READONLY and 51 * therefore we can add things to pdev list. This should not a 52 * problem because this routine is called only from dm_table_load_ioctl. 53 * @argv[0] is name, 54 * @argv[1] is physical data offset. 55 */ 56int 57dm_target_linear_init(dm_table_entry_t *table_en, int argc, char **argv) 58{ 59 dm_target_linear_config_t *tlc; 60 dm_pdev_t *dmp; 61 62 if (argc != 2) { 63 printf("Linear target takes 2 args, %d given\n", argc); 64 return EINVAL; 65 } 66 67 aprint_debug("Linear target init function called %s--%s!!\n", 68 argv[0], argv[1]); 69 70 /* Insert dmp to global pdev list */ 71 if ((dmp = dm_pdev_insert(argv[0])) == NULL) 72 return ENOENT; 73 74 tlc = kmem_alloc(sizeof(dm_target_linear_config_t), KM_SLEEP); 75 tlc->pdev = dmp; 76 tlc->offset = atoi64(argv[1]); 77 78 dm_table_add_deps(table_en, dmp); 79 table_en->target_config = tlc; 80 81 return 0; 82} 83 84/* 85 * Table routine is called to get params string, which is target 86 * specific. When dm_table_status_ioctl is called with flag 87 * DM_STATUS_TABLE_FLAG I have to sent params string back. 88 */ 89char * 90dm_target_linear_table(void *target_config) 91{ 92 dm_target_linear_config_t *tlc; 93 char *params; 94 tlc = target_config; 95 96 aprint_debug("Linear target table function called\n"); 97 98 params = kmem_alloc(DM_MAX_PARAMS_SIZE, KM_SLEEP); 99 snprintf(params, DM_MAX_PARAMS_SIZE, "%s %" PRIu64, 100 tlc->pdev->udev_name, tlc->offset); 101 102 return params; 103} 104 105/* 106 * Do IO operation, called from dmstrategy routine. 107 */ 108int 109dm_target_linear_strategy(dm_table_entry_t *table_en, struct buf *bp) 110{ 111 dm_target_linear_config_t *tlc; 112 113 tlc = table_en->target_config; 114 115 bp->b_blkno += tlc->offset; 116 117 VOP_STRATEGY(tlc->pdev->pdev_vnode, bp); 118 119 return 0; 120} 121 122/* 123 * Sync underlying disk caches. 124 */ 125int 126dm_target_linear_sync(dm_table_entry_t *table_en) 127{ 128 int cmd; 129 dm_target_linear_config_t *tlc; 130 131 tlc = table_en->target_config; 132 133 cmd = 1; 134 135 return VOP_IOCTL(tlc->pdev->pdev_vnode, DIOCCACHESYNC, &cmd, 136 FREAD|FWRITE, kauth_cred_get()); 137} 138 139/* 140 * Destroy target specific data. Decrement table pdevs. 141 */ 142int 143dm_target_linear_destroy(dm_table_entry_t *table_en) 144{ 145 146 /* 147 * Destroy function is called for every target even if it 148 * doesn't have target_config. 149 */ 150 if (table_en->target_config == NULL) 151 goto out; 152 153 dm_target_linear_config_t *tlc = table_en->target_config; 154 155 /* Decrement pdev ref counter if 0 remove it */ 156 dm_pdev_decr(tlc->pdev); 157 158 kmem_free(tlc, sizeof(*tlc)); 159 160out: 161 /* Unbusy target so we can unload it */ 162 dm_target_unbusy(table_en->target); 163 return 0; 164} 165 166#if 0 167/* 168 * Register upcall device. 169 * Linear target doesn't need any upcall devices but other targets like 170 * mirror, snapshot, multipath, stripe will use this functionality. 171 */ 172int 173dm_target_linear_upcall(dm_table_entry_t *table_en, struct buf *bp) 174{ 175 176 return 0; 177} 178#endif 179 180/* 181 * Query physical block size of this target 182 * For a linear target this is just the sector size of the underlying device 183 */ 184int 185dm_target_linear_secsize(dm_table_entry_t *table_en, unsigned int *secsizep) 186{ 187 dm_target_linear_config_t *tlc; 188 unsigned int secsize; 189 190 secsize = 0; 191 192 tlc = table_en->target_config; 193 if (tlc != NULL) 194 secsize = tlc->pdev->pdev_secsize; 195 196 *secsizep = secsize; 197 198 return 0; 199} 200