]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/cam/ctl/ctl_backend.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / sys / cam / ctl / ctl_backend.c
1 /*-
2  * Copyright (c) 2003 Silicon Graphics International Corp.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    substantially similar to the "NO WARRANTY" disclaimer below
13  *    ("Disclaimer") and any redistribution must be conditioned upon
14  *    including a substantially similar Disclaimer requirement for further
15  *    binary redistribution.
16  *
17  * NO WARRANTY
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGES.
29  *
30  * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_backend.c#3 $
31  */
32 /*
33  * CTL backend driver registration routines
34  *
35  * Author: Ken Merry <ken@FreeBSD.org>
36  */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/types.h>
45 #include <sys/malloc.h>
46 #include <sys/lock.h>
47 #include <sys/mutex.h>
48 #include <sys/condvar.h>
49 #include <sys/queue.h>
50 #include <sys/sysctl.h>
51
52 #include <cam/scsi/scsi_all.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/ctl/ctl_io.h>
55 #include <cam/ctl/ctl.h>
56 #include <cam/ctl/ctl_frontend.h>
57 #include <cam/ctl/ctl_backend.h>
58 #include <cam/ctl/ctl_ioctl.h>
59 #include <cam/ctl/ctl_ha.h>
60 #include <cam/ctl/ctl_private.h>
61 #include <cam/ctl/ctl_debug.h>
62
63 extern struct ctl_softc *control_softc;
64
65 int
66 ctl_backend_register(struct ctl_backend_driver *be)
67 {
68         struct ctl_softc *softc = control_softc;
69         struct ctl_backend_driver *be_tmp;
70         int error;
71
72         /* Sanity check, make sure this isn't a duplicate registration. */
73         mtx_lock(&softc->ctl_lock);
74         STAILQ_FOREACH(be_tmp, &softc->be_list, links) {
75                 if (strcmp(be_tmp->name, be->name) == 0) {
76                         mtx_unlock(&softc->ctl_lock);
77                         return (-1);
78                 }
79         }
80         mtx_unlock(&softc->ctl_lock);
81 #ifdef CS_BE_CONFIG_MOVE_DONE_IS_NOT_USED
82         be->config_move_done = ctl_config_move_done;
83 #endif
84         be->num_luns = 0;
85
86         /* Call the backend's initialization routine. */
87         if (be->init != NULL) {
88                 if ((error = be->init()) != 0) {
89                         printf("%s backend init error: %d\n",
90                             be->name, error);
91                         return (error);
92                 }
93         }
94
95         mtx_lock(&softc->ctl_lock);
96         STAILQ_INSERT_TAIL(&softc->be_list, be, links);
97         softc->num_backends++;
98         mtx_unlock(&softc->ctl_lock);
99         return (0);
100 }
101
102 int
103 ctl_backend_deregister(struct ctl_backend_driver *be)
104 {
105         struct ctl_softc *softc = control_softc;
106         int error;
107
108         /* Call the backend's shutdown routine. */
109         if (be->shutdown != NULL) {
110                 if ((error = be->shutdown()) != 0) {
111                         printf("%s backend shutdown error: %d\n",
112                             be->name, error);
113                         return (error);
114                 }
115         }
116
117         mtx_lock(&softc->ctl_lock);
118         STAILQ_REMOVE(&softc->be_list, be, ctl_backend_driver, links);
119         softc->num_backends--;
120         mtx_unlock(&softc->ctl_lock);
121         return (0);
122 }
123
124 struct ctl_backend_driver *
125 ctl_backend_find(char *backend_name)
126 {
127         struct ctl_softc *softc = control_softc;
128         struct ctl_backend_driver *be_tmp;
129
130         mtx_lock(&softc->ctl_lock);
131         STAILQ_FOREACH(be_tmp, &softc->be_list, links) {
132                 if (strcmp(be_tmp->name, backend_name) == 0) {
133                         mtx_unlock(&softc->ctl_lock);
134                         return (be_tmp);
135                 }
136         }
137         mtx_unlock(&softc->ctl_lock);
138
139         return (NULL);
140 }
141
142 void
143 ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
144 {
145         struct ctl_option *opt;
146         int i;
147
148         STAILQ_INIT(opts);
149         for (i = 0; i < num_args; i++) {
150                 if ((args[i].flags & CTL_BEARG_RD) == 0)
151                         continue;
152                 if ((args[i].flags & CTL_BEARG_ASCII) == 0)
153                         continue;
154                 opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
155                 opt->name = strdup(args[i].kname, M_CTL);
156                 opt->value = strdup(args[i].kvalue, M_CTL);
157                 STAILQ_INSERT_TAIL(opts, opt, links);
158         }
159 }
160
161 void
162 ctl_update_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
163 {
164         struct ctl_option *opt;
165         int i;
166
167         for (i = 0; i < num_args; i++) {
168                 if ((args[i].flags & CTL_BEARG_RD) == 0)
169                         continue;
170                 if ((args[i].flags & CTL_BEARG_ASCII) == 0)
171                         continue;
172                 STAILQ_FOREACH(opt, opts, links) {
173                         if (strcmp(opt->name, args[i].kname) == 0)
174                                 break;
175                 }
176                 if (args[i].kvalue != NULL &&
177                     ((char *)args[i].kvalue)[0] != 0) {
178                         if (opt) {
179                                 free(opt->value, M_CTL);
180                                 opt->value = strdup(args[i].kvalue, M_CTL);
181                         } else {
182                                 opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
183                                 opt->name = strdup(args[i].kname, M_CTL);
184                                 opt->value = strdup(args[i].kvalue, M_CTL);
185                                 STAILQ_INSERT_TAIL(opts, opt, links);
186                         }
187                 } else if (opt) {
188                         STAILQ_REMOVE(opts, opt, ctl_option, links);
189                         free(opt->name, M_CTL);
190                         free(opt->value, M_CTL);
191                         free(opt, M_CTL);
192                 }
193         }
194 }
195
196 void
197 ctl_free_opts(ctl_options_t *opts)
198 {
199         struct ctl_option *opt;
200
201         while ((opt = STAILQ_FIRST(opts)) != NULL) {
202                 STAILQ_REMOVE_HEAD(opts, links);
203                 free(opt->name, M_CTL);
204                 free(opt->value, M_CTL);
205                 free(opt, M_CTL);
206         }
207 }
208
209 char *
210 ctl_get_opt(ctl_options_t *opts, const char *name)
211 {
212         struct ctl_option *opt;
213
214         STAILQ_FOREACH(opt, opts, links) {
215                 if (strcmp(opt->name, name) == 0) {
216                         return (opt->value);
217                 }
218         }
219         return (NULL);
220 }
221
222 int
223 ctl_get_opt_number(ctl_options_t *opts, const char *name, uint64_t *val)
224 {
225         const char *value;
226
227         value = ctl_get_opt(opts, name);
228         if (value == NULL)
229                 return (-2);
230         return (ctl_expand_number(value, val));
231 }