1 /*
2  * Copyright (c) 2008, XenSource Inc.
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 are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of XenSource Inc. nor the names of its contributors
13  *       may be used to endorse or promote products derived from this software
14  *       without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #ifndef _TAPDISK_VBD_H_
29 #define _TAPDISK_VBD_H_
30 
31 #include <sys/time.h>
32 #include <xenctrl.h>
33 #include <xen/io/blkif.h>
34 
35 #include "tapdisk.h"
36 #include "scheduler.h"
37 #include "tapdisk-image.h"
38 
39 #define TD_VBD_MAX_RETRIES          100
40 #define TD_VBD_RETRY_INTERVAL       1
41 
42 #define TD_VBD_DEAD                 0x0001
43 #define TD_VBD_CLOSED               0x0002
44 #define TD_VBD_QUIESCE_REQUESTED    0x0004
45 #define TD_VBD_QUIESCED             0x0008
46 #define TD_VBD_PAUSE_REQUESTED      0x0010
47 #define TD_VBD_PAUSED               0x0020
48 #define TD_VBD_SHUTDOWN_REQUESTED   0x0040
49 #define TD_VBD_LOCKING              0x0080
50 #define TD_VBD_RETRY_NEEDED         0x0100
51 #define TD_VBD_LOG_DROPPED          0x0200
52 
53 typedef struct td_ring              td_ring_t;
54 typedef struct td_vbd_request       td_vbd_request_t;
55 typedef struct td_vbd_driver_info   td_vbd_driver_info_t;
56 typedef struct td_vbd_handle        td_vbd_t;
57 typedef void (*td_vbd_cb_t)        (void *, blkif_response_t *);
58 
59 struct td_ring {
60 	int                         fd;
61 	char                       *mem;
62 	blkif_sring_t              *sring;
63 	blkif_back_ring_t           fe_ring;
64 	unsigned long               vstart;
65 };
66 
67 struct td_vbd_request {
68 	blkif_request_t             req;
69 	int16_t                     status;
70 
71 	int                         error;
72 	int                         blocked; /* blocked on a dependency */
73 	int                         submitting;
74 	int                         secs_pending;
75 	int                         num_retries;
76 	struct timeval              last_try;
77 
78 	td_vbd_t                   *vbd;
79 	struct list_head            next;
80 };
81 
82 struct td_vbd_driver_info {
83 	char                       *params;
84 	int                         type;
85 	struct list_head            next;
86 };
87 
88 struct td_vbd_handle {
89 	char                       *name;
90 
91 	td_uuid_t                   uuid;
92 	int                         minor;
93 
94 	struct list_head            driver_stack;
95 
96 	int                         storage;
97 
98 	uint8_t                     reopened;
99 	uint8_t                     reactivated;
100 	td_flag_t                   flags;
101 	td_flag_t                   state;
102 
103 	struct list_head            images;
104 
105 	struct list_head            new_requests;
106 	struct list_head            pending_requests;
107 	struct list_head            failed_requests;
108 	struct list_head            completed_requests;
109 
110 	td_vbd_request_t            request_list[MAX_REQUESTS];
111 
112 	td_ring_t                   ring;
113 	event_id_t                  ring_event_id;
114 
115 	td_vbd_cb_t                 callback;
116 	void                       *argument;
117 
118 	struct list_head            next;
119 
120 	struct timeval              ts;
121 
122 	uint64_t                    received;
123 	uint64_t                    returned;
124 	uint64_t                    kicked;
125 	uint64_t                    secs_pending;
126 	uint64_t                    retries;
127 	uint64_t                    errors;
128 };
129 
130 #define tapdisk_vbd_for_each_request(vreq, tmp, list)	                \
131 	list_for_each_entry_safe((vreq), (tmp), (list), next)
132 
133 #define tapdisk_vbd_for_each_image(vbd, image, tmp)			\
134 	list_for_each_entry_safe((image), (tmp), &(vbd)->images, next)
135 
136 static inline void
tapdisk_vbd_move_request(td_vbd_request_t * vreq,struct list_head * dest)137 tapdisk_vbd_move_request(td_vbd_request_t *vreq, struct list_head *dest)
138 {
139 	list_del(&vreq->next);
140 	INIT_LIST_HEAD(&vreq->next);
141 	list_add_tail(&vreq->next, dest);
142 }
143 
144 static inline void
tapdisk_vbd_add_image(td_vbd_t * vbd,td_image_t * image)145 tapdisk_vbd_add_image(td_vbd_t *vbd, td_image_t *image)
146 {
147 	list_add_tail(&image->next, &vbd->images);
148 }
149 
150 static inline int
tapdisk_vbd_is_last_image(td_vbd_t * vbd,td_image_t * image)151 tapdisk_vbd_is_last_image(td_vbd_t *vbd, td_image_t *image)
152 {
153 	return list_is_last(&image->next, &vbd->images);
154 }
155 
156 td_image_t *
157 tapdisk_vbd_first_image(td_vbd_t *vbd);
158 
159 static inline td_image_t *
tapdisk_vbd_last_image(td_vbd_t * vbd)160 tapdisk_vbd_last_image(td_vbd_t *vbd)
161 {
162 	return list_entry(vbd->images.prev, td_image_t, next);
163 }
164 
165 static inline td_image_t *
tapdisk_vbd_next_image(td_image_t * image)166 tapdisk_vbd_next_image(td_image_t *image)
167 {
168 	return list_entry(image->next.next, td_image_t, next);
169 }
170 
171 td_vbd_t *tapdisk_vbd_create(td_uuid_t);
172 int tapdisk_vbd_initialize(td_uuid_t);
173 void tapdisk_vbd_set_callback(td_vbd_t *, td_vbd_cb_t, void *);
174 int tapdisk_vbd_parse_stack(td_vbd_t *vbd, const char *path);
175 int tapdisk_vbd_open(td_vbd_t *, const char *, uint16_t,
176 		     uint16_t, int, const char *, td_flag_t);
177 int tapdisk_vbd_close(td_vbd_t *);
178 void tapdisk_vbd_free(td_vbd_t *);
179 void tapdisk_vbd_free_stack(td_vbd_t *);
180 
181 int tapdisk_vbd_open_stack(td_vbd_t *, uint16_t, td_flag_t);
182 int tapdisk_vbd_open_vdi(td_vbd_t *, const char *,
183 			 uint16_t, uint16_t, td_flag_t);
184 void tapdisk_vbd_close_vdi(td_vbd_t *);
185 
186 int tapdisk_vbd_attach(td_vbd_t *, const char *, int);
187 void tapdisk_vbd_detach(td_vbd_t *);
188 
189 void tapdisk_vbd_forward_request(td_request_t);
190 
191 int tapdisk_vbd_get_image_info(td_vbd_t *, image_t *);
192 int tapdisk_vbd_queue_ready(td_vbd_t *);
193 int tapdisk_vbd_retry_needed(td_vbd_t *);
194 int tapdisk_vbd_quiesce_queue(td_vbd_t *);
195 int tapdisk_vbd_start_queue(td_vbd_t *);
196 int tapdisk_vbd_issue_requests(td_vbd_t *);
197 int tapdisk_vbd_kill_queue(td_vbd_t *);
198 int tapdisk_vbd_pause(td_vbd_t *);
199 int tapdisk_vbd_resume(td_vbd_t *, const char *, uint16_t);
200 int tapdisk_vbd_kick(td_vbd_t *);
201 void tapdisk_vbd_check_state(td_vbd_t *);
202 void tapdisk_vbd_check_progress(td_vbd_t *);
203 void tapdisk_vbd_debug(td_vbd_t *);
204 
205 void tapdisk_vbd_complete_vbd_request(td_vbd_t *, td_vbd_request_t *);
206 
207 #endif
208