| File: | dev/bio.c |
| Warning: | line 115, column 3 Value stored to 'error' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: bio.c,v 1.19 2023/11/15 23:57:45 dlg Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 2002 Niklas Hallqvist. All rights reserved. |
| 5 | * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>. All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | /* A device controller ioctl tunnelling device. */ |
| 29 | |
| 30 | #include <sys/param.h> |
| 31 | #include <sys/device.h> |
| 32 | #include <sys/ioctl.h> |
| 33 | #include <sys/malloc.h> |
| 34 | #include <sys/tree.h> |
| 35 | #include <sys/systm.h> |
| 36 | |
| 37 | #include <dev/biovar.h> |
| 38 | |
| 39 | struct bio_mapping { |
| 40 | RBT_ENTRY(bio_mapping)struct rb_entry bm_link; |
| 41 | uintptr_t bm_cookie; |
| 42 | struct device *bm_dev; |
| 43 | int (*bm_ioctl)(struct device *, u_long, caddr_t); |
| 44 | }; |
| 45 | |
| 46 | RBT_HEAD(bio_mappings, bio_mapping)struct bio_mappings { struct rb_tree rbh_root; }; |
| 47 | |
| 48 | static inline int |
| 49 | bio_cookie_cmp(const struct bio_mapping *a, const struct bio_mapping *b) |
| 50 | { |
| 51 | if (a->bm_cookie < b->bm_cookie) |
| 52 | return (1); |
| 53 | if (a->bm_cookie > b->bm_cookie) |
| 54 | return (-1); |
| 55 | return (0); |
| 56 | } |
| 57 | |
| 58 | RBT_PROTOTYPE(bio_mappings, bio_mapping, bm_link, bio_cookie_cmp)extern const struct rb_type *const bio_mappings_RBT_TYPE; __attribute__ ((__unused__)) static inline void bio_mappings_RBT_INIT(struct bio_mappings *head) { _rb_init(&head->rbh_root); } __attribute__ ((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_INSERT (struct bio_mappings *head, struct bio_mapping *elm) { return _rb_insert(bio_mappings_RBT_TYPE, &head->rbh_root, elm ); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_REMOVE(struct bio_mappings *head, struct bio_mapping *elm) { return _rb_remove(bio_mappings_RBT_TYPE, &head-> rbh_root, elm); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_FIND(struct bio_mappings *head , const struct bio_mapping *key) { return _rb_find(bio_mappings_RBT_TYPE , &head->rbh_root, key); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_NFIND(struct bio_mappings *head, const struct bio_mapping *key) { return _rb_nfind (bio_mappings_RBT_TYPE, &head->rbh_root, key); } __attribute__ ((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_ROOT (struct bio_mappings *head) { return _rb_root(bio_mappings_RBT_TYPE , &head->rbh_root); } __attribute__((__unused__)) static inline int bio_mappings_RBT_EMPTY(struct bio_mappings *head) { return _rb_empty(&head->rbh_root); } __attribute__( (__unused__)) static inline struct bio_mapping * bio_mappings_RBT_MIN (struct bio_mappings *head) { return _rb_min(bio_mappings_RBT_TYPE , &head->rbh_root); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_MAX(struct bio_mappings *head) { return _rb_max(bio_mappings_RBT_TYPE, &head-> rbh_root); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_NEXT(struct bio_mapping *elm) { return _rb_next(bio_mappings_RBT_TYPE, elm); } __attribute__ ((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_PREV (struct bio_mapping *elm) { return _rb_prev(bio_mappings_RBT_TYPE , elm); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_LEFT(struct bio_mapping *elm) { return _rb_left (bio_mappings_RBT_TYPE, elm); } __attribute__((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_RIGHT(struct bio_mapping *elm) { return _rb_right(bio_mappings_RBT_TYPE, elm); } __attribute__ ((__unused__)) static inline struct bio_mapping * bio_mappings_RBT_PARENT (struct bio_mapping *elm) { return _rb_parent(bio_mappings_RBT_TYPE , elm); } __attribute__((__unused__)) static inline void bio_mappings_RBT_SET_LEFT (struct bio_mapping *elm, struct bio_mapping *left) { _rb_set_left (bio_mappings_RBT_TYPE, elm, left); } __attribute__((__unused__ )) static inline void bio_mappings_RBT_SET_RIGHT(struct bio_mapping *elm, struct bio_mapping *right) { _rb_set_right(bio_mappings_RBT_TYPE , elm, right); } __attribute__((__unused__)) static inline void bio_mappings_RBT_SET_PARENT(struct bio_mapping *elm, struct bio_mapping *parent) { _rb_set_parent(bio_mappings_RBT_TYPE, elm, parent ); } __attribute__((__unused__)) static inline void bio_mappings_RBT_POISON (struct bio_mapping *elm, unsigned long poison) { _rb_poison( bio_mappings_RBT_TYPE, elm, poison); } __attribute__((__unused__ )) static inline int bio_mappings_RBT_CHECK(struct bio_mapping *elm, unsigned long poison) { return _rb_check(bio_mappings_RBT_TYPE , elm, poison); }; |
| 59 | |
| 60 | struct bio_mappings bios = RBT_INITIALIZER(){ { ((void *)0) } }; |
| 61 | |
| 62 | void bioattach(int); |
| 63 | int bioclose(dev_t, int, int, struct proc *); |
| 64 | int bioioctl(dev_t, u_long, caddr_t, int, struct proc *); |
| 65 | int bioopen(dev_t, int, int, struct proc *); |
| 66 | |
| 67 | int bio_delegate_ioctl(struct bio_mapping *, u_long, caddr_t); |
| 68 | struct bio_mapping *bio_lookup(char *); |
| 69 | struct bio_mapping *bio_validate(void *); |
| 70 | |
| 71 | void |
| 72 | bioattach(int nunits) |
| 73 | { |
| 74 | } |
| 75 | |
| 76 | int |
| 77 | bioopen(dev_t dev, int flags, int mode, struct proc *p) |
| 78 | { |
| 79 | return (0); |
| 80 | } |
| 81 | |
| 82 | int |
| 83 | bioclose(dev_t dev, int flags, int mode, struct proc *p) |
| 84 | { |
| 85 | return (0); |
| 86 | } |
| 87 | |
| 88 | int |
| 89 | bioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) |
| 90 | { |
| 91 | struct bio_mapping *bm; |
| 92 | struct bio_locate *locate; |
| 93 | struct bio *bio; |
| 94 | char name[16]; |
| 95 | int error; |
| 96 | |
| 97 | switch (cmd) { |
| 98 | case BIOCLOCATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bio_locate) & 0x1fff) << 16) | ((('B')) << 8) | ((0))): |
| 99 | locate = (struct bio_locate *)addr; |
| 100 | error = copyinstr(locate->bl_name, name, sizeof name, NULL((void *)0)); |
| 101 | if (error != 0) |
| 102 | return (error); |
| 103 | bm = bio_lookup(name); |
| 104 | if (bm == NULL((void *)0)) |
| 105 | return (ENOENT2); |
| 106 | locate->bl_bio.bio_cookie = (void *)bm->bm_cookie; |
| 107 | break; |
| 108 | |
| 109 | default: |
| 110 | bio = (struct bio *)addr; |
| 111 | bm = bio_validate(bio->bio_cookie); |
| 112 | if (bm == NULL((void *)0)) |
| 113 | return (ENOENT2); |
| 114 | |
| 115 | error = bio_delegate_ioctl(bm, cmd, addr); |
Value stored to 'error' is never read | |
| 116 | break; |
| 117 | } |
| 118 | |
| 119 | return (0); |
| 120 | } |
| 121 | |
| 122 | int |
| 123 | bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, caddr_t)) |
| 124 | { |
| 125 | struct bio_mapping *bm; |
| 126 | |
| 127 | bm = malloc(sizeof *bm, M_DEVBUF2, M_NOWAIT0x0002); |
| 128 | if (bm == NULL((void *)0)) |
| 129 | return (ENOMEM12); |
| 130 | bm->bm_dev = dev; |
| 131 | bm->bm_ioctl = ioctl; |
| 132 | do { |
| 133 | bm->bm_cookie = arc4random(); |
| 134 | /* lets hope we don't have 4 billion bio_registers */ |
| 135 | } while (RBT_INSERT(bio_mappings, &bios, bm)bio_mappings_RBT_INSERT(&bios, bm) != NULL((void *)0)); |
| 136 | return (0); |
| 137 | } |
| 138 | |
| 139 | void |
| 140 | bio_unregister(struct device *dev) |
| 141 | { |
| 142 | struct bio_mapping *bm, *next; |
| 143 | |
| 144 | RBT_FOREACH_SAFE(bm, bio_mappings, &bios, next)for ((bm) = bio_mappings_RBT_MIN((&bios)); (bm) != ((void *)0) && ((next) = bio_mappings_RBT_NEXT((bm)), 1); ( bm) = (next)) { |
| 145 | if (dev == bm->bm_dev) { |
| 146 | RBT_REMOVE(bio_mappings, &bios, bm)bio_mappings_RBT_REMOVE(&bios, bm); |
| 147 | free(bm, M_DEVBUF2, sizeof(*bm)); |
| 148 | } |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | struct bio_mapping * |
| 153 | bio_lookup(char *name) |
| 154 | { |
| 155 | struct bio_mapping *bm; |
| 156 | |
| 157 | RBT_FOREACH(bm, bio_mappings, &bios)for ((bm) = bio_mappings_RBT_MIN((&bios)); (bm) != ((void *)0); (bm) = bio_mappings_RBT_NEXT((bm))) { |
| 158 | if (strcmp(name, bm->bm_dev->dv_xname) == 0) |
| 159 | return (bm); |
| 160 | } |
| 161 | |
| 162 | return (NULL((void *)0)); |
| 163 | } |
| 164 | |
| 165 | struct bio_mapping * |
| 166 | bio_validate(void *cookie) |
| 167 | { |
| 168 | struct bio_mapping key = { .bm_cookie = (uintptr_t)cookie }; |
| 169 | |
| 170 | return (RBT_FIND(bio_mappings, &bios, &key)bio_mappings_RBT_FIND(&bios, &key)); |
| 171 | } |
| 172 | |
| 173 | int |
| 174 | bio_delegate_ioctl(struct bio_mapping *bm, u_long cmd, caddr_t addr) |
| 175 | { |
| 176 | return (bm->bm_ioctl(bm->bm_dev, cmd, addr)); |
| 177 | } |
| 178 | |
| 179 | void |
| 180 | bio_info(struct bio_status *bs, int print, const char *fmt, ...) |
| 181 | { |
| 182 | va_list ap; |
| 183 | |
| 184 | va_start(ap, fmt)__builtin_va_start((ap), fmt); |
| 185 | bio_status(bs, print, BIO_MSG_INFO1, fmt, &ap); |
| 186 | va_end(ap)__builtin_va_end((ap)); |
| 187 | } |
| 188 | |
| 189 | void |
| 190 | bio_warn(struct bio_status *bs, int print, const char *fmt, ...) |
| 191 | { |
| 192 | va_list ap; |
| 193 | |
| 194 | va_start(ap, fmt)__builtin_va_start((ap), fmt); |
| 195 | bio_status(bs, print, BIO_MSG_WARN2, fmt, &ap); |
| 196 | va_end(ap)__builtin_va_end((ap)); |
| 197 | } |
| 198 | |
| 199 | void |
| 200 | bio_error(struct bio_status *bs, int print, const char *fmt, ...) |
| 201 | { |
| 202 | va_list ap; |
| 203 | |
| 204 | va_start(ap, fmt)__builtin_va_start((ap), fmt); |
| 205 | bio_status(bs, print, BIO_MSG_ERROR3, fmt, &ap); |
| 206 | va_end(ap)__builtin_va_end((ap)); |
| 207 | } |
| 208 | |
| 209 | void |
| 210 | bio_status_init(struct bio_status *bs, struct device *dv) |
| 211 | { |
| 212 | bzero(bs, sizeof(struct bio_status))__builtin_bzero((bs), (sizeof(struct bio_status))); |
| 213 | |
| 214 | bs->bs_status = BIO_STATUS_UNKNOWN0; |
| 215 | |
| 216 | strlcpy(bs->bs_controller, dv->dv_xname, sizeof(bs->bs_controller)); |
| 217 | } |
| 218 | |
| 219 | void |
| 220 | bio_status(struct bio_status *bs, int print, int msg_type, const char *fmt, |
| 221 | va_list *ap) |
| 222 | { |
| 223 | int idx; |
| 224 | |
| 225 | if (bs->bs_msg_count >= BIO_MSG_COUNT5) { |
| 226 | printf("%s: insufficient message buffers\n", bs->bs_controller); |
| 227 | return; |
| 228 | } |
| 229 | |
| 230 | idx = bs->bs_msg_count++; |
| 231 | |
| 232 | bs->bs_msgs[idx].bm_type = msg_type; |
| 233 | vsnprintf(bs->bs_msgs[idx].bm_msg, BIO_MSG_LEN128, fmt, *ap); |
| 234 | |
| 235 | if (print) |
| 236 | printf("%s: %s\n", bs->bs_controller, bs->bs_msgs[idx].bm_msg); |
| 237 | } |
| 238 | |
| 239 | RBT_GENERATE(bio_mappings, bio_mapping, bm_link, bio_cookie_cmp)static int bio_mappings_RBT_COMPARE(const void *lptr, const void *rptr) { const struct bio_mapping *l = lptr, *r = rptr; return bio_cookie_cmp(l, r); } static const struct rb_type bio_mappings_RBT_INFO = { bio_mappings_RBT_COMPARE, ((void *)0), __builtin_offsetof (struct bio_mapping, bm_link), }; const struct rb_type *const bio_mappings_RBT_TYPE = &bio_mappings_RBT_INFO; |