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; |