Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/fssnap.c
+++ new/usr/src/uts/common/io/fssnap.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 #include <sys/debug.h>
28 28 #include <sys/types.h>
29 29 #include <sys/file.h>
30 30 #include <sys/errno.h>
31 31 #include <sys/uio.h>
32 32 #include <sys/open.h>
33 33 #include <sys/cred.h>
34 34 #include <sys/kmem.h>
35 35 #include <sys/conf.h>
36 36 #include <sys/cmn_err.h>
37 37 #include <sys/modctl.h>
38 38 #include <sys/disp.h>
39 39 #include <sys/atomic.h>
40 40 #include <sys/filio.h>
41 41 #include <sys/stat.h> /* needed for S_IFBLK and S_IFCHR */
42 42 #include <sys/kstat.h>
43 43
44 44 #include <sys/ddi.h>
45 45 #include <sys/devops.h>
46 46 #include <sys/sunddi.h>
47 47 #include <sys/esunddi.h>
48 48 #include <sys/priv_names.h>
49 49
50 50 #include <sys/fssnap.h>
51 51 #include <sys/fssnap_if.h>
52 52
53 53 /*
54 54 * This module implements the file system snapshot code, which provides a
55 55 * point-in-time image of a file system for the purposes of online backup.
56 56 * There are essentially two parts to this project: the driver half and the
57 57 * file system half. The driver half is a pseudo device driver called
58 58 * "fssnap" that represents the snapshot. Each snapshot is assigned a
59 59 * number that corresponds to the minor number of the device, and a control
60 60 * device with a high minor number is used to initiate snapshot creation and
61 61 * deletion. For all practical purposes the driver half acts like a
62 62 * read-only disk device whose contents are exactly the same as the master
63 63 * file system at the time the snapshot was created.
64 64 *
65 65 * The file system half provides interfaces necessary for performing the
66 66 * file system dependent operations required to create and delete snapshots
67 67 * and a special driver strategy routine that must always be used by the file
68 68 * system for snapshots to work correctly.
69 69 *
70 70 * When a snapshot is to be created, the user utility will send an ioctl to
71 71 * the control device of the driver half specifying the file system to be
72 72 * snapshotted, the file descriptor of a backing-store file which is used to
73 73 * hold old data before it is overwritten, and other snapshot parameters.
74 74 * This ioctl is passed on to the file system specified in the original
75 75 * ioctl request. The file system is expected to be able to flush
76 76 * everything out to make the file system consistent and lock it to ensure
77 77 * no changes occur while the snapshot is being created. It then calls
78 78 * fssnap_create() to create state for a new snapshot, from which an opaque
79 79 * handle is returned with the snapshot locked. Next, the file system must
80 80 * populate the "candidate bitmap", which tells the snapshot code which
81 81 * "chunks" should be considered for copy-on-write (a chunk is the unit of
82 82 * granularity used for copy-on-write, which is independent of the device
83 83 * and file system block sizes). This is typically done by scanning the
84 84 * file system allocation bitmaps to determine which chunks contain
85 85 * allocated blocks in the file system at the time the snapshot was created.
86 86 * If a chunk has no allocated blocks, it does not need to be copied before
87 87 * being written to. Once the candidate bitmap is populated with
88 88 * fssnap_set_candidate(), the file system calls fssnap_create_done() to
89 89 * complete the snapshot creation and unlock the snapshot. The file system
90 90 * may now be unlocked and modifications to it resumed.
91 91 *
92 92 * Once a snapshot is created, the file system must perform all writes
93 93 * through a special strategy routine, fssnap_strategy(). This strategy
94 94 * routine determines whether the chunks contained by the write must be
95 95 * copied before being overwritten by consulting the candidate bitmap
96 96 * described above, and the "hastrans bitmap" which tells it whether the chunk
97 97 * has been copied already or not. If the chunk is a candidate but has not
98 98 * been copied, it reads the old data in and adds it to a queue. The
99 99 * old data can then be overwritten with the new data. An asynchronous
100 100 * task queue is dispatched for each old chunk read in which writes the old
101 101 * data to the backing file specified at snapshot creation time. The
102 102 * backing file is a sparse file the same size as the file system that
103 103 * contains the old data at the offset that data originally had in the
104 104 * file system. If the queue containing in-memory chunks gets too large,
105 105 * writes to the file system may be throttled by a semaphore until the
106 106 * task queues have a chance to push some of the chunks to the backing file.
107 107 *
108 108 * With the candidate bitmap, the hastrans bitmap, the data on the master
109 109 * file system, and the old data in memory and in the backing file, the
110 110 * snapshot pseudo-driver can piece together the original file system
111 111 * information to satisfy read requests. If the requested chunk is not a
112 112 * candidate, it returns a zeroed buffer. If the chunk is a candidate but
113 113 * has not been copied it reads it from the master file system. If it is a
114 114 * candidate and has been copied, it either copies the data from the
115 115 * in-memory queue or it reads it in from the backing file. The result is
116 116 * a replication of the original file system that can be backed up, mounted,
117 117 * or manipulated by other file system utilities that work on a read-only
118 118 * device.
119 119 *
120 120 * This module is divided into three roughly logical sections:
121 121 *
122 122 * - The snapshot driver, which is a character/block driver
123 123 * representing the snapshot itself. These routines are
124 124 * prefixed with "snap_".
125 125 *
126 126 * - The library routines that are defined in fssnap_if.h that
127 127 * are used by file systems that use this snapshot implementation.
128 128 * These functions are prefixed with "fssnap_" and are called through
129 129 * a function vector from the file system.
130 130 *
131 131 * - The helper routines used by the snapshot driver and the fssnap
132 132 * library routines for managing the translation table and other
133 133 * useful functions. These routines are all static and are
134 134 * prefixed with either "fssnap_" or "transtbl_" if they
135 135 * are specifically used for translation table activities.
136 136 */
137 137
138 138 static dev_info_t *fssnap_dip = NULL;
139 139 static struct snapshot_id *snapshot = NULL;
140 140 static struct snapshot_id snap_ctl;
141 141 static int num_snapshots = 0;
142 142 static kmutex_t snapshot_mutex;
143 143 static char snapname[] = SNAP_NAME;
144 144
145 145 /* "tunable" parameters */
146 146 static int fssnap_taskq_nthreads = FSSNAP_TASKQ_THREADS;
147 147 static uint_t fssnap_max_mem_chunks = FSSNAP_MAX_MEM_CHUNKS;
148 148 static int fssnap_taskq_maxtasks = FSSNAP_TASKQ_MAXTASKS;
149 149
150 150 /* static function prototypes */
151 151
152 152 /* snapshot driver */
153 153 static int snap_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
154 154 static int snap_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
155 155 static int snap_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
156 156 static int snap_open(dev_t *devp, int flag, int otyp, cred_t *cred);
157 157 static int snap_close(dev_t dev, int flag, int otyp, cred_t *cred);
158 158 static int snap_strategy(struct buf *bp);
159 159 static int snap_read(dev_t dev, struct uio *uiop, cred_t *credp);
160 160 static int snap_print(dev_t dev, char *str);
161 161 static int snap_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
162 162 cred_t *credp, int *rvalp);
163 163 static int snap_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
164 164 int flags, char *name, caddr_t valuep, int *lengthp);
165 165 static int snap_getchunk(struct snapshot_id *sidp, chunknumber_t chunk,
166 166 int offset, int len, char *buffer);
167 167
168 168
169 169 /* fssnap interface implementations (see fssnap_if.h) */
170 170 static void fssnap_strategy_impl(void *, struct buf *);
171 171 static void *fssnap_create_impl(chunknumber_t, uint_t, u_offset_t,
172 172 struct vnode *, int, struct vnode **, char *, u_offset_t);
173 173 static void fssnap_set_candidate_impl(void *, chunknumber_t);
174 174 static int fssnap_is_candidate_impl(void *, u_offset_t);
175 175 static int fssnap_create_done_impl(void *);
176 176 static int fssnap_delete_impl(void *);
177 177
178 178 /* fssnap interface support routines */
179 179 static int fssnap_translate(struct snapshot_id **, struct buf *);
180 180 static void fssnap_write_taskq(void *);
181 181 static void fssnap_create_kstats(snapshot_id_t *, int, const char *,
182 182 const char *);
183 183 static int fssnap_update_kstat_num(kstat_t *, int);
184 184 static void fssnap_delete_kstats(struct cow_info *);
185 185
186 186 /* translation table prototypes */
187 187 static cow_map_node_t *transtbl_add(cow_map_t *, chunknumber_t, caddr_t);
188 188 static cow_map_node_t *transtbl_get(cow_map_t *, chunknumber_t);
189 189 static void transtbl_delete(cow_map_t *, cow_map_node_t *);
190 190 static void transtbl_free(cow_map_t *);
191 191
192 192 static kstat_t *fssnap_highwater_kstat;
193 193
194 194 /* ************************************************************************ */
195 195
196 196 /* Device and Module Structures */
197 197
198 198 static struct cb_ops snap_cb_ops = {
199 199 snap_open,
200 200 snap_close,
201 201 snap_strategy,
202 202 snap_print,
203 203 nodev, /* no snap_dump */
204 204 snap_read,
205 205 nodev, /* no snap_write */
206 206 snap_ioctl,
207 207 nodev, /* no snap_devmap */
208 208 nodev, /* no snap_mmap */
209 209 nodev, /* no snap_segmap */
210 210 nochpoll,
211 211 snap_prop_op,
212 212 NULL, /* streamtab */
213 213 D_64BIT | D_NEW | D_MP, /* driver compatibility */
214 214 CB_REV,
215 215 nodev, /* async I/O read entry point */
216 216 nodev /* async I/O write entry point */
217 217 };
218 218
219 219 static struct dev_ops snap_ops = {
220 220 DEVO_REV,
221 221 0, /* ref count */
222 222 snap_getinfo,
223 223 nulldev, /* snap_identify obsolete */
224 224 nulldev, /* no snap_probe */
225 225 snap_attach,
226 226 snap_detach,
227 227 nodev, /* no snap_reset */
228 228 &snap_cb_ops,
229 229 (struct bus_ops *)NULL,
230 230 nulldev, /* no snap_power() */
231 231 ddi_quiesce_not_needed, /* quiesce */
232 232 };
233 233
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
234 234 extern struct mod_ops mod_driverops;
235 235
236 236 static struct modldrv md = {
237 237 &mod_driverops, /* Type of module. This is a driver */
238 238 "snapshot driver", /* Name of the module */
239 239 &snap_ops,
240 240 };
241 241
242 242 static struct modlinkage ml = {
243 243 MODREV_1,
244 - &md,
245 - NULL
244 + { &md, NULL }
246 245 };
247 246
248 247 static void *statep;
249 248
250 249 int
251 250 _init(void)
252 251 {
253 252 int error;
254 253 kstat_t *ksp;
255 254 kstat_named_t *ksdata;
256 255
257 256 error = ddi_soft_state_init(&statep, sizeof (struct snapshot_id *), 1);
258 257 if (error) {
259 258 cmn_err(CE_WARN, "_init: failed to init ddi_soft_state.");
260 259 return (error);
261 260 }
262 261
263 262 error = mod_install(&ml);
264 263
265 264 if (error) {
266 265 cmn_err(CE_WARN, "_init: failed to mod_install.");
267 266 ddi_soft_state_fini(&statep);
268 267 return (error);
269 268 }
270 269
271 270 /*
272 271 * Fill in the snapshot operations vector for file systems
273 272 * (defined in fssnap_if.c)
274 273 */
275 274
276 275 snapops.fssnap_create = fssnap_create_impl;
277 276 snapops.fssnap_set_candidate = fssnap_set_candidate_impl;
278 277 snapops.fssnap_is_candidate = fssnap_is_candidate_impl;
279 278 snapops.fssnap_create_done = fssnap_create_done_impl;
280 279 snapops.fssnap_delete = fssnap_delete_impl;
281 280 snapops.fssnap_strategy = fssnap_strategy_impl;
282 281
283 282 mutex_init(&snapshot_mutex, NULL, MUTEX_DEFAULT, NULL);
284 283
285 284 /*
286 285 * Initialize the fssnap highwater kstat
287 286 */
288 287 ksp = kstat_create(snapname, 0, FSSNAP_KSTAT_HIGHWATER, "misc",
289 288 KSTAT_TYPE_NAMED, 1, 0);
290 289 if (ksp != NULL) {
291 290 ksdata = (kstat_named_t *)ksp->ks_data;
292 291 kstat_named_init(ksdata, FSSNAP_KSTAT_HIGHWATER,
293 292 KSTAT_DATA_UINT32);
294 293 ksdata->value.ui32 = 0;
295 294 kstat_install(ksp);
296 295 } else {
297 296 cmn_err(CE_WARN, "_init: failed to create highwater kstat.");
298 297 }
299 298 fssnap_highwater_kstat = ksp;
300 299
301 300 return (0);
302 301 }
303 302
304 303 int
305 304 _info(struct modinfo *modinfop)
306 305 {
307 306 return (mod_info(&ml, modinfop));
308 307 }
309 308
310 309 int
311 310 _fini(void)
312 311 {
313 312 int error;
314 313
315 314 error = mod_remove(&ml);
316 315 if (error)
317 316 return (error);
318 317 ddi_soft_state_fini(&statep);
319 318
320 319 /*
321 320 * delete the fssnap highwater kstat
322 321 */
323 322 kstat_delete(fssnap_highwater_kstat);
324 323
325 324 mutex_destroy(&snapshot_mutex);
326 325
327 326 /* Clear out the file system operations vector */
328 327 snapops.fssnap_create = NULL;
329 328 snapops.fssnap_set_candidate = NULL;
330 329 snapops.fssnap_create_done = NULL;
331 330 snapops.fssnap_delete = NULL;
332 331 snapops.fssnap_strategy = NULL;
333 332
334 333 return (0);
335 334 }
336 335
337 336 /* ************************************************************************ */
338 337
339 338 /*
340 339 * Snapshot Driver Routines
341 340 *
342 341 * This section implements the snapshot character and block drivers. The
343 342 * device will appear to be a consistent read-only file system to
344 343 * applications that wish to back it up or mount it. The snapshot driver
345 344 * communicates with the file system through the translation table, which
346 345 * tells the snapshot driver where to find the data necessary to piece
347 346 * together the frozen file system. The data may either be on the master
348 347 * device (no translation exists), in memory (a translation exists but has
349 348 * not been flushed to the backing store), or in the backing store file.
350 349 * The read request may require the snapshot driver to retrieve data from
351 350 * several different places and piece it together to look like a single
352 351 * contiguous read.
353 352 *
354 353 * The device minor number corresponds to the snapshot number in the list of
355 354 * snapshot identifiers. The soft state for each minor number is simply a
356 355 * pointer to the snapshot id, which holds all of the snapshot state. One
357 356 * minor number is designated as the control device. All snapshot create
358 357 * and delete requests go through the control device to ensure this module
359 358 * is properly loaded and attached before the file system starts calling
360 359 * routines defined here.
361 360 */
362 361
363 362
364 363 /*
365 364 * snap_getinfo() - snapshot driver getinfo(9E) routine
366 365 *
367 366 */
368 367 /*ARGSUSED*/
369 368 static int
370 369 snap_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
371 370 {
372 371 switch (infocmd) {
373 372 case DDI_INFO_DEVT2DEVINFO:
374 373 *result = fssnap_dip;
375 374 return (DDI_SUCCESS);
376 375 case DDI_INFO_DEVT2INSTANCE:
377 376 *result = 0; /* we only have one instance */
378 377 return (DDI_SUCCESS);
379 378 }
380 379 return (DDI_FAILURE);
381 380 }
382 381
383 382 /*
384 383 * snap_attach() - snapshot driver attach(9E) routine
385 384 *
386 385 * sets up snapshot control device and control state. The control state
387 386 * is a pointer to an "anonymous" snapshot_id for tracking opens and closes
388 387 */
389 388 static int
390 389 snap_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
391 390 {
392 391 int error;
393 392
394 393 switch (cmd) {
395 394 case DDI_ATTACH:
396 395 /* create the control device */
397 396 error = ddi_create_priv_minor_node(dip, SNAP_CTL_NODE, S_IFCHR,
398 397 SNAP_CTL_MINOR, DDI_PSEUDO, PRIVONLY_DEV,
399 398 PRIV_SYS_CONFIG, PRIV_SYS_CONFIG, 0666);
400 399 if (error == DDI_FAILURE) {
401 400 return (DDI_FAILURE);
402 401 }
403 402
404 403 rw_init(&snap_ctl.sid_rwlock, NULL, RW_DEFAULT, NULL);
405 404 rw_enter(&snap_ctl.sid_rwlock, RW_WRITER);
406 405 fssnap_dip = dip;
407 406 snap_ctl.sid_snapnumber = SNAP_CTL_MINOR;
408 407 /* the control sid is not linked into the snapshot list */
409 408 snap_ctl.sid_next = NULL;
410 409 snap_ctl.sid_cowinfo = NULL;
411 410 snap_ctl.sid_flags = 0;
412 411 rw_exit(&snap_ctl.sid_rwlock);
413 412 ddi_report_dev(dip);
414 413
415 414 return (DDI_SUCCESS);
416 415 case DDI_PM_RESUME:
417 416 return (DDI_SUCCESS);
418 417
419 418 case DDI_RESUME:
420 419 return (DDI_SUCCESS);
421 420
422 421 default:
423 422 return (DDI_FAILURE);
424 423 }
425 424 }
426 425
427 426 /*
428 427 * snap_detach() - snapshot driver detach(9E) routine
429 428 *
430 429 * destroys snapshot control device and control state. If any snapshots
431 430 * are active (ie. num_snapshots != 0), the device will refuse to detach.
432 431 */
433 432 static int
434 433 snap_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
435 434 {
436 435 struct snapshot_id *sidp, *sidnextp;
437 436
438 437 switch (cmd) {
439 438 case DDI_DETACH:
440 439 /* do not detach if the device is active */
441 440 mutex_enter(&snapshot_mutex);
442 441 if ((num_snapshots != 0) ||
443 442 ((snap_ctl.sid_flags & SID_CHAR_BUSY) != 0)) {
444 443 mutex_exit(&snapshot_mutex);
445 444 return (DDI_FAILURE);
446 445 }
447 446
448 447 /* free up the snapshot list */
449 448 for (sidp = snapshot; sidp != NULL; sidp = sidnextp) {
450 449 ASSERT(SID_AVAILABLE(sidp) &&
451 450 !RW_LOCK_HELD(&sidp->sid_rwlock));
452 451 sidnextp = sidp->sid_next;
453 452 rw_destroy(&sidp->sid_rwlock);
454 453 kmem_free(sidp, sizeof (struct snapshot_id));
455 454 }
456 455 snapshot = NULL;
457 456
458 457 /* delete the control device */
459 458 ddi_remove_minor_node(dip, SNAP_CTL_NODE);
460 459 fssnap_dip = NULL;
461 460
462 461 ASSERT((snap_ctl.sid_flags & SID_CHAR_BUSY) == 0);
463 462 rw_destroy(&snap_ctl.sid_rwlock);
464 463 mutex_exit(&snapshot_mutex);
465 464
466 465 return (DDI_SUCCESS);
467 466
468 467 default:
469 468 return (DDI_FAILURE);
470 469 }
471 470 }
472 471
473 472 /*
474 473 * snap_open() - snapshot driver open(9E) routine
475 474 *
476 475 * marks the snapshot id as busy so it will not be recycled when deleted
477 476 * until the snapshot is closed.
478 477 */
479 478 /* ARGSUSED */
480 479 static int
481 480 snap_open(dev_t *devp, int flag, int otyp, cred_t *cred)
482 481 {
483 482 minor_t minor;
484 483 struct snapshot_id **sidpp, *sidp;
485 484
486 485 /* snapshots are read-only */
487 486 if (flag & FWRITE)
488 487 return (EROFS);
489 488
490 489 minor = getminor(*devp);
491 490
492 491 if (minor == SNAP_CTL_MINOR) {
493 492 /* control device must be opened exclusively */
494 493 if (((flag & FEXCL) != FEXCL) || (otyp != OTYP_CHR))
495 494 return (EINVAL);
496 495
497 496 rw_enter(&snap_ctl.sid_rwlock, RW_WRITER);
498 497 if ((snap_ctl.sid_flags & SID_CHAR_BUSY) != 0) {
499 498 rw_exit(&snap_ctl.sid_rwlock);
500 499 return (EBUSY);
501 500 }
502 501
503 502 snap_ctl.sid_flags |= SID_CHAR_BUSY;
504 503 rw_exit(&snap_ctl.sid_rwlock);
505 504
506 505 return (0);
507 506 }
508 507
509 508 sidpp = ddi_get_soft_state(statep, minor);
510 509 if (sidpp == NULL || *sidpp == NULL)
511 510 return (ENXIO);
512 511 sidp = *sidpp;
513 512 rw_enter(&sidp->sid_rwlock, RW_WRITER);
514 513
515 514 if ((flag & FEXCL) && SID_BUSY(sidp)) {
516 515 rw_exit(&sidp->sid_rwlock);
517 516 return (EAGAIN);
518 517 }
519 518
520 519 ASSERT(sidpp != NULL && sidp != NULL);
521 520 /* check to see if this snapshot has been killed on us */
522 521 if (SID_INACTIVE(sidp)) {
523 522 cmn_err(CE_WARN, "snap_open: snapshot %d does not exist.",
524 523 minor);
525 524 rw_exit(&sidp->sid_rwlock);
526 525 return (ENXIO);
527 526 }
528 527
529 528 switch (otyp) {
530 529 case OTYP_CHR:
531 530 sidp->sid_flags |= SID_CHAR_BUSY;
532 531 break;
533 532 case OTYP_BLK:
534 533 sidp->sid_flags |= SID_BLOCK_BUSY;
535 534 break;
536 535 default:
537 536 rw_exit(&sidp->sid_rwlock);
538 537 return (EINVAL);
539 538 }
540 539
541 540 rw_exit(&sidp->sid_rwlock);
542 541
543 542 /*
544 543 * at this point if a valid snapshot was found then it has
545 544 * been marked busy and we can use it.
546 545 */
547 546 return (0);
548 547 }
549 548
550 549 /*
551 550 * snap_close() - snapshot driver close(9E) routine
552 551 *
553 552 * unsets the busy bits in the snapshot id. If the snapshot has been
554 553 * deleted while the snapshot device was open, the close call will clean
555 554 * up the remaining state information.
556 555 */
557 556 /* ARGSUSED */
558 557 static int
559 558 snap_close(dev_t dev, int flag, int otyp, cred_t *cred)
560 559 {
561 560 struct snapshot_id **sidpp, *sidp;
562 561 minor_t minor;
563 562 char name[20];
564 563
565 564 minor = getminor(dev);
566 565
567 566 /* if this is the control device, close it and return */
568 567 if (minor == SNAP_CTL_MINOR) {
569 568 rw_enter(&snap_ctl.sid_rwlock, RW_WRITER);
570 569 snap_ctl.sid_flags &= ~(SID_CHAR_BUSY);
571 570 rw_exit(&snap_ctl.sid_rwlock);
572 571 return (0);
573 572 }
574 573
575 574 sidpp = ddi_get_soft_state(statep, minor);
576 575 if (sidpp == NULL || *sidpp == NULL) {
577 576 cmn_err(CE_WARN, "snap_close: could not find state for "
578 577 "snapshot %d.", minor);
579 578 return (ENXIO);
580 579 }
581 580 sidp = *sidpp;
582 581 mutex_enter(&snapshot_mutex);
583 582 rw_enter(&sidp->sid_rwlock, RW_WRITER);
584 583
585 584 /* Mark the snapshot as not being busy anymore */
586 585 switch (otyp) {
587 586 case OTYP_CHR:
588 587 sidp->sid_flags &= ~(SID_CHAR_BUSY);
589 588 break;
590 589 case OTYP_BLK:
591 590 sidp->sid_flags &= ~(SID_BLOCK_BUSY);
592 591 break;
593 592 default:
594 593 mutex_exit(&snapshot_mutex);
595 594 rw_exit(&sidp->sid_rwlock);
596 595 return (EINVAL);
597 596 }
598 597
599 598 if (SID_AVAILABLE(sidp)) {
600 599 /*
601 600 * if this is the last close on a snapshot that has been
602 601 * deleted, then free up the soft state. The snapdelete
603 602 * ioctl does not free this when the device is in use so
604 603 * we do it here after the last reference goes away.
605 604 */
606 605
607 606 /* remove the device nodes */
608 607 ASSERT(fssnap_dip != NULL);
609 608 (void) snprintf(name, sizeof (name), "%d",
610 609 sidp->sid_snapnumber);
611 610 ddi_remove_minor_node(fssnap_dip, name);
612 611 (void) snprintf(name, sizeof (name), "%d,raw",
613 612 sidp->sid_snapnumber);
614 613 ddi_remove_minor_node(fssnap_dip, name);
615 614
616 615 /* delete the state structure */
617 616 ddi_soft_state_free(statep, sidp->sid_snapnumber);
618 617 num_snapshots--;
619 618 }
620 619
621 620 mutex_exit(&snapshot_mutex);
622 621 rw_exit(&sidp->sid_rwlock);
623 622
624 623 return (0);
625 624 }
626 625
627 626 /*
628 627 * snap_read() - snapshot driver read(9E) routine
629 628 *
630 629 * reads data from the snapshot by calling snap_strategy() through physio()
631 630 */
632 631 /* ARGSUSED */
633 632 static int
634 633 snap_read(dev_t dev, struct uio *uiop, cred_t *credp)
635 634 {
636 635 minor_t minor;
637 636 struct snapshot_id **sidpp;
638 637
639 638 minor = getminor(dev);
640 639 sidpp = ddi_get_soft_state(statep, minor);
641 640 if (sidpp == NULL || *sidpp == NULL) {
642 641 cmn_err(CE_WARN,
643 642 "snap_read: could not find state for snapshot %d.", minor);
644 643 return (ENXIO);
645 644 }
646 645 return (physio(snap_strategy, NULL, dev, B_READ, minphys, uiop));
647 646 }
648 647
649 648 /*
650 649 * snap_strategy() - snapshot driver strategy(9E) routine
651 650 *
652 651 * cycles through each chunk in the requested buffer and calls
653 652 * snap_getchunk() on each chunk to retrieve it from the appropriate
654 653 * place. Once all of the parts are put together the requested buffer
655 654 * is returned. The snapshot driver is read-only, so a write is invalid.
656 655 */
657 656 static int
658 657 snap_strategy(struct buf *bp)
659 658 {
660 659 struct snapshot_id **sidpp, *sidp;
661 660 minor_t minor;
662 661 chunknumber_t chunk;
663 662 int off, len;
664 663 u_longlong_t reqptr;
665 664 int error = 0;
666 665 size_t chunksz;
667 666 caddr_t buf;
668 667
669 668 /* snapshot device is read-only */
670 669 if (bp->b_flags & B_WRITE) {
671 670 bioerror(bp, EROFS);
672 671 bp->b_resid = bp->b_bcount;
673 672 biodone(bp);
674 673 return (0);
675 674 }
676 675
677 676 minor = getminor(bp->b_edev);
678 677 sidpp = ddi_get_soft_state(statep, minor);
679 678 if (sidpp == NULL || *sidpp == NULL) {
680 679 cmn_err(CE_WARN,
681 680 "snap_strategy: could not find state for snapshot %d.",
682 681 minor);
683 682 bioerror(bp, ENXIO);
684 683 bp->b_resid = bp->b_bcount;
685 684 biodone(bp);
686 685 return (0);
687 686 }
688 687 sidp = *sidpp;
689 688 ASSERT(sidp);
690 689 rw_enter(&sidp->sid_rwlock, RW_READER);
691 690
692 691 if (SID_INACTIVE(sidp)) {
693 692 bioerror(bp, ENXIO);
694 693 bp->b_resid = bp->b_bcount;
695 694 biodone(bp);
696 695 rw_exit(&sidp->sid_rwlock);
697 696 return (0);
698 697 }
699 698
700 699 if (bp->b_flags & (B_PAGEIO|B_PHYS))
701 700 bp_mapin(bp);
702 701
703 702 bp->b_resid = bp->b_bcount;
704 703 ASSERT(bp->b_un.b_addr);
705 704 buf = bp->b_un.b_addr;
706 705
707 706 chunksz = sidp->sid_cowinfo->cow_map.cmap_chunksz;
708 707
709 708 /* reqptr is the current DEV_BSIZE offset into the device */
710 709 /* chunk is the chunk containing reqptr */
711 710 /* len is the length of the request (in the current chunk) in bytes */
712 711 /* off is the byte offset into the current chunk */
713 712 reqptr = bp->b_lblkno;
714 713 while (bp->b_resid > 0) {
715 714 chunk = dbtocowchunk(&sidp->sid_cowinfo->cow_map, reqptr);
716 715 off = (reqptr % (chunksz >> DEV_BSHIFT)) << DEV_BSHIFT;
717 716 len = min(chunksz - off, bp->b_resid);
718 717 ASSERT((off + len) <= chunksz);
719 718
720 719 if ((error = snap_getchunk(sidp, chunk, off, len, buf)) != 0) {
721 720 /*
722 721 * EINVAL means the user tried to go out of range.
723 722 * Anything else means it's likely that we're
724 723 * confused.
725 724 */
726 725 if (error != EINVAL) {
727 726 cmn_err(CE_WARN, "snap_strategy: error "
728 727 "calling snap_getchunk, chunk = %llu, "
729 728 "offset = %d, len = %d, resid = %lu, "
730 729 "error = %d.",
731 730 chunk, off, len, bp->b_resid, error);
732 731 }
733 732 bioerror(bp, error);
734 733 biodone(bp);
735 734 rw_exit(&sidp->sid_rwlock);
736 735 return (0);
737 736 }
738 737 bp->b_resid -= len;
739 738 reqptr += (len >> DEV_BSHIFT);
740 739 buf += len;
741 740 }
742 741
743 742 ASSERT(bp->b_resid == 0);
744 743 biodone(bp);
745 744
746 745 rw_exit(&sidp->sid_rwlock);
747 746 return (0);
748 747 }
749 748
750 749 /*
751 750 * snap_getchunk() - helper function for snap_strategy()
752 751 *
753 752 * gets the requested data from the appropriate place and fills in the
754 753 * buffer. chunk is the chunk number of the request, offset is the
755 754 * offset into that chunk and must be less than the chunk size. len is
756 755 * the length of the request starting at offset, and must not exceed a
757 756 * chunk boundary. buffer is the address to copy the data to. len
758 757 * bytes are copied into the buffer starting at the location specified.
759 758 *
760 759 * A chunk is located according to the following algorithm:
761 760 * - If the chunk does not have a translation or is not a candidate
762 761 * for translation, it is read straight from the master device.
763 762 * - If the chunk does have a translation, then it is either on
764 763 * disk or in memory:
765 764 * o If it is in memory the requested data is simply copied out
766 765 * of the in-memory buffer.
767 766 * o If it is in the backing store, it is read from there.
768 767 *
769 768 * This function does the real work of the snapshot driver.
770 769 */
771 770 static int
772 771 snap_getchunk(struct snapshot_id *sidp, chunknumber_t chunk, int offset,
773 772 int len, char *buffer)
774 773 {
775 774 cow_map_t *cmap = &sidp->sid_cowinfo->cow_map;
776 775 cow_map_node_t *cmn;
777 776 struct buf *snapbuf;
778 777 int error = 0;
779 778 char *newbuffer;
780 779 int newlen = 0;
781 780 int partial = 0;
782 781
783 782 ASSERT(RW_READ_HELD(&sidp->sid_rwlock));
784 783 ASSERT(offset + len <= cmap->cmap_chunksz);
785 784
786 785 /*
787 786 * Check if the chunk number is out of range and if so bail out
788 787 */
789 788 if (chunk >= (cmap->cmap_bmsize * NBBY)) {
790 789 return (EINVAL);
791 790 }
792 791
793 792 /*
794 793 * If the chunk is not a candidate for translation, then the chunk
795 794 * was not allocated when the snapshot was taken. Since it does
796 795 * not contain data associated with this snapshot, just return a
797 796 * zero buffer instead.
798 797 */
799 798 if (isclr(cmap->cmap_candidate, chunk)) {
800 799 bzero(buffer, len);
801 800 return (0);
802 801 }
803 802
804 803 /*
805 804 * if the chunk is a candidate for translation but a
806 805 * translation does not exist, then read through to the
807 806 * original file system. The rwlock is held until the read
808 807 * completes if it hasn't been translated to make sure the
809 808 * file system does not translate the block before we
810 809 * access it. If it has already been translated we don't
811 810 * need the lock, because the translation will never go away.
812 811 */
813 812 rw_enter(&cmap->cmap_rwlock, RW_READER);
814 813 if (isclr(cmap->cmap_hastrans, chunk)) {
815 814 snapbuf = getrbuf(KM_SLEEP);
816 815 /*
817 816 * Reading into the buffer saves having to do a copy,
818 817 * but gets tricky if the request size is not a
819 818 * multiple of DEV_BSIZE. However, we are filling the
820 819 * buffer left to right, so future reads will write
821 820 * over any extra data we might have read.
822 821 */
823 822
824 823 partial = len % DEV_BSIZE;
825 824
826 825 snapbuf->b_bcount = len;
827 826 snapbuf->b_lblkno = lbtodb(chunk * cmap->cmap_chunksz + offset);
828 827 snapbuf->b_un.b_addr = buffer;
829 828
830 829 snapbuf->b_iodone = NULL;
831 830 snapbuf->b_proc = NULL; /* i.e. the kernel */
832 831 snapbuf->b_flags = B_READ | B_BUSY;
833 832 snapbuf->b_edev = sidp->sid_fvp->v_vfsp->vfs_dev;
834 833
835 834 if (partial) {
836 835 /*
837 836 * Partial block read in progress.
838 837 * This is bad as modules further down the line
839 838 * assume buf's are exact multiples of DEV_BSIZE
840 839 * and we end up with fewer, or zero, bytes read.
841 840 * To get round this we need to round up to the
842 841 * nearest full block read and then return only
843 842 * len bytes.
844 843 */
845 844 newlen = (len - partial) + DEV_BSIZE;
846 845 newbuffer = kmem_alloc(newlen, KM_SLEEP);
847 846
848 847 snapbuf->b_bcount = newlen;
849 848 snapbuf->b_un.b_addr = newbuffer;
850 849 }
851 850
852 851 (void) bdev_strategy(snapbuf);
853 852 (void) biowait(snapbuf);
854 853
855 854 error = geterror(snapbuf);
856 855
857 856 if (partial) {
858 857 /*
859 858 * Partial block read. Now we need to bcopy the
860 859 * correct number of bytes back into the
861 860 * supplied buffer, and tidy up our temp
862 861 * buffer.
863 862 */
864 863 bcopy(newbuffer, buffer, len);
865 864 kmem_free(newbuffer, newlen);
866 865 }
867 866
868 867 freerbuf(snapbuf);
869 868 rw_exit(&cmap->cmap_rwlock);
870 869
871 870 return (error);
872 871 }
873 872
874 873 /*
875 874 * finally, if the chunk is a candidate for translation and it
876 875 * has been translated, then we clone the chunk of the buffer
877 876 * that was copied aside by the file system.
878 877 * The cmap_rwlock does not need to be held after we know the
879 878 * data has already been copied. Once a chunk has been copied
880 879 * to the backing file, it is stable read only data.
881 880 */
882 881 cmn = transtbl_get(cmap, chunk);
883 882
884 883 /* check whether the data is in memory or in the backing file */
885 884 if (cmn != NULL) {
886 885 ASSERT(cmn->cmn_buf);
887 886 /* already in memory */
888 887 bcopy(cmn->cmn_buf + offset, buffer, len);
889 888 rw_exit(&cmap->cmap_rwlock);
890 889 } else {
891 890 ssize_t resid = len;
892 891 int bf_index;
893 892 /*
894 893 * can cause deadlock with writer if we don't drop the
895 894 * cmap_rwlock before trying to get the backing store file
896 895 * vnode rwlock.
897 896 */
898 897 rw_exit(&cmap->cmap_rwlock);
899 898
900 899 bf_index = chunk / cmap->cmap_chunksperbf;
901 900
902 901 /* read buffer from backing file */
903 902 error = vn_rdwr(UIO_READ,
904 903 (sidp->sid_cowinfo->cow_backfile_array)[bf_index],
905 904 buffer, len, ((chunk % cmap->cmap_chunksperbf) *
906 905 cmap->cmap_chunksz) + offset, UIO_SYSSPACE, 0,
907 906 RLIM64_INFINITY, kcred, &resid);
908 907 }
909 908
910 909 return (error);
911 910 }
912 911
913 912 /*
914 913 * snap_print() - snapshot driver print(9E) routine
915 914 *
916 915 * prints the device identification string.
917 916 */
918 917 static int
919 918 snap_print(dev_t dev, char *str)
920 919 {
921 920 struct snapshot_id **sidpp;
922 921 minor_t minor;
923 922
924 923 minor = getminor(dev);
925 924 sidpp = ddi_get_soft_state(statep, minor);
926 925 if (sidpp == NULL || *sidpp == NULL) {
927 926 cmn_err(CE_WARN,
928 927 "snap_print: could not find state for snapshot %d.", minor);
929 928 return (ENXIO);
930 929 }
931 930
932 931 cmn_err(CE_NOTE, "snap_print: snapshot %d: %s", minor, str);
933 932
934 933 return (0);
935 934 }
936 935
937 936 /*
938 937 * snap_prop_op() - snapshot driver prop_op(9E) routine
939 938 *
940 939 * get 32-bit and 64-bit values for size (character driver) and nblocks
941 940 * (block driver).
942 941 */
943 942 static int
944 943 snap_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
945 944 int flags, char *name, caddr_t valuep, int *lengthp)
946 945 {
947 946 int minor;
948 947 struct snapshot_id **sidpp;
949 948 dev_t mdev;
950 949 dev_info_t *mdip;
951 950 int error;
952 951
953 952 minor = getminor(dev);
954 953
955 954 /*
956 955 * If this is the control device just check for .conf properties,
957 956 * if the wildcard DDI_DEV_T_ANY was passed in via the dev_t
958 957 * just fall back to the defaults.
959 958 */
960 959 if ((minor == SNAP_CTL_MINOR) || (dev == DDI_DEV_T_ANY))
961 960 return (ddi_prop_op(dev, dip, prop_op, flags, name,
962 961 valuep, lengthp));
963 962
964 963 /* check to see if there is a master device plumbed */
965 964 sidpp = ddi_get_soft_state(statep, minor);
966 965 if (sidpp == NULL || *sidpp == NULL) {
967 966 cmn_err(CE_WARN,
968 967 "snap_prop_op: could not find state for "
969 968 "snapshot %d.", minor);
970 969 return (DDI_PROP_NOT_FOUND);
971 970 }
972 971
973 972 if (((*sidpp)->sid_fvp == NULL) || ((*sidpp)->sid_fvp->v_vfsp == NULL))
974 973 return (ddi_prop_op(dev, dip, prop_op, flags, name,
975 974 valuep, lengthp));
976 975
977 976 /* hold master device and pass operation down */
978 977 mdev = (*sidpp)->sid_fvp->v_vfsp->vfs_dev;
979 978 if (mdip = e_ddi_hold_devi_by_dev(mdev, 0)) {
980 979
981 980 /* get size information from the master device. */
982 981 error = cdev_prop_op(mdev, mdip,
983 982 prop_op, flags, name, valuep, lengthp);
984 983 ddi_release_devi(mdip);
985 984 if (error == DDI_PROP_SUCCESS)
986 985 return (error);
987 986 }
988 987
989 988 /* master device did not service the request, try framework */
990 989 return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp));
991 990
992 991 }
993 992
994 993 /*
995 994 * snap_ioctl() - snapshot driver ioctl(9E) routine
996 995 *
997 996 * only applies to the control device. The control device accepts two
998 997 * ioctl requests: create a snapshot or delete a snapshot. In either
999 998 * case, the vnode for the requested file system is extracted, and the
1000 999 * request is passed on to the file system via the same ioctl. The file
1001 1000 * system is responsible for doing the things necessary for creating or
1002 1001 * destroying a snapshot, including any file system specific operations
1003 1002 * that must be performed as well as setting up and deleting the snapshot
1004 1003 * state through the fssnap interfaces.
1005 1004 */
1006 1005 static int
1007 1006 snap_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1008 1007 int *rvalp)
1009 1008 {
1010 1009 minor_t minor;
1011 1010 int error = 0;
1012 1011
1013 1012 minor = getminor(dev);
1014 1013
1015 1014 if (minor != SNAP_CTL_MINOR) {
1016 1015 return (EINVAL);
1017 1016 }
1018 1017
1019 1018 switch (cmd) {
1020 1019 case _FIOSNAPSHOTCREATE:
1021 1020 {
1022 1021 struct fiosnapcreate fc;
1023 1022 struct file *fp;
1024 1023 struct vnode *vp;
1025 1024
1026 1025 if (ddi_copyin((void *)arg, &fc, sizeof (fc), mode))
1027 1026 return (EFAULT);
1028 1027
1029 1028 /* get vnode for file system mount point */
1030 1029 if ((fp = getf(fc.rootfiledesc)) == NULL)
1031 1030 return (EBADF);
1032 1031
1033 1032 ASSERT(fp->f_vnode);
1034 1033 vp = fp->f_vnode;
1035 1034 VN_HOLD(vp);
1036 1035 releasef(fc.rootfiledesc);
1037 1036
1038 1037 /* pass ioctl request to file system */
1039 1038 error = VOP_IOCTL(vp, cmd, arg, 0, credp, rvalp, NULL);
1040 1039 VN_RELE(vp);
1041 1040 break;
1042 1041 }
1043 1042 case _FIOSNAPSHOTCREATE_MULTI:
1044 1043 {
1045 1044 struct fiosnapcreate_multi fc;
1046 1045 struct file *fp;
1047 1046 struct vnode *vp;
1048 1047
1049 1048 if (ddi_copyin((void *)arg, &fc, sizeof (fc), mode))
1050 1049 return (EFAULT);
1051 1050
1052 1051 /* get vnode for file system mount point */
1053 1052 if ((fp = getf(fc.rootfiledesc)) == NULL)
1054 1053 return (EBADF);
1055 1054
1056 1055 ASSERT(fp->f_vnode);
1057 1056 vp = fp->f_vnode;
1058 1057 VN_HOLD(vp);
1059 1058 releasef(fc.rootfiledesc);
1060 1059
1061 1060 /* pass ioctl request to file system */
1062 1061 error = VOP_IOCTL(vp, cmd, arg, 0, credp, rvalp, NULL);
1063 1062 VN_RELE(vp);
1064 1063 break;
1065 1064 }
1066 1065 case _FIOSNAPSHOTDELETE:
1067 1066 {
1068 1067 major_t major;
1069 1068 struct fiosnapdelete fc;
1070 1069 snapshot_id_t *sidp = NULL;
1071 1070 snapshot_id_t *sidnextp = NULL;
1072 1071 struct file *fp = NULL;
1073 1072 struct vnode *vp = NULL;
1074 1073 struct vfs *vfsp = NULL;
1075 1074 vfsops_t *vfsops = EIO_vfsops;
1076 1075
1077 1076 if (ddi_copyin((void *)arg, &fc, sizeof (fc), mode))
1078 1077 return (EFAULT);
1079 1078
1080 1079 /* get vnode for file system mount point */
1081 1080 if ((fp = getf(fc.rootfiledesc)) == NULL)
1082 1081 return (EBADF);
1083 1082
1084 1083 ASSERT(fp->f_vnode);
1085 1084 vp = fp->f_vnode;
1086 1085 VN_HOLD(vp);
1087 1086 releasef(fc.rootfiledesc);
1088 1087 /*
1089 1088 * Test for two formats of delete and set correct minor/vp:
1090 1089 * pseudo device:
1091 1090 * fssnap -d [/dev/fssnap/x]
1092 1091 * or
1093 1092 * mount point:
1094 1093 * fssnap -d [/mntpt]
1095 1094 * Note that minor is verified to be equal to SNAP_CTL_MINOR
1096 1095 * at this point which is an invalid minor number.
1097 1096 */
1098 1097 ASSERT(fssnap_dip != NULL);
1099 1098 major = ddi_driver_major(fssnap_dip);
1100 1099 mutex_enter(&snapshot_mutex);
1101 1100 for (sidp = snapshot; sidp != NULL; sidp = sidnextp) {
1102 1101 rw_enter(&sidp->sid_rwlock, RW_READER);
1103 1102 sidnextp = sidp->sid_next;
1104 1103 /* pseudo device: */
1105 1104 if (major == getmajor(vp->v_rdev)) {
1106 1105 minor = getminor(vp->v_rdev);
1107 1106 if (sidp->sid_snapnumber == (uint_t)minor &&
1108 1107 sidp->sid_fvp) {
1109 1108 VN_RELE(vp);
1110 1109 vp = sidp->sid_fvp;
1111 1110 VN_HOLD(vp);
1112 1111 rw_exit(&sidp->sid_rwlock);
1113 1112 break;
1114 1113 }
1115 1114 /* Mount point: */
1116 1115 } else {
1117 1116 if (sidp->sid_fvp == vp) {
1118 1117 minor = sidp->sid_snapnumber;
1119 1118 rw_exit(&sidp->sid_rwlock);
1120 1119 break;
1121 1120 }
1122 1121 }
1123 1122 rw_exit(&sidp->sid_rwlock);
1124 1123 }
1125 1124 mutex_exit(&snapshot_mutex);
1126 1125 /* Verify minor got set correctly above */
1127 1126 if (minor == SNAP_CTL_MINOR) {
1128 1127 VN_RELE(vp);
1129 1128 return (EINVAL);
1130 1129 }
1131 1130 dev = makedevice(major, minor);
1132 1131 /*
1133 1132 * Create dummy vfs entry
1134 1133 * to use as a locking semaphore across the IOCTL
1135 1134 * for mount in progress cases...
1136 1135 */
1137 1136 vfsp = vfs_alloc(KM_SLEEP);
1138 1137 VFS_INIT(vfsp, vfsops, NULL);
1139 1138 VFS_HOLD(vfsp);
1140 1139 vfs_addmip(dev, vfsp);
1141 1140 if ((vfs_devmounting(dev, vfsp)) ||
1142 1141 (vfs_devismounted(dev))) {
1143 1142 vfs_delmip(vfsp);
1144 1143 VFS_RELE(vfsp);
1145 1144 VN_RELE(vp);
1146 1145 return (EBUSY);
1147 1146 }
1148 1147 /*
1149 1148 * Nobody mounted but do not release mount in progress lock
1150 1149 * until IOCTL complete to prohibit a mount sneaking
1151 1150 * in
1152 1151 */
1153 1152 error = VOP_IOCTL(vp, cmd, arg, 0, credp, rvalp, NULL);
1154 1153 vfs_delmip(vfsp);
1155 1154 VFS_RELE(vfsp);
1156 1155 VN_RELE(vp);
1157 1156 break;
1158 1157 }
1159 1158 default:
1160 1159 cmn_err(CE_WARN, "snap_ioctl: Invalid ioctl cmd %d, minor %d.",
1161 1160 cmd, minor);
1162 1161 return (EINVAL);
1163 1162 }
1164 1163
1165 1164 return (error);
1166 1165 }
1167 1166
1168 1167
1169 1168 /* ************************************************************************ */
1170 1169
1171 1170 /*
1172 1171 * Translation Table Routines
1173 1172 *
1174 1173 * These support routines implement a simple doubly linked list
1175 1174 * to keep track of chunks that are currently in memory. The maximum
1176 1175 * size of the list is determined by the fssnap_max_mem_chunks variable.
1177 1176 * The cmap_rwlock is used to protect the linkage of the list.
1178 1177 */
1179 1178
1180 1179 /*
1181 1180 * transtbl_add() - add a node to the translation table
1182 1181 *
1183 1182 * allocates a new node and points it at the buffer passed in. The node
1184 1183 * is added to the beginning of the doubly linked list and the head of
1185 1184 * the list is moved. The cmap_rwlock must be held as a writer through
1186 1185 * this operation.
1187 1186 */
1188 1187 static cow_map_node_t *
1189 1188 transtbl_add(cow_map_t *cmap, chunknumber_t chunk, caddr_t buf)
1190 1189 {
1191 1190 cow_map_node_t *cmnode;
1192 1191
1193 1192 ASSERT(RW_WRITE_HELD(&cmap->cmap_rwlock));
1194 1193
1195 1194 cmnode = kmem_alloc(sizeof (cow_map_node_t), KM_SLEEP);
1196 1195
1197 1196 /*
1198 1197 * insert new translations at the beginning so cmn_table is always
1199 1198 * the first node.
1200 1199 */
1201 1200 cmnode->cmn_chunk = chunk;
1202 1201 cmnode->cmn_buf = buf;
1203 1202 cmnode->cmn_prev = NULL;
1204 1203 cmnode->cmn_next = cmap->cmap_table;
1205 1204 if (cmnode->cmn_next)
1206 1205 cmnode->cmn_next->cmn_prev = cmnode;
1207 1206 cmap->cmap_table = cmnode;
1208 1207
1209 1208 return (cmnode);
1210 1209 }
1211 1210
1212 1211 /*
1213 1212 * transtbl_get() - look up a node in the translation table
1214 1213 *
1215 1214 * called by the snapshot driver to find data that has been translated.
1216 1215 * The lookup is done by the chunk number, and the node is returned.
1217 1216 * If the node was not found, NULL is returned.
1218 1217 */
1219 1218 static cow_map_node_t *
1220 1219 transtbl_get(cow_map_t *cmap, chunknumber_t chunk)
1221 1220 {
1222 1221 cow_map_node_t *cmn;
1223 1222
1224 1223 ASSERT(RW_READ_HELD(&cmap->cmap_rwlock));
1225 1224 ASSERT(cmap);
1226 1225
1227 1226 /* search the translation table */
1228 1227 for (cmn = cmap->cmap_table; cmn != NULL; cmn = cmn->cmn_next) {
1229 1228 if (cmn->cmn_chunk == chunk)
1230 1229 return (cmn);
1231 1230 }
1232 1231
1233 1232 /* not found */
1234 1233 return (NULL);
1235 1234 }
1236 1235
1237 1236 /*
1238 1237 * transtbl_delete() - delete a node from the translation table
1239 1238 *
1240 1239 * called when a node's data has been written out to disk. The
1241 1240 * cmap_rwlock must be held as a writer for this operation. If the node
1242 1241 * being deleted is the head of the list, then the head is moved to the
1243 1242 * next node. Both the node's data and the node itself are freed.
1244 1243 */
1245 1244 static void
1246 1245 transtbl_delete(cow_map_t *cmap, cow_map_node_t *cmn)
1247 1246 {
1248 1247 ASSERT(RW_WRITE_HELD(&cmap->cmap_rwlock));
1249 1248 ASSERT(cmn);
1250 1249 ASSERT(cmap->cmap_table);
1251 1250
1252 1251 /* if the head of the list is being deleted, then move the head up */
1253 1252 if (cmap->cmap_table == cmn) {
1254 1253 ASSERT(cmn->cmn_prev == NULL);
1255 1254 cmap->cmap_table = cmn->cmn_next;
1256 1255 }
1257 1256
1258 1257
1259 1258 /* make previous node's next pointer skip over current node */
1260 1259 if (cmn->cmn_prev != NULL) {
1261 1260 ASSERT(cmn->cmn_prev->cmn_next == cmn);
1262 1261 cmn->cmn_prev->cmn_next = cmn->cmn_next;
1263 1262 }
1264 1263
1265 1264 /* make next node's previous pointer skip over current node */
1266 1265 if (cmn->cmn_next != NULL) {
1267 1266 ASSERT(cmn->cmn_next->cmn_prev == cmn);
1268 1267 cmn->cmn_next->cmn_prev = cmn->cmn_prev;
1269 1268 }
1270 1269
1271 1270 /* free the data and the node */
1272 1271 ASSERT(cmn->cmn_buf);
1273 1272 kmem_free(cmn->cmn_buf, cmap->cmap_chunksz);
1274 1273 kmem_free(cmn, sizeof (cow_map_node_t));
1275 1274 }
1276 1275
1277 1276 /*
1278 1277 * transtbl_free() - free the entire translation table
1279 1278 *
1280 1279 * called when the snapshot is deleted. This frees all of the nodes in
1281 1280 * the translation table (but not the bitmaps).
1282 1281 */
1283 1282 static void
1284 1283 transtbl_free(cow_map_t *cmap)
1285 1284 {
1286 1285 cow_map_node_t *curnode;
1287 1286 cow_map_node_t *tempnode;
1288 1287
1289 1288 for (curnode = cmap->cmap_table; curnode != NULL; curnode = tempnode) {
1290 1289 tempnode = curnode->cmn_next;
1291 1290
1292 1291 kmem_free(curnode->cmn_buf, cmap->cmap_chunksz);
1293 1292 kmem_free(curnode, sizeof (cow_map_node_t));
1294 1293 }
1295 1294 }
1296 1295
1297 1296
1298 1297 /* ************************************************************************ */
1299 1298
1300 1299 /*
1301 1300 * Interface Implementation Routines
1302 1301 *
1303 1302 * The following functions implement snapshot interface routines that are
1304 1303 * called by the file system to create, delete, and use a snapshot. The
1305 1304 * interfaces are defined in fssnap_if.c and are filled in by this driver
1306 1305 * when it is loaded. This technique allows the file system to depend on
1307 1306 * the interface module without having to load the full implementation and
1308 1307 * snapshot device drivers.
1309 1308 */
1310 1309
1311 1310 /*
1312 1311 * fssnap_strategy_impl() - strategy routine called by the file system
1313 1312 *
1314 1313 * called by the file system to handle copy-on-write when necessary. All
1315 1314 * reads and writes that the file system performs should go through this
1316 1315 * function. If the file system calls the underlying device's strategy
1317 1316 * routine without going through fssnap_strategy() (eg. by calling
1318 1317 * bdev_strategy()), the snapshot may not be consistent.
1319 1318 *
1320 1319 * This function starts by doing significant sanity checking to insure
1321 1320 * the snapshot was not deleted out from under it or deleted and then
1322 1321 * recreated. To do this, it checks the actual pointer passed into it
1323 1322 * (ie. the handle held by the file system). NOTE that the parameter is
1324 1323 * a POINTER TO A POINTER to the snapshot id. Once the snapshot id is
1325 1324 * locked, it knows things are ok and that this snapshot is really for
1326 1325 * this file system.
1327 1326 *
1328 1327 * If the request is a write, fssnap_translate() is called to determine
1329 1328 * whether a copy-on-write is required. If it is a read, the read is
1330 1329 * simply passed on to the underlying device.
1331 1330 */
1332 1331 static void
1333 1332 fssnap_strategy_impl(void *snapshot_id, buf_t *bp)
1334 1333 {
1335 1334 struct snapshot_id **sidpp;
1336 1335 struct snapshot_id *sidp;
1337 1336 int error;
1338 1337
1339 1338 /* read requests are always passed through */
1340 1339 if (bp->b_flags & B_READ) {
1341 1340 (void) bdev_strategy(bp);
1342 1341 return;
1343 1342 }
1344 1343
1345 1344 /*
1346 1345 * Because we were not able to take the snapshot read lock BEFORE
1347 1346 * checking for a snapshot back in the file system, things may have
1348 1347 * drastically changed out from under us. For instance, the snapshot
1349 1348 * may have been deleted, deleted and recreated, or worse yet, deleted
1350 1349 * for this file system but now the snapshot number is in use by another
1351 1350 * file system.
1352 1351 *
1353 1352 * Having a pointer to the file system's snapshot id pointer allows us
1354 1353 * to sanity check most of this, though it assumes the file system is
1355 1354 * keeping track of a pointer to the snapshot_id somewhere.
1356 1355 */
1357 1356 sidpp = (struct snapshot_id **)snapshot_id;
1358 1357 sidp = *sidpp;
1359 1358
1360 1359 /*
1361 1360 * if this file system's snapshot was disabled, just pass the
1362 1361 * request through.
1363 1362 */
1364 1363 if (sidp == NULL) {
1365 1364 (void) bdev_strategy(bp);
1366 1365 return;
1367 1366 }
1368 1367
1369 1368 /*
1370 1369 * Once we have the reader lock the snapshot will not magically go
1371 1370 * away. But things may have changed on us before this so double check.
1372 1371 */
1373 1372 rw_enter(&sidp->sid_rwlock, RW_READER);
1374 1373
1375 1374 /*
1376 1375 * if an error was founds somewhere the DELETE flag will be
1377 1376 * set to indicate the snapshot should be deleted and no new
1378 1377 * translations should occur.
1379 1378 */
1380 1379 if (sidp->sid_flags & SID_DELETE) {
1381 1380 rw_exit(&sidp->sid_rwlock);
1382 1381 (void) fssnap_delete_impl(sidpp);
1383 1382 (void) bdev_strategy(bp);
1384 1383 return;
1385 1384 }
1386 1385
1387 1386 /*
1388 1387 * If the file system is no longer pointing to the snapshot we were
1389 1388 * called with, then it should not attempt to translate this buffer as
1390 1389 * it may be going to a snapshot for a different file system.
1391 1390 * Even if the file system snapshot pointer is still the same, the
1392 1391 * snapshot may have been disabled before we got the reader lock.
1393 1392 */
1394 1393 if (sidp != *sidpp || SID_INACTIVE(sidp)) {
1395 1394 rw_exit(&sidp->sid_rwlock);
1396 1395 (void) bdev_strategy(bp);
1397 1396 return;
1398 1397 }
1399 1398
1400 1399 /*
1401 1400 * At this point we're sure the snapshot will not go away while the
1402 1401 * reader lock is held, and we are reasonably certain that we are
1403 1402 * writing to the correct snapshot.
1404 1403 */
1405 1404 if ((error = fssnap_translate(sidpp, bp)) != 0) {
1406 1405 /*
1407 1406 * fssnap_translate can release the reader lock if it
1408 1407 * has to wait for a semaphore. In this case it is possible
1409 1408 * for the snapshot to be deleted in this time frame. If this
1410 1409 * happens just sent the buf thru to the filesystems device.
1411 1410 */
1412 1411 if (sidp != *sidpp || SID_INACTIVE(sidp)) {
1413 1412 rw_exit(&sidp->sid_rwlock);
1414 1413 (void) bdev_strategy(bp);
1415 1414 return;
1416 1415 }
1417 1416 bioerror(bp, error);
1418 1417 biodone(bp);
1419 1418 }
1420 1419 rw_exit(&sidp->sid_rwlock);
1421 1420 }
1422 1421
1423 1422 /*
1424 1423 * fssnap_translate() - helper function for fssnap_strategy()
1425 1424 *
1426 1425 * performs the actual copy-on-write for write requests, if required.
1427 1426 * This function does the real work of the file system side of things.
1428 1427 *
1429 1428 * It first checks the candidate bitmap to quickly determine whether any
1430 1429 * action is necessary. If the candidate bitmap indicates the chunk was
1431 1430 * allocated when the snapshot was created, then it checks to see whether
1432 1431 * a translation already exists. If a translation already exists then no
1433 1432 * action is required. If the chunk is a candidate for copy-on-write,
1434 1433 * and a translation does not already exist, then the chunk is read in
1435 1434 * and a node is added to the translation table.
1436 1435 *
1437 1436 * Once all of the chunks in the request range have been copied (if they
1438 1437 * needed to be), then the original request can be satisfied and the old
1439 1438 * data can be overwritten.
1440 1439 */
1441 1440 static int
1442 1441 fssnap_translate(struct snapshot_id **sidpp, struct buf *wbp)
1443 1442 {
1444 1443 snapshot_id_t *sidp = *sidpp;
1445 1444 struct buf *oldbp; /* buffer to store old data in */
1446 1445 struct cow_info *cowp = sidp->sid_cowinfo;
1447 1446 cow_map_t *cmap = &cowp->cow_map;
1448 1447 cow_map_node_t *cmn;
1449 1448 chunknumber_t cowchunk, startchunk, endchunk;
1450 1449 int error;
1451 1450 int throttle_write = 0;
1452 1451
1453 1452 /* make sure the snapshot is active */
1454 1453 ASSERT(RW_READ_HELD(&sidp->sid_rwlock));
1455 1454
1456 1455 startchunk = dbtocowchunk(cmap, wbp->b_lblkno);
1457 1456 endchunk = dbtocowchunk(cmap, wbp->b_lblkno +
1458 1457 ((wbp->b_bcount-1) >> DEV_BSHIFT));
1459 1458
1460 1459 /*
1461 1460 * Do not throttle the writes of the fssnap taskq thread and
1462 1461 * the log roll (trans_roll) thread. Furthermore the writes to
1463 1462 * the on-disk log are also not subject to throttling.
1464 1463 * The fssnap_write_taskq thread's write can block on the throttling
1465 1464 * semaphore which leads to self-deadlock as this same thread
1466 1465 * releases the throttling semaphore after completing the IO.
1467 1466 * If the trans_roll thread's write is throttled then we can deadlock
1468 1467 * because the fssnap_taskq_thread which releases the throttling
1469 1468 * semaphore can block waiting for log space which can only be
1470 1469 * released by the trans_roll thread.
1471 1470 */
1472 1471
1473 1472 throttle_write = !(taskq_member(cowp->cow_taskq, curthread) ||
1474 1473 tsd_get(bypass_snapshot_throttle_key));
1475 1474
1476 1475 /*
1477 1476 * Iterate through all chunks covered by this write and perform the
1478 1477 * copy-aside if necessary. Once all chunks have been safely
1479 1478 * stowed away, the new data may be written in a single sweep.
1480 1479 *
1481 1480 * For each chunk in the range, the following sequence is performed:
1482 1481 * - Is the chunk a candidate for translation?
1483 1482 * o If not, then no translation is necessary, continue
1484 1483 * - If it is a candidate, then does it already have a translation?
1485 1484 * o If so, then no translation is necessary, continue
1486 1485 * - If it is a candidate, but does not yet have a translation,
1487 1486 * then read the old data and schedule an asynchronous taskq
1488 1487 * to write the old data to the backing file.
1489 1488 *
1490 1489 * Once this has been performed over the entire range of chunks, then
1491 1490 * it is safe to overwrite the data that is there.
1492 1491 *
1493 1492 * Note that no lock is required to check the candidate bitmap because
1494 1493 * it never changes once the snapshot is created. The reader lock is
1495 1494 * taken to check the hastrans bitmap since it may change. If it
1496 1495 * turns out a copy is required, then the lock is upgraded to a
1497 1496 * writer, and the bitmap is re-checked as it may have changed while
1498 1497 * the lock was released. Finally, the write lock is held while
1499 1498 * reading the old data to make sure it is not translated out from
1500 1499 * under us.
1501 1500 *
1502 1501 * This locking mechanism should be sufficient to handle multiple
1503 1502 * threads writing to overlapping chunks simultaneously.
1504 1503 */
1505 1504 for (cowchunk = startchunk; cowchunk <= endchunk; cowchunk++) {
1506 1505 /*
1507 1506 * If the cowchunk is outside of the range of our
1508 1507 * candidate maps, then simply break out of the
1509 1508 * loop and pass the I/O through to bdev_strategy.
1510 1509 * This would occur if the file system has grown
1511 1510 * larger since the snapshot was taken.
1512 1511 */
1513 1512 if (cowchunk >= (cmap->cmap_bmsize * NBBY))
1514 1513 break;
1515 1514
1516 1515 /*
1517 1516 * If no disk blocks were allocated in this chunk when the
1518 1517 * snapshot was created then no copy-on-write will be
1519 1518 * required. Since this bitmap is read-only no locks are
1520 1519 * necessary.
1521 1520 */
1522 1521 if (isclr(cmap->cmap_candidate, cowchunk)) {
1523 1522 continue;
1524 1523 }
1525 1524
1526 1525 /*
1527 1526 * If a translation already exists, the data can be written
1528 1527 * through since the old data has already been saved off.
1529 1528 */
1530 1529 if (isset(cmap->cmap_hastrans, cowchunk)) {
1531 1530 continue;
1532 1531 }
1533 1532
1534 1533
1535 1534 /*
1536 1535 * Throttle translations if there are too many outstanding
1537 1536 * chunks in memory. The semaphore is sema_v'd by the taskq.
1538 1537 *
1539 1538 * You can't keep the sid_rwlock if you would go to sleep.
1540 1539 * This will result in deadlock when someone tries to delete
1541 1540 * the snapshot (wants the sid_rwlock as a writer, but can't
1542 1541 * get it).
1543 1542 */
1544 1543 if (throttle_write) {
1545 1544 if (sema_tryp(&cmap->cmap_throttle_sem) == 0) {
1546 1545 rw_exit(&sidp->sid_rwlock);
1547 1546 atomic_inc_32(&cmap->cmap_waiters);
1548 1547 sema_p(&cmap->cmap_throttle_sem);
1549 1548 atomic_dec_32(&cmap->cmap_waiters);
1550 1549 rw_enter(&sidp->sid_rwlock, RW_READER);
1551 1550
1552 1551 /*
1553 1552 * Now since we released the sid_rwlock the state may
1554 1553 * have transitioned underneath us. so check that again.
1555 1554 */
1556 1555 if (sidp != *sidpp || SID_INACTIVE(sidp)) {
1557 1556 sema_v(&cmap->cmap_throttle_sem);
1558 1557 return (ENXIO);
1559 1558 }
1560 1559 }
1561 1560 }
1562 1561
1563 1562 /*
1564 1563 * Acquire the lock as a writer and check to see if a
1565 1564 * translation has been added in the meantime.
1566 1565 */
1567 1566 rw_enter(&cmap->cmap_rwlock, RW_WRITER);
1568 1567 if (isset(cmap->cmap_hastrans, cowchunk)) {
1569 1568 if (throttle_write)
1570 1569 sema_v(&cmap->cmap_throttle_sem);
1571 1570 rw_exit(&cmap->cmap_rwlock);
1572 1571 continue; /* go to the next chunk */
1573 1572 }
1574 1573
1575 1574 /*
1576 1575 * read a full chunk of data from the requested offset rounded
1577 1576 * down to the nearest chunk size.
1578 1577 */
1579 1578 oldbp = getrbuf(KM_SLEEP);
1580 1579 oldbp->b_lblkno = cowchunktodb(cmap, cowchunk);
1581 1580 oldbp->b_edev = wbp->b_edev;
1582 1581 oldbp->b_bcount = cmap->cmap_chunksz;
1583 1582 oldbp->b_bufsize = cmap->cmap_chunksz;
1584 1583 oldbp->b_iodone = NULL;
1585 1584 oldbp->b_proc = NULL;
1586 1585 oldbp->b_flags = B_READ;
1587 1586 oldbp->b_un.b_addr = kmem_alloc(cmap->cmap_chunksz, KM_SLEEP);
1588 1587
1589 1588 (void) bdev_strategy(oldbp);
1590 1589 (void) biowait(oldbp);
1591 1590
1592 1591 /*
1593 1592 * It's ok to bail in the middle of translating the range
1594 1593 * because the extra copy-asides will not hurt anything
1595 1594 * (except by using extra space in the backing store).
1596 1595 */
1597 1596 if ((error = geterror(oldbp)) != 0) {
1598 1597 cmn_err(CE_WARN, "fssnap_translate: error reading "
1599 1598 "old data for snapshot %d, chunk %llu, disk block "
1600 1599 "%lld, size %lu, error %d.", sidp->sid_snapnumber,
1601 1600 cowchunk, oldbp->b_lblkno, oldbp->b_bcount, error);
1602 1601 kmem_free(oldbp->b_un.b_addr, cmap->cmap_chunksz);
1603 1602 freerbuf(oldbp);
1604 1603 rw_exit(&cmap->cmap_rwlock);
1605 1604 if (throttle_write)
1606 1605 sema_v(&cmap->cmap_throttle_sem);
1607 1606 return (error);
1608 1607 }
1609 1608
1610 1609 /*
1611 1610 * add the node to the translation table and save a reference
1612 1611 * to pass to the taskq for writing out to the backing file
1613 1612 */
1614 1613 cmn = transtbl_add(cmap, cowchunk, oldbp->b_un.b_addr);
1615 1614 freerbuf(oldbp);
1616 1615
1617 1616 /*
1618 1617 * Add a reference to the snapshot id so the lower level
1619 1618 * processing (ie. the taskq) can get back to the state
1620 1619 * information.
1621 1620 */
1622 1621 cmn->cmn_sid = sidp;
1623 1622 cmn->release_sem = throttle_write;
1624 1623 setbit(cmap->cmap_hastrans, cowchunk);
1625 1624
1626 1625 rw_exit(&cmap->cmap_rwlock);
1627 1626
1628 1627 /*
1629 1628 * schedule the asynchronous write to the backing file
1630 1629 */
1631 1630 if (cowp->cow_backfile_array != NULL)
1632 1631 (void) taskq_dispatch(cowp->cow_taskq,
1633 1632 fssnap_write_taskq, cmn, TQ_SLEEP);
1634 1633 }
1635 1634
1636 1635 /*
1637 1636 * Write new data in place of the old data. At this point all of the
1638 1637 * chunks touched by this write have been copied aside and so the new
1639 1638 * data can be written out all at once.
1640 1639 */
1641 1640 (void) bdev_strategy(wbp);
1642 1641
1643 1642 return (0);
1644 1643 }
1645 1644
1646 1645 /*
1647 1646 * fssnap_write_taskq() - write in-memory translations to the backing file
1648 1647 *
1649 1648 * writes in-memory translations to the backing file asynchronously. A
1650 1649 * task is dispatched each time a new translation is created. The task
1651 1650 * writes the data to the backing file and removes it from the memory
1652 1651 * list. The throttling semaphore is released only if the particular
1653 1652 * translation was throttled in fssnap_translate.
1654 1653 */
1655 1654 static void
1656 1655 fssnap_write_taskq(void *arg)
1657 1656 {
1658 1657 cow_map_node_t *cmn = (cow_map_node_t *)arg;
1659 1658 snapshot_id_t *sidp = cmn->cmn_sid;
1660 1659 cow_info_t *cowp = sidp->sid_cowinfo;
1661 1660 cow_map_t *cmap = &cowp->cow_map;
1662 1661 int error;
1663 1662 int bf_index;
1664 1663 int release_sem = cmn->release_sem;
1665 1664
1666 1665 /*
1667 1666 * The sid_rwlock does not need to be held here because the taskqs
1668 1667 * are destroyed explicitly by fssnap_delete (with the sid_rwlock
1669 1668 * held as a writer). taskq_destroy() will flush all of the tasks
1670 1669 * out before fssnap_delete frees up all of the structures.
1671 1670 */
1672 1671
1673 1672 /* if the snapshot was disabled from under us, drop the request. */
1674 1673 rw_enter(&sidp->sid_rwlock, RW_READER);
1675 1674 if (SID_INACTIVE(sidp)) {
1676 1675 rw_exit(&sidp->sid_rwlock);
1677 1676 if (release_sem)
1678 1677 sema_v(&cmap->cmap_throttle_sem);
1679 1678 return;
1680 1679 }
1681 1680 rw_exit(&sidp->sid_rwlock);
1682 1681
1683 1682 atomic_inc_64((uint64_t *)&cmap->cmap_nchunks);
1684 1683
1685 1684 if ((cmap->cmap_maxsize != 0) &&
1686 1685 ((cmap->cmap_nchunks * cmap->cmap_chunksz) > cmap->cmap_maxsize)) {
1687 1686 cmn_err(CE_WARN, "fssnap_write_taskq: snapshot %d (%s) has "
1688 1687 "reached the maximum backing file size specified (%llu "
1689 1688 "bytes) and will be deleted.", sidp->sid_snapnumber,
1690 1689 (char *)cowp->cow_kstat_mntpt->ks_data,
1691 1690 cmap->cmap_maxsize);
1692 1691 if (release_sem)
1693 1692 sema_v(&cmap->cmap_throttle_sem);
1694 1693 atomic_or_uint(&sidp->sid_flags, SID_DELETE);
1695 1694 return;
1696 1695 }
1697 1696
1698 1697 /* perform the write */
1699 1698 bf_index = cmn->cmn_chunk / cmap->cmap_chunksperbf;
1700 1699
1701 1700 if (error = vn_rdwr(UIO_WRITE, (cowp->cow_backfile_array)[bf_index],
1702 1701 cmn->cmn_buf, cmap->cmap_chunksz,
1703 1702 (cmn->cmn_chunk % cmap->cmap_chunksperbf) * cmap->cmap_chunksz,
1704 1703 UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, (ssize_t *)NULL)) {
1705 1704 cmn_err(CE_WARN, "fssnap_write_taskq: error writing to "
1706 1705 "backing file. DELETING SNAPSHOT %d, backing file path "
1707 1706 "%s, offset %llu bytes, error %d.", sidp->sid_snapnumber,
1708 1707 (char *)cowp->cow_kstat_bfname->ks_data,
1709 1708 cmn->cmn_chunk * cmap->cmap_chunksz, error);
1710 1709 if (release_sem)
1711 1710 sema_v(&cmap->cmap_throttle_sem);
1712 1711 atomic_or_uint(&sidp->sid_flags, SID_DELETE);
1713 1712 return;
1714 1713 }
1715 1714
1716 1715 /*
1717 1716 * now remove the node and buffer from memory
1718 1717 */
1719 1718 rw_enter(&cmap->cmap_rwlock, RW_WRITER);
1720 1719 transtbl_delete(cmap, cmn);
1721 1720 rw_exit(&cmap->cmap_rwlock);
1722 1721
1723 1722 /* Allow more translations */
1724 1723 if (release_sem)
1725 1724 sema_v(&cmap->cmap_throttle_sem);
1726 1725
1727 1726 }
1728 1727
1729 1728 /*
1730 1729 * fssnap_create_impl() - called from the file system to create a new snapshot
1731 1730 *
1732 1731 * allocates and initializes the structures needed for a new snapshot.
1733 1732 * This is called by the file system when it receives an ioctl request to
1734 1733 * create a new snapshot. An unused snapshot identifier is either found
1735 1734 * or created, and eventually returned as the opaque handle the file
1736 1735 * system will use to identify this snapshot. The snapshot number
1737 1736 * associated with the snapshot identifier is the same as the minor
1738 1737 * number for the snapshot device that is used to access that snapshot.
1739 1738 *
1740 1739 * The snapshot can not be used until the candidate bitmap is populated
1741 1740 * by the file system (see fssnap_set_candidate_impl()), and the file
1742 1741 * system finishes the setup process by calling fssnap_create_done().
1743 1742 * Nearly all of the snapshot locks are held for the duration of the
1744 1743 * create, and are not released until fssnap_create_done is called().
1745 1744 */
1746 1745 static void *
1747 1746 fssnap_create_impl(chunknumber_t nchunks, uint_t chunksz, u_offset_t maxsize,
1748 1747 struct vnode *fsvp, int backfilecount, struct vnode **bfvpp, char *backpath,
1749 1748 u_offset_t max_backfile_size)
1750 1749 {
1751 1750 refstr_t *mountpoint;
1752 1751 char taskqname[50];
1753 1752 struct cow_info *cowp;
1754 1753 struct cow_map *cmap;
1755 1754 struct snapshot_id *sidp;
1756 1755 int lastsnap;
1757 1756
1758 1757 /*
1759 1758 * Sanity check the parameters we care about
1760 1759 * (we don't care about the informational parameters)
1761 1760 */
1762 1761 if ((nchunks == 0) ||
1763 1762 ((chunksz % DEV_BSIZE) != 0) ||
1764 1763 (bfvpp == NULL)) {
1765 1764 return (NULL);
1766 1765 }
1767 1766
1768 1767 /*
1769 1768 * Look for unused snapshot identifiers. Snapshot ids are never
1770 1769 * freed, but deleted snapshot ids will be recycled as needed.
1771 1770 */
1772 1771 mutex_enter(&snapshot_mutex);
1773 1772
1774 1773 findagain:
1775 1774 lastsnap = 0;
1776 1775 for (sidp = snapshot; sidp != NULL; sidp = sidp->sid_next) {
1777 1776 if (sidp->sid_snapnumber > lastsnap)
1778 1777 lastsnap = sidp->sid_snapnumber;
1779 1778
1780 1779 /*
1781 1780 * The sid_rwlock is taken as a reader initially so that
1782 1781 * activity on each snapshot is not stalled while searching
1783 1782 * for a free snapshot id.
1784 1783 */
1785 1784 rw_enter(&sidp->sid_rwlock, RW_READER);
1786 1785
1787 1786 /*
1788 1787 * If the snapshot has been deleted and nobody is using the
1789 1788 * snapshot device than we can reuse this snapshot_id. If
1790 1789 * the snapshot is marked to be deleted (SID_DELETE), then
1791 1790 * it hasn't been deleted yet so don't reuse it.
1792 1791 */
1793 1792 if (SID_AVAILABLE(sidp))
1794 1793 break; /* This spot is unused, so take it */
1795 1794 rw_exit(&sidp->sid_rwlock);
1796 1795 }
1797 1796
1798 1797 /*
1799 1798 * add a new snapshot identifier if there are no deleted
1800 1799 * entries. Since it doesn't matter what order the entries
1801 1800 * are in we can just add it to the beginning of the list.
1802 1801 */
1803 1802 if (sidp) {
1804 1803 if (rw_tryupgrade(&sidp->sid_rwlock) == 0) {
1805 1804 /* someone else grabbed it as a writer, try again */
1806 1805 rw_exit(&sidp->sid_rwlock);
1807 1806 goto findagain;
1808 1807 }
1809 1808 } else {
1810 1809 /* Create a new node if we didn't find an unused one */
1811 1810 sidp = kmem_alloc(sizeof (struct snapshot_id), KM_SLEEP);
1812 1811 rw_init(&sidp->sid_rwlock, NULL, RW_DEFAULT, NULL);
1813 1812 rw_enter(&sidp->sid_rwlock, RW_WRITER);
1814 1813 sidp->sid_snapnumber = (snapshot == NULL) ? 0 : lastsnap + 1;
1815 1814 sidp->sid_cowinfo = NULL;
1816 1815 sidp->sid_flags = 0;
1817 1816 sidp->sid_next = snapshot;
1818 1817 snapshot = sidp;
1819 1818 }
1820 1819
1821 1820 ASSERT(RW_WRITE_HELD(&sidp->sid_rwlock));
1822 1821 ASSERT(sidp->sid_cowinfo == NULL);
1823 1822 ASSERT(sidp->sid_snapnumber <= (lastsnap + 1));
1824 1823
1825 1824 sidp->sid_flags |= SID_CREATING;
1826 1825 /* The root vnode is held until snap_delete_impl() is called */
1827 1826 VN_HOLD(fsvp);
1828 1827 sidp->sid_fvp = fsvp;
1829 1828 num_snapshots++;
1830 1829
1831 1830 /* allocate and initialize structures */
1832 1831
1833 1832 cowp = kmem_zalloc(sizeof (struct cow_info), KM_SLEEP);
1834 1833
1835 1834 cowp->cow_backfile_array = bfvpp;
1836 1835 cowp->cow_backcount = backfilecount;
1837 1836 cowp->cow_backfile_sz = max_backfile_size;
1838 1837
1839 1838 /*
1840 1839 * Initialize task queues for this snapshot. Only a small number
1841 1840 * of threads are required because they will be serialized on the
1842 1841 * backing file's reader/writer lock anyway.
1843 1842 */
1844 1843 (void) snprintf(taskqname, sizeof (taskqname), "%s_taskq_%d", snapname,
1845 1844 sidp->sid_snapnumber);
1846 1845 cowp->cow_taskq = taskq_create(taskqname, fssnap_taskq_nthreads,
1847 1846 minclsyspri, 1, fssnap_taskq_maxtasks, 0);
1848 1847
1849 1848 /* don't allow tasks to start until after everything is ready */
1850 1849 taskq_suspend(cowp->cow_taskq);
1851 1850
1852 1851 /* initialize translation table */
1853 1852 cmap = &cowp->cow_map;
1854 1853 rw_init(&cmap->cmap_rwlock, NULL, RW_DEFAULT, NULL);
1855 1854 rw_enter(&cmap->cmap_rwlock, RW_WRITER);
1856 1855
1857 1856 sema_init(&cmap->cmap_throttle_sem, fssnap_max_mem_chunks, NULL,
1858 1857 SEMA_DEFAULT, NULL);
1859 1858
1860 1859 cmap->cmap_chunksz = chunksz;
1861 1860 cmap->cmap_maxsize = maxsize;
1862 1861 cmap->cmap_chunksperbf = max_backfile_size / chunksz;
1863 1862
1864 1863 /*
1865 1864 * allocate one bit per chunk for the bitmaps, round up
1866 1865 */
1867 1866 cmap->cmap_bmsize = (nchunks + (NBBY - 1)) / NBBY;
1868 1867 cmap->cmap_hastrans = kmem_zalloc(cmap->cmap_bmsize, KM_SLEEP);
1869 1868 cmap->cmap_candidate = kmem_zalloc(cmap->cmap_bmsize, KM_SLEEP);
1870 1869
1871 1870 sidp->sid_cowinfo = cowp;
1872 1871
1873 1872 /* initialize kstats for this snapshot */
1874 1873 mountpoint = vfs_getmntpoint(fsvp->v_vfsp);
1875 1874 fssnap_create_kstats(sidp, sidp->sid_snapnumber,
1876 1875 refstr_value(mountpoint), backpath);
1877 1876 refstr_rele(mountpoint);
1878 1877
1879 1878 mutex_exit(&snapshot_mutex);
1880 1879
1881 1880 /*
1882 1881 * return with snapshot id rwlock held as a writer until
1883 1882 * fssnap_create_done is called
1884 1883 */
1885 1884 return (sidp);
1886 1885 }
1887 1886
1888 1887 /*
1889 1888 * fssnap_set_candidate_impl() - mark a chunk as a candidate for copy-on-write
1890 1889 *
1891 1890 * sets a bit in the candidate bitmap that indicates that a chunk is a
1892 1891 * candidate for copy-on-write. Typically, chunks that are allocated on
1893 1892 * the file system at the time the snapshot is taken are candidates,
1894 1893 * while chunks that have no allocated data do not need to be copied.
1895 1894 * Chunks containing metadata must be marked as candidates as well.
1896 1895 */
1897 1896 static void
1898 1897 fssnap_set_candidate_impl(void *snapshot_id, chunknumber_t chunknumber)
1899 1898 {
1900 1899 struct snapshot_id *sid = snapshot_id;
1901 1900 struct cow_info *cowp = sid->sid_cowinfo;
1902 1901 struct cow_map *cmap = &cowp->cow_map;
1903 1902
1904 1903 /* simple bitmap operation for now */
1905 1904 ASSERT(chunknumber < (cmap->cmap_bmsize * NBBY));
1906 1905 setbit(cmap->cmap_candidate, chunknumber);
1907 1906 }
1908 1907
1909 1908 /*
1910 1909 * fssnap_is_candidate_impl() - check whether a chunk is a candidate
1911 1910 *
1912 1911 * returns 0 if the chunk is not a candidate and 1 if the chunk is a
1913 1912 * candidate. This can be used by the file system to change behavior for
1914 1913 * chunks that might induce a copy-on-write. The offset is specified in
1915 1914 * bytes since the chunk size may not be known by the file system.
1916 1915 */
1917 1916 static int
1918 1917 fssnap_is_candidate_impl(void *snapshot_id, u_offset_t off)
1919 1918 {
1920 1919 struct snapshot_id *sid = snapshot_id;
1921 1920 struct cow_info *cowp = sid->sid_cowinfo;
1922 1921 struct cow_map *cmap = &cowp->cow_map;
1923 1922 ulong_t chunknumber = off / cmap->cmap_chunksz;
1924 1923
1925 1924 /* simple bitmap operation for now */
1926 1925 ASSERT(chunknumber < (cmap->cmap_bmsize * NBBY));
1927 1926 return (isset(cmap->cmap_candidate, chunknumber));
1928 1927 }
1929 1928
1930 1929 /*
1931 1930 * fssnap_create_done_impl() - complete the snapshot setup process
1932 1931 *
1933 1932 * called when the file system is done populating the candidate bitmap
1934 1933 * and it is ready to start using the snapshot. This routine releases
1935 1934 * the snapshot locks, allows taskq tasks to start processing, and
1936 1935 * creates the device minor nodes associated with the snapshot.
1937 1936 */
1938 1937 static int
1939 1938 fssnap_create_done_impl(void *snapshot_id)
1940 1939 {
1941 1940 struct snapshot_id **sidpp, *sidp = snapshot_id;
1942 1941 struct cow_info *cowp;
1943 1942 struct cow_map *cmap;
1944 1943 int snapnumber = -1;
1945 1944 char name[20];
1946 1945
1947 1946 /* sid rwlock and cmap rwlock should be taken from fssnap_create */
1948 1947 ASSERT(sidp);
1949 1948 ASSERT(RW_WRITE_HELD(&sidp->sid_rwlock));
1950 1949 ASSERT(sidp->sid_cowinfo);
1951 1950
1952 1951 cowp = sidp->sid_cowinfo;
1953 1952 cmap = &cowp->cow_map;
1954 1953
1955 1954 ASSERT(RW_WRITE_HELD(&cmap->cmap_rwlock));
1956 1955
1957 1956 sidp->sid_flags &= ~(SID_CREATING | SID_DISABLED);
1958 1957 snapnumber = sidp->sid_snapnumber;
1959 1958
1960 1959 /* allocate state structure and find new snapshot id */
1961 1960 if (ddi_soft_state_zalloc(statep, snapnumber) != DDI_SUCCESS) {
1962 1961 cmn_err(CE_WARN,
1963 1962 "snap_ioctl: create: could not allocate "
1964 1963 "state for snapshot %d.", snapnumber);
1965 1964 snapnumber = -1;
1966 1965 goto out;
1967 1966 }
1968 1967
1969 1968 sidpp = ddi_get_soft_state(statep, snapnumber);
1970 1969 *sidpp = sidp;
1971 1970
1972 1971 /* create minor node based on snapshot number */
1973 1972 ASSERT(fssnap_dip != NULL);
1974 1973 (void) snprintf(name, sizeof (name), "%d", snapnumber);
1975 1974 if (ddi_create_minor_node(fssnap_dip, name, S_IFBLK,
1976 1975 snapnumber, DDI_PSEUDO, 0) != DDI_SUCCESS) {
1977 1976 cmn_err(CE_WARN, "snap_ioctl: could not create "
1978 1977 "block minor node for snapshot %d.", snapnumber);
1979 1978 snapnumber = -1;
1980 1979 goto out;
1981 1980 }
1982 1981
1983 1982 (void) snprintf(name, sizeof (name), "%d,raw", snapnumber);
1984 1983 if (ddi_create_minor_node(fssnap_dip, name, S_IFCHR,
1985 1984 snapnumber, DDI_PSEUDO, 0) != DDI_SUCCESS) {
1986 1985 cmn_err(CE_WARN, "snap_ioctl: could not create "
1987 1986 "character minor node for snapshot %d.", snapnumber);
1988 1987 snapnumber = -1;
1989 1988 }
1990 1989
1991 1990 out:
1992 1991 rw_exit(&sidp->sid_rwlock);
1993 1992 rw_exit(&cmap->cmap_rwlock);
1994 1993
1995 1994 /* let the taskq threads start processing */
1996 1995 taskq_resume(cowp->cow_taskq);
1997 1996
1998 1997 return (snapnumber);
1999 1998 }
2000 1999
2001 2000 /*
2002 2001 * fssnap_delete_impl() - delete a snapshot
2003 2002 *
2004 2003 * used when a snapshot is no longer needed. This is called by the file
2005 2004 * system when it receives an ioctl request to delete a snapshot. It is
2006 2005 * also called internally when error conditions such as disk full, errors
2007 2006 * writing to the backing file, or backing file maxsize exceeded occur.
2008 2007 * If the snapshot device is busy when the delete request is received,
2009 2008 * all state will be deleted except for the soft state and device files
2010 2009 * associated with the snapshot; they will be deleted when the snapshot
2011 2010 * device is closed.
2012 2011 *
2013 2012 * NOTE this function takes a POINTER TO A POINTER to the snapshot id,
2014 2013 * and expects to be able to set the handle held by the file system to
2015 2014 * NULL. This depends on the file system checking that variable for NULL
2016 2015 * before calling fssnap_strategy().
2017 2016 */
2018 2017 static int
2019 2018 fssnap_delete_impl(void *snapshot_id)
2020 2019 {
2021 2020 struct snapshot_id **sidpp = (struct snapshot_id **)snapshot_id;
2022 2021 struct snapshot_id *sidp;
2023 2022 struct snapshot_id **statesidpp;
2024 2023 struct cow_info *cowp;
2025 2024 struct cow_map *cmap;
2026 2025 char name[20];
2027 2026 int snapnumber = -1;
2028 2027 vnode_t **vpp;
2029 2028
2030 2029 /*
2031 2030 * sidp is guaranteed to be valid if sidpp is valid because
2032 2031 * the snapshot list is append-only.
2033 2032 */
2034 2033 if (sidpp == NULL) {
2035 2034 return (-1);
2036 2035 }
2037 2036
2038 2037 sidp = *sidpp;
2039 2038 rw_enter(&sidp->sid_rwlock, RW_WRITER);
2040 2039
2041 2040 ASSERT(RW_WRITE_HELD(&sidp->sid_rwlock));
2042 2041
2043 2042 /*
2044 2043 * double check that the snapshot is still valid for THIS file system
2045 2044 */
2046 2045 if (*sidpp == NULL) {
2047 2046 rw_exit(&sidp->sid_rwlock);
2048 2047 return (-1);
2049 2048 }
2050 2049
2051 2050 /*
2052 2051 * Now we know the snapshot is still valid and will not go away
2053 2052 * because we have the write lock. Once the state is transitioned
2054 2053 * to "disabling", the sid_rwlock can be released. Any pending I/O
2055 2054 * waiting for the lock as a reader will check for this state and
2056 2055 * abort without touching data that may be getting freed.
2057 2056 */
2058 2057 sidp->sid_flags |= SID_DISABLING;
2059 2058 if (sidp->sid_flags & SID_DELETE) {
2060 2059 cmn_err(CE_WARN, "Snapshot %d automatically deleted.",
2061 2060 sidp->sid_snapnumber);
2062 2061 sidp->sid_flags &= ~(SID_DELETE);
2063 2062 }
2064 2063
2065 2064
2066 2065 /*
2067 2066 * This is pointing into file system specific data! The assumption is
2068 2067 * that fssnap_strategy() gets called from the file system based on
2069 2068 * whether this reference to the snapshot_id is NULL or not. So
2070 2069 * setting this to NULL should disable snapshots for the file system.
2071 2070 */
2072 2071 *sidpp = NULL;
2073 2072
2074 2073 /* remove cowinfo */
2075 2074 cowp = sidp->sid_cowinfo;
2076 2075 if (cowp == NULL) {
2077 2076 rw_exit(&sidp->sid_rwlock);
2078 2077 return (-1);
2079 2078 }
2080 2079 rw_exit(&sidp->sid_rwlock);
2081 2080
2082 2081 /* destroy task queues first so they don't reference freed data. */
2083 2082 if (cowp->cow_taskq) {
2084 2083 taskq_destroy(cowp->cow_taskq);
2085 2084 cowp->cow_taskq = NULL;
2086 2085 }
2087 2086
2088 2087 if (cowp->cow_backfile_array != NULL) {
2089 2088 for (vpp = cowp->cow_backfile_array; *vpp; vpp++)
2090 2089 VN_RELE(*vpp);
2091 2090 kmem_free(cowp->cow_backfile_array,
2092 2091 (cowp->cow_backcount + 1) * sizeof (vnode_t *));
2093 2092 cowp->cow_backfile_array = NULL;
2094 2093 }
2095 2094
2096 2095 sidp->sid_cowinfo = NULL;
2097 2096
2098 2097 /* remove cmap */
2099 2098 cmap = &cowp->cow_map;
2100 2099 ASSERT(cmap);
2101 2100
2102 2101 if (cmap->cmap_candidate)
2103 2102 kmem_free(cmap->cmap_candidate, cmap->cmap_bmsize);
2104 2103
2105 2104 if (cmap->cmap_hastrans)
2106 2105 kmem_free(cmap->cmap_hastrans, cmap->cmap_bmsize);
2107 2106
2108 2107 if (cmap->cmap_table)
2109 2108 transtbl_free(&cowp->cow_map);
2110 2109
2111 2110 rw_destroy(&cmap->cmap_rwlock);
2112 2111
2113 2112 while (cmap->cmap_waiters) {
2114 2113 sema_p(&cmap->cmap_throttle_sem);
2115 2114 sema_v(&cmap->cmap_throttle_sem);
2116 2115 }
2117 2116 sema_destroy(&cmap->cmap_throttle_sem);
2118 2117
2119 2118 /* remove kstats */
2120 2119 fssnap_delete_kstats(cowp);
2121 2120
2122 2121 kmem_free(cowp, sizeof (struct cow_info));
2123 2122
2124 2123 statesidpp = ddi_get_soft_state(statep, sidp->sid_snapnumber);
2125 2124 if (statesidpp == NULL || *statesidpp == NULL) {
2126 2125 cmn_err(CE_WARN,
2127 2126 "fssnap_delete_impl: could not find state for snapshot %d.",
2128 2127 sidp->sid_snapnumber);
2129 2128 }
2130 2129 ASSERT(*statesidpp == sidp);
2131 2130
2132 2131 /*
2133 2132 * Leave the node in the list marked DISABLED so it can be reused
2134 2133 * and avoid many race conditions. Return the snapshot number
2135 2134 * that was deleted.
2136 2135 */
2137 2136 mutex_enter(&snapshot_mutex);
2138 2137 rw_enter(&sidp->sid_rwlock, RW_WRITER);
2139 2138 sidp->sid_flags &= ~(SID_DISABLING);
2140 2139 sidp->sid_flags |= SID_DISABLED;
2141 2140 VN_RELE(sidp->sid_fvp);
2142 2141 sidp->sid_fvp = NULL;
2143 2142 snapnumber = sidp->sid_snapnumber;
2144 2143
2145 2144 /*
2146 2145 * If the snapshot is not busy, free the device info now. Otherwise
2147 2146 * the device nodes are freed in snap_close() when the device is
2148 2147 * closed. The sid will not be reused until the device is not busy.
2149 2148 */
2150 2149 if (SID_AVAILABLE(sidp)) {
2151 2150 /* remove the device nodes */
2152 2151 ASSERT(fssnap_dip != NULL);
2153 2152 (void) snprintf(name, sizeof (name), "%d",
2154 2153 sidp->sid_snapnumber);
2155 2154 ddi_remove_minor_node(fssnap_dip, name);
2156 2155 (void) snprintf(name, sizeof (name), "%d,raw",
2157 2156 sidp->sid_snapnumber);
2158 2157 ddi_remove_minor_node(fssnap_dip, name);
2159 2158
2160 2159 /* delete the state structure */
2161 2160 ddi_soft_state_free(statep, sidp->sid_snapnumber);
2162 2161 num_snapshots--;
2163 2162 }
2164 2163
2165 2164 mutex_exit(&snapshot_mutex);
2166 2165 rw_exit(&sidp->sid_rwlock);
2167 2166
2168 2167 return (snapnumber);
2169 2168 }
2170 2169
2171 2170 /*
2172 2171 * fssnap_create_kstats() - allocate and initialize snapshot kstats
2173 2172 *
2174 2173 */
2175 2174 static void
2176 2175 fssnap_create_kstats(snapshot_id_t *sidp, int snapnum,
2177 2176 const char *mountpoint, const char *backfilename)
2178 2177 {
2179 2178 kstat_t *num, *mntpoint, *bfname;
2180 2179 kstat_named_t *hw;
2181 2180 struct cow_info *cowp = sidp->sid_cowinfo;
2182 2181 struct cow_kstat_num *stats;
2183 2182
2184 2183 /* update the high water mark */
2185 2184 if (fssnap_highwater_kstat == NULL) {
2186 2185 cmn_err(CE_WARN, "fssnap_create_kstats: failed to lookup "
2187 2186 "high water mark kstat.");
2188 2187 return;
2189 2188 }
2190 2189
2191 2190 hw = (kstat_named_t *)fssnap_highwater_kstat->ks_data;
2192 2191 if (hw->value.ui32 < snapnum)
2193 2192 hw->value.ui32 = snapnum;
2194 2193
2195 2194 /* initialize the mount point kstat */
2196 2195 kstat_delete_byname(snapname, snapnum, FSSNAP_KSTAT_MNTPT);
2197 2196
2198 2197 if (mountpoint != NULL) {
2199 2198 mntpoint = kstat_create(snapname, snapnum, FSSNAP_KSTAT_MNTPT,
2200 2199 "misc", KSTAT_TYPE_RAW, strlen(mountpoint) + 1, 0);
2201 2200 if (mntpoint == NULL) {
2202 2201 cowp->cow_kstat_mntpt = NULL;
2203 2202 cmn_err(CE_WARN, "fssnap_create_kstats: failed to "
2204 2203 "create mount point kstat");
2205 2204 } else {
2206 2205 (void) strncpy(mntpoint->ks_data, mountpoint,
2207 2206 strlen(mountpoint));
2208 2207 cowp->cow_kstat_mntpt = mntpoint;
2209 2208 kstat_install(mntpoint);
2210 2209 }
2211 2210 } else {
2212 2211 cowp->cow_kstat_mntpt = NULL;
2213 2212 cmn_err(CE_WARN, "fssnap_create_kstats: mount point not "
2214 2213 "specified.");
2215 2214 }
2216 2215
2217 2216 /* initialize the backing file kstat */
2218 2217 kstat_delete_byname(snapname, snapnum, FSSNAP_KSTAT_BFNAME);
2219 2218
2220 2219 if (backfilename == NULL) {
2221 2220 cowp->cow_kstat_bfname = NULL;
2222 2221 } else {
2223 2222 bfname = kstat_create(snapname, snapnum, FSSNAP_KSTAT_BFNAME,
2224 2223 "misc", KSTAT_TYPE_RAW, strlen(backfilename) + 1, 0);
2225 2224 if (bfname != NULL) {
2226 2225 (void) strncpy(bfname->ks_data, backfilename,
2227 2226 strlen(backfilename));
2228 2227 cowp->cow_kstat_bfname = bfname;
2229 2228 kstat_install(bfname);
2230 2229 } else {
2231 2230 cowp->cow_kstat_bfname = NULL;
2232 2231 cmn_err(CE_WARN, "fssnap_create_kstats: failed to "
2233 2232 "create backing file name kstat");
2234 2233 }
2235 2234 }
2236 2235
2237 2236 /* initialize numeric kstats */
2238 2237 kstat_delete_byname(snapname, snapnum, FSSNAP_KSTAT_NUM);
2239 2238
2240 2239 num = kstat_create(snapname, snapnum, FSSNAP_KSTAT_NUM,
2241 2240 "misc", KSTAT_TYPE_NAMED,
2242 2241 sizeof (struct cow_kstat_num) / sizeof (kstat_named_t),
2243 2242 0);
2244 2243 if (num == NULL) {
2245 2244 cmn_err(CE_WARN, "fssnap_create_kstats: failed to create "
2246 2245 "numeric kstats");
2247 2246 cowp->cow_kstat_num = NULL;
2248 2247 return;
2249 2248 }
2250 2249
2251 2250 cowp->cow_kstat_num = num;
2252 2251 stats = num->ks_data;
2253 2252 num->ks_update = fssnap_update_kstat_num;
2254 2253 num->ks_private = sidp;
2255 2254
2256 2255 kstat_named_init(&stats->ckn_state, FSSNAP_KSTAT_NUM_STATE,
2257 2256 KSTAT_DATA_INT32);
2258 2257 kstat_named_init(&stats->ckn_bfsize, FSSNAP_KSTAT_NUM_BFSIZE,
2259 2258 KSTAT_DATA_UINT64);
2260 2259 kstat_named_init(&stats->ckn_maxsize, FSSNAP_KSTAT_NUM_MAXSIZE,
2261 2260 KSTAT_DATA_UINT64);
2262 2261 kstat_named_init(&stats->ckn_createtime, FSSNAP_KSTAT_NUM_CREATETIME,
2263 2262 KSTAT_DATA_LONG);
2264 2263 kstat_named_init(&stats->ckn_chunksize, FSSNAP_KSTAT_NUM_CHUNKSIZE,
2265 2264 KSTAT_DATA_UINT32);
2266 2265
2267 2266 /* initialize the static kstats */
2268 2267 stats->ckn_chunksize.value.ui32 = cowp->cow_map.cmap_chunksz;
2269 2268 stats->ckn_maxsize.value.ui64 = cowp->cow_map.cmap_maxsize;
2270 2269 stats->ckn_createtime.value.l = gethrestime_sec();
2271 2270
2272 2271 kstat_install(num);
2273 2272 }
2274 2273
2275 2274 /*
2276 2275 * fssnap_update_kstat_num() - update a numerical snapshot kstat value
2277 2276 *
2278 2277 */
2279 2278 int
2280 2279 fssnap_update_kstat_num(kstat_t *ksp, int rw)
2281 2280 {
2282 2281 snapshot_id_t *sidp = (snapshot_id_t *)ksp->ks_private;
2283 2282 struct cow_info *cowp = sidp->sid_cowinfo;
2284 2283 struct cow_kstat_num *stats = ksp->ks_data;
2285 2284
2286 2285 if (rw == KSTAT_WRITE)
2287 2286 return (EACCES);
2288 2287
2289 2288 /* state */
2290 2289 if (sidp->sid_flags & SID_CREATING)
2291 2290 stats->ckn_state.value.i32 = COWSTATE_CREATING;
2292 2291 else if (SID_INACTIVE(sidp))
2293 2292 stats->ckn_state.value.i32 = COWSTATE_DISABLED;
2294 2293 else if (SID_BUSY(sidp))
2295 2294 stats->ckn_state.value.i32 = COWSTATE_ACTIVE;
2296 2295 else
2297 2296 stats->ckn_state.value.i32 = COWSTATE_IDLE;
2298 2297
2299 2298 /* bfsize */
2300 2299 stats->ckn_bfsize.value.ui64 = cowp->cow_map.cmap_nchunks *
2301 2300 cowp->cow_map.cmap_chunksz;
2302 2301
2303 2302 return (0);
2304 2303 }
2305 2304
2306 2305 /*
2307 2306 * fssnap_delete_kstats() - deallocate snapshot kstats
2308 2307 *
2309 2308 */
2310 2309 void
2311 2310 fssnap_delete_kstats(struct cow_info *cowp)
2312 2311 {
2313 2312 if (cowp->cow_kstat_num != NULL) {
2314 2313 kstat_delete(cowp->cow_kstat_num);
2315 2314 cowp->cow_kstat_num = NULL;
2316 2315 }
2317 2316 if (cowp->cow_kstat_mntpt != NULL) {
2318 2317 kstat_delete(cowp->cow_kstat_mntpt);
2319 2318 cowp->cow_kstat_mntpt = NULL;
2320 2319 }
2321 2320 if (cowp->cow_kstat_bfname != NULL) {
2322 2321 kstat_delete(cowp->cow_kstat_bfname);
2323 2322 cowp->cow_kstat_bfname = NULL;
2324 2323 }
2325 2324 }
↓ open down ↓ |
2070 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX