1*a70f355bSandvar /* $NetBSD: dm.h,v 1.56 2021/08/21 22:23:33 andvar Exp $ */ 2c9d0c62aShaad 3c9d0c62aShaad /* 4c9d0c62aShaad * Copyright (c) 2008 The NetBSD Foundation, Inc. 5c9d0c62aShaad * All rights reserved. 6c9d0c62aShaad * 7c9d0c62aShaad * This code is derived from software contributed to The NetBSD Foundation 8c9d0c62aShaad * by Adam Hamsik. 9c9d0c62aShaad * 10c9d0c62aShaad * Redistribution and use in source and binary forms, with or without 11c9d0c62aShaad * modification, are permitted provided that the following conditions 12c9d0c62aShaad * are met: 13c9d0c62aShaad * 1. Redistributions of source code must retain the above copyright 14c9d0c62aShaad * notice, this list of conditions and the following disclaimer. 15c9d0c62aShaad * 2. Redistributions in binary form must reproduce the above copyright 16c9d0c62aShaad * notice, this list of conditions and the following disclaimer in the 17c9d0c62aShaad * documentation and/or other materials provided with the distribution. 18c9d0c62aShaad * 19c9d0c62aShaad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20c9d0c62aShaad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21c9d0c62aShaad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22c9d0c62aShaad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23c9d0c62aShaad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24c9d0c62aShaad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25c9d0c62aShaad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26c9d0c62aShaad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27c9d0c62aShaad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28c9d0c62aShaad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29c9d0c62aShaad * POSSIBILITY OF SUCH DAMAGE. 30c9d0c62aShaad */ 31c9d0c62aShaad 3246b8a4bcStkusumi #ifndef _DM_H_ 3346b8a4bcStkusumi #define _DM_H_ 34c9d0c62aShaad 35c9d0c62aShaad #ifdef _KERNEL 36c9d0c62aShaad 37c9d0c62aShaad #include <sys/errno.h> 38c9d0c62aShaad #include <sys/atomic.h> 3958b64727Shaad #include <sys/fcntl.h> 40c9d0c62aShaad #include <sys/condvar.h> 4158b64727Shaad #include <sys/kauth.h> 42c9d0c62aShaad #include <sys/mutex.h> 43c9d0c62aShaad #include <sys/rwlock.h> 44c9d0c62aShaad #include <sys/queue.h> 452991ea0dStkusumi #include <sys/vnode.h> 4636fe0698Shaad #include <sys/device.h> 4775268cffSmlelstv #include <sys/disk.h> 4850b5b59cShaad #include <sys/disklabel.h> 4950b5b59cShaad 50292a0c7fShannken #include <miscfs/specfs/specdev.h> /* for v_rdev */ 51292a0c7fShannken 52b63bf390Sdyoung #include <prop/proplib.h> 53b63bf390Sdyoung 54c9d0c62aShaad #define DM_MAX_TYPE_NAME 16 55c9d0c62aShaad #define DM_NAME_LEN 128 56c9d0c62aShaad #define DM_UUID_LEN 129 57c9d0c62aShaad 58676cba41Shaad #define DM_VERSION_MAJOR 4 59676cba41Shaad #define DM_VERSION_MINOR 16 60676cba41Shaad 61c9d0c62aShaad #define DM_VERSION_PATCHLEVEL 0 62c9d0c62aShaad 63c9d0c62aShaad /*** Internal device-mapper structures ***/ 64c9d0c62aShaad 6554497987Stkusumi extern const struct dkdriver dmdkdriver; 6654497987Stkusumi extern uint32_t dm_dev_counter; 6754497987Stkusumi 68ee87a3caStkusumi typedef struct dm_mapping { 69ee87a3caStkusumi union { 70ee87a3caStkusumi struct dm_pdev *pdev; 71ee87a3caStkusumi } data; 72ee87a3caStkusumi TAILQ_ENTRY(dm_mapping) next; 73ee87a3caStkusumi } dm_mapping_t; 74ee87a3caStkusumi 75c9d0c62aShaad /* 76c9d0c62aShaad * A device mapper table is a list of physical ranges plus the mapping target 77c9d0c62aShaad * applied to them. 78c9d0c62aShaad */ 79c9d0c62aShaad typedef struct dm_table_entry { 80c9d0c62aShaad struct dm_dev *dm_dev; /* backlink */ 81c9d0c62aShaad uint64_t start; 82c9d0c62aShaad uint64_t length; 83c9d0c62aShaad 84c9d0c62aShaad struct dm_target *target; /* Link to table target. */ 85c9d0c62aShaad void *target_config; /* Target specific data. */ 86c9d0c62aShaad SLIST_ENTRY(dm_table_entry) next; 87ee87a3caStkusumi 88ee87a3caStkusumi TAILQ_HEAD(, dm_mapping) pdev_maps; 89c9d0c62aShaad } dm_table_entry_t; 90c9d0c62aShaad 91c9d0c62aShaad SLIST_HEAD(dm_table, dm_table_entry); 92c9d0c62aShaad 93c9d0c62aShaad typedef struct dm_table dm_table_t; 94c9d0c62aShaad 95c9d0c62aShaad typedef struct dm_table_head { 96c9d0c62aShaad /* Current active table is selected with this. */ 97c9d0c62aShaad int cur_active_table; 9846b8a4bcStkusumi dm_table_t tables[2]; 99c9d0c62aShaad 100c9d0c62aShaad kmutex_t table_mtx; 10146b8a4bcStkusumi kcondvar_t table_cv; /* I/O waiting cv */ 102c9d0c62aShaad 103c9d0c62aShaad uint32_t io_cnt; 104c9d0c62aShaad } dm_table_head_t; 105c9d0c62aShaad 106c9d0c62aShaad #define MAX_DEV_NAME 32 107c9d0c62aShaad 108c9d0c62aShaad /* 109c9d0c62aShaad * This structure is used to store opened vnodes for disk with name. 110c9d0c62aShaad * I need this because devices can be opened only once, but I can 111d860f590Swiz * have more than one device on one partition. 112c9d0c62aShaad */ 113c9d0c62aShaad typedef struct dm_pdev { 114c9d0c62aShaad char name[MAX_DEV_NAME]; 115aecedc2eStkusumi char udev_name[MAX_DEV_NAME]; 116c9d0c62aShaad 117c9d0c62aShaad struct vnode *pdev_vnode; 11875268cffSmlelstv uint64_t pdev_numsec; 119c3c15a28Stkusumi unsigned int pdev_secsize; 120c9d0c62aShaad int ref_cnt; /* reference counter for users of this pdev */ 121c9d0c62aShaad 122c9d0c62aShaad SLIST_ENTRY(dm_pdev) next_pdev; 123c9d0c62aShaad } dm_pdev_t; 124c9d0c62aShaad 125c9d0c62aShaad /* 126c9d0c62aShaad * This structure is called for every device-mapper device. 127c9d0c62aShaad * It points to SLIST of device tables and mirrored, snapshoted etc. devices. 128c9d0c62aShaad */ 129b1afbb31Smatt TAILQ_HEAD(dm_dev_head, dm_dev); 130b1afbb31Smatt //extern struct dm_dev_head dm_devs; 131c9d0c62aShaad 132c9d0c62aShaad typedef struct dm_dev { 133c9d0c62aShaad char name[DM_NAME_LEN]; 134c9d0c62aShaad char uuid[DM_UUID_LEN]; 135c9d0c62aShaad 13636fe0698Shaad device_t devt; /* pointer to autoconf device_t structure */ 13750cad777Shaad uint64_t minor; /* Device minor number */ 138c9d0c62aShaad uint32_t flags; /* store communication protocol flags */ 139c9d0c62aShaad 140*a70f355bSandvar kmutex_t dev_mtx; /* mutex for general device lock */ 141c9d0c62aShaad kcondvar_t dev_cv; /* cv for between ioctl synchronisation */ 142c9d0c62aShaad 143c9d0c62aShaad uint32_t event_nr; 144c9d0c62aShaad uint32_t ref_cnt; 145c9d0c62aShaad 146c9d0c62aShaad dm_table_head_t table_head; 147c9d0c62aShaad 148c6f7eba1Stkusumi //struct dm_dev_head upcalls; 149c9d0c62aShaad 150d80238daShaad struct disk *diskp; 15136fe0698Shaad kmutex_t diskp_mtx; 152c9d0c62aShaad 153c6f7eba1Stkusumi //TAILQ_ENTRY(dm_dev) next_upcall; /* LIST of mirrored, snapshoted devices. */ 154c9d0c62aShaad 155c9d0c62aShaad TAILQ_ENTRY(dm_dev) next_devlist; /* Major device list. */ 156c9d0c62aShaad } dm_dev_t; 157c9d0c62aShaad 15846b8a4bcStkusumi /* For linear target. */ 159c9d0c62aShaad typedef struct target_linear_config { 160c9d0c62aShaad dm_pdev_t *pdev; 161c9d0c62aShaad uint64_t offset; 1621a571ae4Shaad TAILQ_ENTRY(target_linear_config) entries; 163c9d0c62aShaad } dm_target_linear_config_t; 164c9d0c62aShaad 1651a571ae4Shaad /* 1661a571ae4Shaad * Striping devices are stored in a linked list, this might be inefficient 1671a571ae4Shaad * for more than 8 striping devices and can be changed to something more 1681a571ae4Shaad * scalable. 1691a571ae4Shaad * TODO: look for other options than linked list. 1701a571ae4Shaad */ 1711a571ae4Shaad TAILQ_HEAD(target_linear_devs, target_linear_config); 1721a571ae4Shaad 1731a571ae4Shaad typedef struct target_linear_devs dm_target_linear_devs_t; 1741a571ae4Shaad 175c9d0c62aShaad /* constant dm_target structures for error, zero, linear, stripes etc. */ 176c9d0c62aShaad typedef struct dm_target { 177c9d0c62aShaad char name[DM_MAX_TYPE_NAME]; 178c9d0c62aShaad /* Initialize target_config area */ 179d14bb027Stkusumi int (*init)(dm_table_entry_t *, int, char **); 180c9d0c62aShaad 181c9d0c62aShaad /* Destroy target_config area */ 182c9d0c62aShaad int (*destroy)(dm_table_entry_t *); 183c9d0c62aShaad 184c9d0c62aShaad int (*strategy)(dm_table_entry_t *, struct buf *); 18567de4a93Stkusumi //int (*upcall)(dm_table_entry_t *, struct buf *); 186c2813277Stkusumi 18737b6bcc1Stkusumi /* 18837b6bcc1Stkusumi * Optional routines. 18937b6bcc1Stkusumi */ 190a9ece896Stkusumi /* 191a9ece896Stkusumi * Info/table routine are called to get params string, which is target 192a9ece896Stkusumi * specific. When dm_table_status_ioctl is called with flag 193a9ece896Stkusumi * DM_STATUS_TABLE_FLAG I have to sent params string back. 194a9ece896Stkusumi */ 195c2813277Stkusumi char *(*info)(void *); 196a9ece896Stkusumi char *(*table)(void *); 197b83e697eStkusumi int (*sync)(dm_table_entry_t *); 198c3c15a28Stkusumi int (*secsize)(dm_table_entry_t *, unsigned int *); 199c9d0c62aShaad 200c9d0c62aShaad uint32_t version[3]; 20135079414Sjustin uint32_t ref_cnt; 202d14bb027Stkusumi int max_argc; 203c9d0c62aShaad 204c9d0c62aShaad TAILQ_ENTRY(dm_target) dm_target_next; 205c9d0c62aShaad } dm_target_t; 206c9d0c62aShaad 207c9d0c62aShaad /* device-mapper */ 208f5b48500Shaad void dmgetproperties(struct disk *, dm_table_head_t *); 209c9d0c62aShaad 210e4ac7035Stkusumi /* Generic function used to convert char to string */ 211e4ac7035Stkusumi uint64_t atoi64(const char *); 212e4ac7035Stkusumi 213c9d0c62aShaad /* dm_ioctl.c */ 214c9d0c62aShaad int dm_dev_create_ioctl(prop_dictionary_t); 215c9d0c62aShaad int dm_dev_list_ioctl(prop_dictionary_t); 216c9d0c62aShaad int dm_dev_remove_ioctl(prop_dictionary_t); 217c9d0c62aShaad int dm_dev_rename_ioctl(prop_dictionary_t); 218c9d0c62aShaad int dm_dev_resume_ioctl(prop_dictionary_t); 219c9d0c62aShaad int dm_dev_status_ioctl(prop_dictionary_t); 220c9d0c62aShaad int dm_dev_suspend_ioctl(prop_dictionary_t); 221c9d0c62aShaad 222c9d0c62aShaad int dm_check_version(prop_dictionary_t); 223c9d0c62aShaad int dm_list_versions_ioctl(prop_dictionary_t); 224c9d0c62aShaad 225c9d0c62aShaad int dm_table_clear_ioctl(prop_dictionary_t); 226c9d0c62aShaad int dm_table_deps_ioctl(prop_dictionary_t); 227c9d0c62aShaad int dm_table_load_ioctl(prop_dictionary_t); 228c9d0c62aShaad int dm_table_status_ioctl(prop_dictionary_t); 229c9d0c62aShaad 230c9d0c62aShaad /* dm_target.c */ 231cca8fb31Shaad dm_target_t* dm_target_alloc(const char *); 23217599f37Shaad dm_target_t* dm_target_autoload(const char *); 233c9d0c62aShaad int dm_target_destroy(void); 234c9d0c62aShaad int dm_target_insert(dm_target_t *); 235c9d0c62aShaad prop_array_t dm_target_prop_list(void); 23678284dcaShaad dm_target_t* dm_target_lookup(const char *); 2371c486dc6Stkusumi int dm_target_rem(const char *); 23878284dcaShaad void dm_target_unbusy(dm_target_t *); 23978284dcaShaad void dm_target_busy(dm_target_t *); 240c9d0c62aShaad int dm_target_init(void); 241c9d0c62aShaad 24262e994ceShaad #define DM_MAX_PARAMS_SIZE 1024 24362e994ceShaad 244c9d0c62aShaad /* dm_target_linear.c */ 245d14bb027Stkusumi int dm_target_linear_init(dm_table_entry_t *, int, char **); 2468026110eStkusumi char *dm_target_linear_table(void *); 247c9d0c62aShaad int dm_target_linear_strategy(dm_table_entry_t *, struct buf *); 24858b64727Shaad int dm_target_linear_sync(dm_table_entry_t *); 249c9d0c62aShaad int dm_target_linear_destroy(dm_table_entry_t *); 25067de4a93Stkusumi //int dm_target_linear_upcall(dm_table_entry_t *, struct buf *); 251c3c15a28Stkusumi int dm_target_linear_secsize(dm_table_entry_t *, unsigned int *); 252c9d0c62aShaad 25332013fd9Shaad /* dm_target_stripe.c */ 254d14bb027Stkusumi int dm_target_stripe_init(dm_table_entry_t *, int, char **); 255c2813277Stkusumi char *dm_target_stripe_info(void *); 2568026110eStkusumi char *dm_target_stripe_table(void *); 25732013fd9Shaad int dm_target_stripe_strategy(dm_table_entry_t *, struct buf *); 25858b64727Shaad int dm_target_stripe_sync(dm_table_entry_t *); 25932013fd9Shaad int dm_target_stripe_destroy(dm_table_entry_t *); 26067de4a93Stkusumi //int dm_target_stripe_upcall(dm_table_entry_t *, struct buf *); 261c3c15a28Stkusumi int dm_target_stripe_secsize(dm_table_entry_t *, unsigned int *); 26232013fd9Shaad 26384d45206Stkusumi /* dm_target_error.c */ 26484d45206Stkusumi int dm_target_error_init(dm_table_entry_t*, int, char **); 26584d45206Stkusumi int dm_target_error_strategy(dm_table_entry_t *, struct buf *); 26684d45206Stkusumi int dm_target_error_destroy(dm_table_entry_t *); 26767de4a93Stkusumi //int dm_target_error_upcall(dm_table_entry_t *, struct buf *); 26884d45206Stkusumi 26984d45206Stkusumi /* dm_target_zero.c */ 27084d45206Stkusumi int dm_target_zero_init(dm_table_entry_t *, int, char **); 27184d45206Stkusumi int dm_target_zero_strategy(dm_table_entry_t *, struct buf *); 27284d45206Stkusumi int dm_target_zero_destroy(dm_table_entry_t *); 27367de4a93Stkusumi //int dm_target_zero_upcall(dm_table_entry_t *, struct buf *); 27484d45206Stkusumi 2758dab45b6Stkusumi #if 0 276ea24dc8dStkusumi /* dm_target_delay.c */ 277ea24dc8dStkusumi void dm_target_delay_pool_create(void); 278ea24dc8dStkusumi void dm_target_delay_pool_destroy(void); 279ea24dc8dStkusumi int dm_target_delay_init(dm_table_entry_t *, int, char **); 280ea24dc8dStkusumi char *dm_target_delay_info(void *); 281ea24dc8dStkusumi char *dm_target_delay_table(void *); 282ea24dc8dStkusumi int dm_target_delay_strategy(dm_table_entry_t *, struct buf *); 283ea24dc8dStkusumi int dm_target_delay_sync(dm_table_entry_t *); 284ea24dc8dStkusumi int dm_target_delay_destroy(dm_table_entry_t *); 28567de4a93Stkusumi //int dm_target_delay_upcall(dm_table_entry_t *, struct buf *); 286ea24dc8dStkusumi int dm_target_delay_secsize(dm_table_entry_t *, unsigned int *); 287ea24dc8dStkusumi 2888dab45b6Stkusumi /* dm_target_flakey.c */ 2898dab45b6Stkusumi int dm_target_flakey_init(dm_table_entry_t *, int, char **); 2908dab45b6Stkusumi char *dm_target_flakey_table(void *); 2918dab45b6Stkusumi int dm_target_flakey_strategy(dm_table_entry_t *, struct buf *); 2928dab45b6Stkusumi int dm_target_flakey_sync(dm_table_entry_t *); 2938dab45b6Stkusumi int dm_target_flakey_destroy(dm_table_entry_t *); 29467de4a93Stkusumi //int dm_target_flakey_upcall(dm_table_entry_t *, struct buf *); 2958dab45b6Stkusumi int dm_target_flakey_secsize(dm_table_entry_t *, unsigned int *); 2968dab45b6Stkusumi #endif 2978dab45b6Stkusumi 298c9d0c62aShaad /* dm_table.c */ 299c9d0c62aShaad #define DM_TABLE_ACTIVE 0 300c9d0c62aShaad #define DM_TABLE_INACTIVE 1 301c9d0c62aShaad 302c9d0c62aShaad int dm_table_destroy(dm_table_head_t *, uint8_t); 303c9d0c62aShaad uint64_t dm_table_size(dm_table_head_t *); 304ff2b2e8eSahoka uint64_t dm_inactive_table_size(dm_table_head_t *); 305c3c15a28Stkusumi void dm_table_disksize(dm_table_head_t *, uint64_t *, unsigned int *); 306c9d0c62aShaad dm_table_t *dm_table_get_entry(dm_table_head_t *, uint8_t); 307c9d0c62aShaad int dm_table_get_target_count(dm_table_head_t *, uint8_t); 308c9d0c62aShaad void dm_table_release(dm_table_head_t *, uint8_t s); 309c9d0c62aShaad void dm_table_switch_tables(dm_table_head_t *); 310c9d0c62aShaad void dm_table_head_init(dm_table_head_t *); 311c9d0c62aShaad void dm_table_head_destroy(dm_table_head_t *); 312ee87a3caStkusumi int dm_table_add_deps(dm_table_entry_t *, dm_pdev_t *); 313c9d0c62aShaad 314c9d0c62aShaad /* dm_dev.c */ 315c9d0c62aShaad dm_dev_t* dm_dev_alloc(void); 316c9d0c62aShaad void dm_dev_busy(dm_dev_t *); 317c9d0c62aShaad int dm_dev_destroy(void); 31836fe0698Shaad dm_dev_t* dm_dev_detach(device_t); 319c9d0c62aShaad int dm_dev_free(dm_dev_t *); 320c9d0c62aShaad int dm_dev_init(void); 321c9d0c62aShaad int dm_dev_insert(dm_dev_t *); 322c9d0c62aShaad dm_dev_t* dm_dev_lookup(const char *, const char *, int); 323c9d0c62aShaad prop_array_t dm_dev_prop_list(void); 324c9d0c62aShaad dm_dev_t* dm_dev_rem(const char *, const char *, int); 325c9d0c62aShaad /*int dm_dev_test_minor(int);*/ 326c9d0c62aShaad void dm_dev_unbusy(dm_dev_t *); 327c9d0c62aShaad 328c9d0c62aShaad /* dm_pdev.c */ 329c9d0c62aShaad int dm_pdev_decr(dm_pdev_t *); 330c9d0c62aShaad int dm_pdev_destroy(void); 331c9d0c62aShaad int dm_pdev_init(void); 332c9d0c62aShaad dm_pdev_t* dm_pdev_insert(const char *); 333c9d0c62aShaad 334c9d0c62aShaad #endif /*_KERNEL*/ 335c9d0c62aShaad 33646b8a4bcStkusumi #endif /*_DM_H_*/ 337