1 /*
2  * Copyright (c) 2007, 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  * Some notes on the tap_disk interface:
29  *
30  * tap_disk aims to provide a generic interface to easily implement new
31  * types of image accessors.  The structure-of-function-calls is similar
32  * to disk interfaces used in qemu/denali/etc, with the significant
33  * difference being the expectation of asynchronous rather than synchronous
34  * I/O.  The asynchronous interface is intended to allow lots of requests to
35  * be pipelined through a disk, without the disk requiring any of its own
36  * threads of control.  As such, a batch of requests is delivered to the disk
37  * using:
38  *
39  *    td_queue_[read,write]()
40  *
41  * and passing in a completion callback, which the disk is responsible for
42  * tracking.  Disks should transform these requests as necessary and return
43  * the resulting iocbs to tapdisk using td_prep_[read,write]() and
44  * td_queue_tiocb().
45  *
46  * NOTE: tapdisk uses the number of sectors submitted per request as a
47  * ref count.  Plugins must use the callback function to communicate the
48  * completion -- or error -- of every sector submitted to them.
49  *
50  * td_get_parent_id returns:
51  *     0 if parent id successfully retrieved
52  *     TD_NO_PARENT if no parent exists
53  *     -errno on error
54  */
55 
56 #ifndef _TAPDISK_H_
57 #define _TAPDISK_H_
58 
59 #include <time.h>
60 #include <stdint.h>
61 
62 #include "list.h"
63 #include "blktaplib.h"
64 #include "tapdisk-log.h"
65 #include "tapdisk-utils.h"
66 
67 #ifdef MEMSHR
68 #include "memshr.h"
69 #endif
70 
71 #define DPRINTF(_f, _a...)           syslog(LOG_INFO, _f, ##_a)
72 #define EPRINTF(_f, _a...)           syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
73 #define PERROR(_f, _a...)            EPRINTF(_f ": %s", ##_a, strerror(errno))
74 
75 #define MAX_SEGMENTS_PER_REQ         11
76 #define SECTOR_SHIFT                 9
77 #define DEFAULT_SECTOR_SIZE          512
78 
79 #define TAPDISK_DATA_REQUESTS       (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ)
80 
81 //#define BLK_NOT_ALLOCATED            (-99)
82 #define TD_NO_PARENT                 1
83 
84 #define MAX_RAMDISK_SIZE             1024000 /*500MB disk limit*/
85 
86 #define TD_OP_READ                   0
87 #define TD_OP_WRITE                  1
88 
89 #define TD_OPEN_QUIET                0x00001
90 #define TD_OPEN_QUERY                0x00002
91 #define TD_OPEN_RDONLY               0x00004
92 #define TD_OPEN_STRICT               0x00008
93 #define TD_OPEN_SHAREABLE            0x00010
94 #define TD_OPEN_ADD_CACHE            0x00020
95 #define TD_OPEN_VHD_INDEX            0x00040
96 #define TD_OPEN_LOG_DIRTY            0x00080
97 
98 #define TD_CREATE_SPARSE             0x00001
99 #define TD_CREATE_MULTITYPE          0x00002
100 
101 #define td_flag_set(word, flag)      ((word) |= (flag))
102 #define td_flag_clear(word, flag)    ((word) &= ~(flag))
103 #define td_flag_test(word, flag)     ((word) & (flag))
104 
105 typedef uint16_t                     td_uuid_t;
106 typedef uint32_t                     td_flag_t;
107 typedef uint64_t                     td_sector_t;
108 typedef struct td_disk_id            td_disk_id_t;
109 typedef struct td_disk_info          td_disk_info_t;
110 typedef struct td_request            td_request_t;
111 typedef struct td_driver_handle      td_driver_t;
112 typedef struct td_image_handle       td_image_t;
113 
114 struct td_disk_id {
115 	char                        *name;
116 	int                          drivertype;
117 };
118 
119 struct td_disk_info {
120 	td_sector_t                  size;
121         uint64_t                     sector_size;
122 	uint32_t                     info;
123 };
124 
125 struct td_request {
126 	int                          op;
127 	char                        *buf;
128 	td_sector_t                  sec;
129 	int                          secs;
130 
131 	uint8_t                      blocked; /* blocked on a dependency */
132 
133 	td_image_t                  *image;
134 
135 	void * /*td_callback_t*/     cb;
136 	void                        *cb_data;
137 
138 	uint64_t                     id;
139 	int                          sidx;
140 	void                        *private;
141 
142 #ifdef MEMSHR
143 	share_tuple_t                memshr_hnd;
144 #endif
145 };
146 
147 /*
148  * Prototype of the callback to activate as requests complete.
149  */
150 typedef void (*td_callback_t)(td_request_t, int);
151 
152 /*
153  * Structure describing the interface to a virtual disk implementation.
154  * See note at the top of this file describing this interface.
155  */
156 struct tap_disk {
157 	const char                  *disk_type;
158 	td_flag_t                    flags;
159 	int                          private_data_size;
160 	int (*td_open)               (td_driver_t *, const char *, td_flag_t);
161 	int (*td_close)              (td_driver_t *);
162 	int (*td_get_parent_id)      (td_driver_t *, td_disk_id_t *);
163 	int (*td_validate_parent)    (td_driver_t *, td_driver_t *, td_flag_t);
164 	void (*td_queue_read)        (td_driver_t *, td_request_t);
165 	void (*td_queue_write)       (td_driver_t *, td_request_t);
166 	void (*td_debug)             (td_driver_t *);
167 };
168 
169 #endif
170