dm_target_snapshot.c revision 1.1.2.7 1 /* $NetBSD: dm_target_snapshot.c,v 1.1.2.7 2008/09/03 22:43:10 haad Exp $ */
2
3 /*
4 * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Hamsik.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * 1. Suspend my_data to temporarily stop any I/O while the snapshot is being
34 * activated.
35 * dmsetup suspend my_data
36 *
37 * 2. Create the snapshot-origin device with no table.
38 * dmsetup create my_data_org
39 *
40 * 3. Read the table from my_data and load it into my_data_org.
41 * dmsetup table my_data | dmsetup load my_data_org
42 *
43 * 4. Resume this new table.
44 * dmsetup resume my_data_org
45 *
46 * 5. Create the snapshot device with no table.
47 * dmsetup create my_data_snap
48 *
49 * 6. Load the table into my_data_snap. This uses /dev/hdd1 as the COW device and
50 * uses a 32kB chunk-size.
51 * echo "0 `blockdev --getsize /dev/mapper/my_data` snapshot \
52 * /dev/mapper/my_data_org /dev/hdd1 p 64" | dmsetup load my_data_snap
53 *
54 * 7. Reload my_data as a snapshot-origin device that points to my_data_org.
55 * echo "0 `blockdev --getsize /dev/mapper/my_data` snapshot-origin \
56 * /dev/mapper/my_data_org" | dmsetup load my_data
57 *
58 * 8. Resume the snapshot and origin devices.
59 * dmsetup resume my_data_snap
60 * dmsetup resume my_data
61 */
62
63 /*
64 * This file implements initial version of device-mapper snapshot target.
65 */
66 #include <sys/types.h>
67 #include <sys/param.h>
68
69 #include <sys/buf.h>
70 #include <sys/kmem.h>
71 #include <sys/vnode.h>
72
73 #include "dm.h"
74
75 /*
76 * Init function called from dm_table_load_ioctl.
77 * argv: /dev/mapper/my_data_org /dev/mapper/cow_dev p 64
78 * snapshot_origin device, cow device, persistent flag, chunk size
79 */
80 int
81 dm_target_snapshot_init(struct dm_dev *dmv, void **target_config, char *params)
82 {
83 struct target_snapshot_config *tsc;
84
85 char **ap, *argv[5];
86
87 /*
88 * Parse a string, containing tokens delimited by white space,
89 * into an argument vector
90 */
91 for (ap = argv; ap < &argv[4] &&
92 (*ap = strsep(¶ms, " \t")) != NULL;) {
93 if (**ap != '\0')
94 ap++;
95 }
96
97 printf("Snapshot target init function called!!\n");
98 printf("Snapshotted device: %s, cow device %s, persistent flag: %s,"
99 "chunk size: %s\n", argv[0], argv[1], argv[2], argv[3]);
100
101 if ((tsc = kmem_alloc(sizeof(struct target_snapshot_config), KM_NOSLEEP))
102 == NULL)
103 return 1;
104
105 tsc->persistent_dev = 0;
106
107 tsc->chunk_size = atoi(argv[3]);
108
109 if (strcmp(argv[2], "p") == 0)
110 tsc->persistent_dev = 1;
111
112 *target_config = tsc;
113
114
115 dmv->dev_type = DM_SNAPSHOT_DEV;
116
117 return 0;
118 }
119
120 /*
121 * Status routine is called to get params string, which is target
122 * specific. When dm_table_status_ioctl is called with flag
123 * DM_STATUS_TABLE_FLAG I have to sent params string back.
124 */
125 char *
126 dm_target_snapshot_status(void *target_config)
127 {
128 struct target_snapshot_config *tlc;
129
130 tlc = target_config;
131
132 printf("Snapshot target status function called\n");
133
134 return 0;
135 }
136
137 /* Strategy routine called from dm_strategy. */
138 int
139 dm_target_snapshot_strategy(struct dm_table_entry *table_en, struct buf *bp)
140 {
141
142 printf("Snapshot target read function called!!\n");
143
144 bp->b_error = EIO;
145 bp->b_resid = 0;
146
147 biodone(bp);
148
149 return 0;
150 }
151
152 /* Doesn't do anything here. */
153 int
154 dm_target_snapshot_destroy(struct dm_table_entry *table_en)
155 {
156 table_en->target_config = NULL;
157
158 return 0;
159 }
160
161 /* Unsupported for this target. */
162 int
163 dm_target_snapshot_upcall(struct dm_table_entry *table_en, struct buf *bp)
164 {
165 return 0;
166 }
167 /*
168 * dm target snapshot origin routines.
169 *
170 * Keep for compatibility with linux lvm2tools. They use two targets
171 * to implement snapshots. Snapshot target will implement exception
172 * store and snapshot origin will implement device which calls every
173 * snapshot device when write is done on master device.
174 */
175
176 /* Init function called from dm_table_load_ioctl. */
177 int
178 dm_target_snapshot_orig_init(struct dm_dev *dmv, void **target_config, char *argv)
179 {
180
181 printf("Snapshot_Orig target init function called!!\n");
182
183 *target_config = NULL;
184
185
186 dmv->dev_type = DM_SNAPSHOT_ORIG_DEV;
187
188 return 0;
189 }
190
191 /*
192 * Status routine is called to get params string, which is target
193 * specific. When dm_table_status_ioctl is called with flag
194 * DM_STATUS_TABLE_FLAG I have to sent params string back.
195 */
196 char *
197 dm_target_snapshot_orig_status(void *target_config)
198 {
199 struct target_snapshot_orig_config *tlc;
200
201 tlc = target_config;
202
203 printf("Snapshot_Orig target status function called\n");
204
205 return 0;
206 }
207
208 /* Strategy routine called from dm_strategy. */
209 int
210 dm_target_snapshot_orig_strategy(struct dm_table_entry *table_en, struct buf *bp)
211 {
212
213 printf("Snapshot_Orig target read function called!!\n");
214
215 bp->b_error = EIO;
216 bp->b_resid = 0;
217
218 biodone(bp);
219
220 return 0;
221 }
222
223 /* Doesn't do anything here. */
224 int
225 dm_target_snapshot_orig_destroy(struct dm_table_entry *table_en)
226 {
227 table_en->target_config = NULL;
228
229 return 0;
230 }
231
232 /* Unsupported for this target. */
233 int
234 dm_target_snapshot_orig_upcall(struct dm_table_entry *table_en, struct buf *bp)
235 {
236 return 0;
237 }
238