1/* 2 * kernel/lvm-snap.c 3 * 4 * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE 5 * 2000 - 2002 Heinz Mauelshagen, Sistina Software 6 * 7 * LVM snapshot driver is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2, or (at your option) 10 * any later version. 11 * 12 * LVM snapshot driver is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU CC; see the file COPYING. If not, write to 19 * the Free Software Foundation, 59 Temple Place - Suite 330, 20 * Boston, MA 02111-1307, USA. 21 * 22 */ 23 24/* 25 * Changelog 26 * 27 * 05/07/2000 - implemented persistent snapshot support 28 * 23/11/2000 - used cpu_to_le64 rather than my own macro 29 * 25/01/2001 - Put LockPage back in 30 * 01/02/2001 - A dropped snapshot is now set as inactive 31 * 14/02/2001 - tidied debug statements 32 * 19/02/2001 - changed rawio calls to pass in preallocated buffer_heads 33 * 26/02/2001 - introduced __brw_kiovec to remove a lot of conditional 34 * compiles. 35 * 07/03/2001 - fixed COW exception table not persistent on 2.2 (HM) 36 * 12/03/2001 - lvm_pv_get_number changes: 37 * o made it static 38 * o renamed it to _pv_get_number 39 * o pv number is returned in new uint * arg 40 * o -1 returned on error 41 * lvm_snapshot_fill_COW_table has a return value too. 42 * 15/10/2001 - fix snapshot alignment problem [CM] 43 * - fix snapshot full oops (always check lv_block_exception) [CM] 44 * 26/06/2002 - support for new list_move macro [patch@luckynet.dynu.com] 45 * 46 */ 47 48#include <linux/kernel.h> 49#include <linux/vmalloc.h> 50#include <linux/blkdev.h> 51#include <linux/smp_lock.h> 52#include <linux/types.h> 53#include <linux/iobuf.h> 54#include <linux/lvm.h> 55#include <linux/devfs_fs_kernel.h> 56 57 58#include "lvm-internal.h" 59 60static char *lvm_snap_version __attribute__ ((unused)) = "LVM "LVM_RELEASE_NAME" snapshot code ("LVM_RELEASE_DATE")\n"; 61 62 63extern const char *const lvm_name; 64extern int lvm_blocksizes[]; 65 66void lvm_snapshot_release(lv_t *); 67 68static int _write_COW_table_block(vg_t *vg, lv_t *lv, int idx, 69 const char **reason); 70static void _disable_snapshot(vg_t *vg, lv_t *lv); 71 72 73static inline int __brw_kiovec(int rw, int nr, struct kiobuf *iovec[], 74 kdev_t dev, unsigned long b[], int size, 75 lv_t *lv) { 76 return brw_kiovec(rw, nr, iovec, dev, b, size); 77} 78 79 80static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) 81{ 82 uint p; 83 for (p = 0; p < vg->pv_max; p++) { 84 if (vg->pv[p] == NULL) 85 continue; 86 87 if (vg->pv[p]->pv_dev == rdev) 88 break; 89 } 90 91 if (p >= vg->pv_max) { 92 /* bad news, the snapshot COW table is probably corrupt */ 93 printk(KERN_ERR 94 "%s -- _pv_get_number failed for rdev = %u\n", 95 lvm_name, rdev); 96 return -1; 97 } 98 99 *pvn = vg->pv[p]->pv_number; 100 return 0; 101} 102 103 104#define hashfn(dev,block,mask,chunk_size) \ 105 ((HASHDEV(dev)^((block)/(chunk_size))) & (mask)) 106 107static inline lv_block_exception_t * 108lvm_find_exception_table(kdev_t org_dev, unsigned long org_start, lv_t * lv) 109{ 110 struct list_head * hash_table = lv->lv_snapshot_hash_table, * next; 111 unsigned long mask = lv->lv_snapshot_hash_mask; 112 int chunk_size = lv->lv_chunk_size; 113 lv_block_exception_t * ret; 114 int i = 0; 115 116 hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)]; 117 ret = NULL; 118 for (next = hash_table->next; next != hash_table; next = next->next) 119 { 120 lv_block_exception_t * exception; 121 122 exception = list_entry(next, lv_block_exception_t, hash); 123 if (exception->rsector_org == org_start && 124 exception->rdev_org == org_dev) 125 { 126 if (i) 127 { 128 /* fun, isn't it? :) */ 129#ifdef list_move 130 list_move(next, hash_table); 131#else 132 list_del(next); 133 list_add(next, hash_table); 134#endif 135 } 136 ret = exception; 137 break; 138 } 139 i++; 140 } 141 return ret; 142} 143 144inline void lvm_hash_link(lv_block_exception_t * exception, 145 kdev_t org_dev, unsigned long org_start, 146 lv_t * lv) 147{ 148 struct list_head * hash_table = lv->lv_snapshot_hash_table; 149 unsigned long mask = lv->lv_snapshot_hash_mask; 150 int chunk_size = lv->lv_chunk_size; 151 152 if (!hash_table) 153 BUG(); 154 hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)]; 155 list_add(&exception->hash, hash_table); 156} 157 158/* 159 * Determine if we already have a snapshot chunk for this block. 160 * Return: 1 if it the chunk already exists 161 * 0 if we need to COW this block and allocate a new chunk 162 * -1 if the snapshot was disabled because it ran out of space 163 * 164 * We need to be holding at least a read lock on lv->lv_lock. 165 */ 166int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector, 167 unsigned long pe_start, lv_t * lv) 168{ 169 int ret; 170 unsigned long pe_off, pe_adjustment, __org_start; 171 kdev_t __org_dev; 172 int chunk_size = lv->lv_chunk_size; 173 lv_block_exception_t * exception; 174 175 if (!lv->lv_block_exception) 176 return -1; 177 178 pe_off = pe_start % chunk_size; 179 pe_adjustment = (*org_sector-pe_off) % chunk_size; 180 __org_start = *org_sector - pe_adjustment; 181 __org_dev = *org_dev; 182 ret = 0; 183 exception = lvm_find_exception_table(__org_dev, __org_start, lv); 184 if (exception) 185 { 186 *org_dev = exception->rdev_new; 187 *org_sector = exception->rsector_new + pe_adjustment; 188 ret = 1; 189 } 190 return ret; 191} 192 193void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason) 194{ 195 kdev_t last_dev; 196 int i; 197 198 /* no exception storage space available for this snapshot 199 or error on this snapshot --> release it */ 200 invalidate_buffers(lv_snap->lv_dev); 201 202 /* wipe the snapshot since it's inconsistent now */ 203 _disable_snapshot(vg, lv_snap); 204 205 for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) { 206 if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) { 207 last_dev = lv_snap->lv_block_exception[i].rdev_new; 208 invalidate_buffers(last_dev); 209 } 210 } 211 212 lvm_snapshot_release(lv_snap); 213 lv_snap->lv_status &= ~LV_ACTIVE; 214 215 printk(KERN_INFO 216 "%s -- giving up to snapshot %s on %s: %s\n", 217 lvm_name, lv_snap->lv_snapshot_org->lv_name, lv_snap->lv_name, 218 reason); 219} 220 221static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks, 222 unsigned long start, 223 int nr_sectors, 224 int blocksize) 225{ 226 int i, sectors_per_block, nr_blocks; 227 228 sectors_per_block = blocksize / SECTOR_SIZE; 229 230 if (start & (sectors_per_block - 1)) 231 return 0; 232 233 nr_blocks = nr_sectors / sectors_per_block; 234 start /= sectors_per_block; 235 236 for (i = 0; i < nr_blocks; i++) 237 blocks[i] = start++; 238 239 return 1; 240} 241 242inline int lvm_get_blksize(kdev_t dev) 243{ 244 int correct_size = BLOCK_SIZE, i, major; 245 246 major = MAJOR(dev); 247 if (blksize_size[major]) 248 { 249 i = blksize_size[major][MINOR(dev)]; 250 if (i) 251 correct_size = i; 252 } 253 return correct_size; 254} 255 256#ifdef DEBUG_SNAPSHOT 257static inline void invalidate_snap_cache(unsigned long start, unsigned long nr, 258 kdev_t dev) 259{ 260 struct buffer_head * bh; 261 int sectors_per_block, i, blksize, minor; 262 263 minor = MINOR(dev); 264 blksize = lvm_blocksizes[minor]; 265 sectors_per_block = blksize >> 9; 266 nr /= sectors_per_block; 267 start /= sectors_per_block; 268 269 for (i = 0; i < nr; i++) 270 { 271 bh = get_hash_table(dev, start++, blksize); 272 if (bh) 273 bforget(bh); 274 } 275} 276#endif 277 278 279int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) 280{ 281 int id = 0, is = lv_snap->lv_remap_ptr; 282 ulong blksize_snap; 283 lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *) 284 page_address(lv_snap->lv_COW_table_iobuf->maplist[0]); 285 286 if (is == 0) 287 return 0; 288 289 is--; 290 blksize_snap = 291 lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new); 292 is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t)); 293 294 memset(lv_COW_table, 0, blksize_snap); 295 for ( ; is < lv_snap->lv_remap_ptr; is++, id++) { 296 /* store new COW_table entry */ 297 lv_block_exception_t *be = lv_snap->lv_block_exception + is; 298 uint pvn; 299 300 if (_pv_get_number(vg, be->rdev_org, &pvn)) 301 goto bad; 302 303 lv_COW_table[id].pv_org_number = cpu_to_le64(pvn); 304 lv_COW_table[id].pv_org_rsector = cpu_to_le64(be->rsector_org); 305 306 if (_pv_get_number(vg, be->rdev_new, &pvn)) 307 goto bad; 308 309 lv_COW_table[id].pv_snap_number = cpu_to_le64(pvn); 310 lv_COW_table[id].pv_snap_rsector = cpu_to_le64(be->rsector_new); 311 } 312 313 return 0; 314 315 bad: 316 printk(KERN_ERR "%s -- lvm_snapshot_fill_COW_page failed", lvm_name); 317 return -1; 318} 319 320 321/* 322 * writes a COW exception table sector to disk (HM) 323 * 324 * We need to hold a write lock on lv_snap->lv_lock. 325 */ 326int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap) 327{ 328 int r; 329 const char *err; 330 if((r = _write_COW_table_block(vg, lv_snap, 331 lv_snap->lv_remap_ptr - 1, &err))) 332 lvm_drop_snapshot(vg, lv_snap, err); 333 return r; 334} 335 336/* 337 * copy on write handler for one snapshot logical volume 338 * 339 * read the original blocks and store it/them on the new one(s). 340 * if there is no exception storage space free any longer --> release snapshot. 341 * 342 * this routine gets called for each _first_ write to a physical chunk. 343 * 344 * We need to hold a write lock on lv_snap->lv_lock. It is assumed that 345 * lv->lv_block_exception is non-NULL (checked by lvm_snapshot_remap_block()) 346 * when this function is called. 347 */ 348int lvm_snapshot_COW(kdev_t org_phys_dev, 349 unsigned long org_phys_sector, 350 unsigned long org_pe_start, 351 unsigned long org_virt_sector, 352 vg_t *vg, lv_t* lv_snap) 353{ 354 const char * reason; 355 unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off; 356 unsigned long phys_start; 357 int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size; 358 struct kiobuf * iobuf = lv_snap->lv_iobuf; 359 unsigned long *blocks = iobuf->blocks; 360 int blksize_snap, blksize_org, min_blksize, max_blksize; 361 int max_sectors, nr_sectors; 362 363 /* check if we are out of snapshot space */ 364 if (idx >= lv_snap->lv_remap_end) 365 goto fail_out_of_space; 366 367 /* calculate physical boundaries of source chunk */ 368 pe_off = org_pe_start % chunk_size; 369 org_start = org_phys_sector - ((org_phys_sector-pe_off) % chunk_size); 370 virt_start = org_virt_sector - (org_phys_sector - org_start); 371 372 /* calculate physical boundaries of destination chunk */ 373 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new; 374 snap_start = lv_snap->lv_block_exception[idx].rsector_new; 375 376#ifdef DEBUG_SNAPSHOT 377 printk(KERN_INFO 378 "%s -- COW: " 379 "org %s faulting %lu start %lu, snap %s start %lu, " 380 "size %d, pe_start %lu pe_off %lu, virt_sec %lu\n", 381 lvm_name, 382 kdevname(org_phys_dev), org_phys_sector, org_start, 383 kdevname(snap_phys_dev), snap_start, 384 chunk_size, 385 org_pe_start, pe_off, 386 org_virt_sector); 387#endif 388 389 blksize_org = lvm_sectsize(org_phys_dev); 390 blksize_snap = lvm_sectsize(snap_phys_dev); 391 max_blksize = max(blksize_org, blksize_snap); 392 min_blksize = min(blksize_org, blksize_snap); 393 max_sectors = KIO_MAX_SECTORS * (min_blksize>>9); 394 395 if (chunk_size % (max_blksize>>9)) 396 goto fail_blksize; 397 398 /* Don't change org_start, we need it to fill in the exception table */ 399 phys_start = org_start; 400 401 while (chunk_size) 402 { 403 nr_sectors = min(chunk_size, max_sectors); 404 chunk_size -= nr_sectors; 405 406 iobuf->length = nr_sectors << 9; 407 408 if (!lvm_snapshot_prepare_blocks(blocks, phys_start, 409 nr_sectors, blksize_org)) 410 goto fail_prepare; 411 412 if (__brw_kiovec(READ, 1, &iobuf, org_phys_dev, blocks, 413 blksize_org, lv_snap) != (nr_sectors<<9)) 414 goto fail_raw_read; 415 416 if (!lvm_snapshot_prepare_blocks(blocks, snap_start, 417 nr_sectors, blksize_snap)) 418 goto fail_prepare; 419 420 if (__brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev, blocks, 421 blksize_snap, lv_snap) != (nr_sectors<<9)) 422 goto fail_raw_write; 423 424 phys_start += nr_sectors; 425 snap_start += nr_sectors; 426 } 427 428#ifdef DEBUG_SNAPSHOT 429 /* invalidate the logical snapshot buffer cache */ 430 invalidate_snap_cache(virt_start, lv_snap->lv_chunk_size, 431 lv_snap->lv_dev); 432#endif 433 434 /* the original chunk is now stored on the snapshot volume 435 so update the execption table */ 436 lv_snap->lv_block_exception[idx].rdev_org = org_phys_dev; 437 lv_snap->lv_block_exception[idx].rsector_org = org_start; 438 439 lvm_hash_link(lv_snap->lv_block_exception + idx, 440 org_phys_dev, org_start, lv_snap); 441 lv_snap->lv_remap_ptr = idx + 1; 442 if (lv_snap->lv_snapshot_use_rate > 0) { 443 if (lv_snap->lv_remap_ptr * 100 / lv_snap->lv_remap_end >= lv_snap->lv_snapshot_use_rate) 444 wake_up_interruptible(&lv_snap->lv_snapshot_wait); 445 } 446 return 0; 447 448 /* slow path */ 449out: 450 lvm_drop_snapshot(vg, lv_snap, reason); 451 return 1; 452 453fail_out_of_space: 454 reason = "out of space"; 455 goto out; 456fail_raw_read: 457 reason = "read error"; 458 goto out; 459fail_raw_write: 460 reason = "write error"; 461 goto out; 462fail_blksize: 463 reason = "blocksize error"; 464 goto out; 465 466fail_prepare: 467 reason = "couldn't prepare kiovec blocks " 468 "(start probably isn't block aligned)"; 469 goto out; 470} 471 472int lvm_snapshot_alloc_iobuf_pages(struct kiobuf * iobuf, int sectors) 473{ 474 int bytes, nr_pages, err, i; 475 476 bytes = sectors * SECTOR_SIZE; 477 nr_pages = (bytes + ~PAGE_MASK) >> PAGE_SHIFT; 478 err = expand_kiobuf(iobuf, nr_pages); 479 if (err) goto out; 480 481 err = -ENOMEM; 482 iobuf->locked = 1; 483 iobuf->nr_pages = 0; 484 for (i = 0; i < nr_pages; i++) 485 { 486 struct page * page; 487 488 page = alloc_page(GFP_KERNEL); 489 if (!page) goto out; 490 491 iobuf->maplist[i] = page; 492 LockPage(page); 493 iobuf->nr_pages++; 494 } 495 iobuf->offset = 0; 496 497 err = 0; 498 499out: 500 return err; 501} 502 503static int calc_max_buckets(void) 504{ 505 unsigned long mem; 506 507 mem = num_physpages << PAGE_SHIFT; 508 mem /= 100; 509 mem *= 2; 510 mem /= sizeof(struct list_head); 511 512 return mem; 513} 514 515int lvm_snapshot_alloc_hash_table(lv_t * lv) 516{ 517 int err; 518 unsigned long buckets, max_buckets, size; 519 struct list_head * hash; 520 521 buckets = lv->lv_remap_end; 522 max_buckets = calc_max_buckets(); 523 buckets = min(buckets, max_buckets); 524 while (buckets & (buckets-1)) 525 buckets &= (buckets-1); 526 527 size = buckets * sizeof(struct list_head); 528 529 err = -ENOMEM; 530 hash = vmalloc(size); 531 lv->lv_snapshot_hash_table = hash; 532 533 if (!hash) 534 goto out; 535 lv->lv_snapshot_hash_table_size = size; 536 537 lv->lv_snapshot_hash_mask = buckets-1; 538 while (buckets--) 539 INIT_LIST_HEAD(hash+buckets); 540 err = 0; 541out: 542 return err; 543} 544 545int lvm_snapshot_alloc(lv_t * lv_snap) 546{ 547 int ret, max_sectors; 548 549 /* allocate kiovec to do chunk io */ 550 ret = alloc_kiovec(1, &lv_snap->lv_iobuf); 551 if (ret) goto out; 552 553 max_sectors = KIO_MAX_SECTORS << (PAGE_SHIFT-9); 554 555 ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors); 556 if (ret) goto out_free_kiovec; 557 558 /* allocate kiovec to do exception table io */ 559 ret = alloc_kiovec(1, &lv_snap->lv_COW_table_iobuf); 560 if (ret) goto out_free_kiovec; 561 562 ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_COW_table_iobuf, 563 PAGE_SIZE/SECTOR_SIZE); 564 if (ret) goto out_free_both_kiovecs; 565 566 ret = lvm_snapshot_alloc_hash_table(lv_snap); 567 if (ret) goto out_free_both_kiovecs; 568 569out: 570 return ret; 571 572out_free_both_kiovecs: 573 unmap_kiobuf(lv_snap->lv_COW_table_iobuf); 574 free_kiovec(1, &lv_snap->lv_COW_table_iobuf); 575 lv_snap->lv_COW_table_iobuf = NULL; 576 577out_free_kiovec: 578 unmap_kiobuf(lv_snap->lv_iobuf); 579 free_kiovec(1, &lv_snap->lv_iobuf); 580 lv_snap->lv_iobuf = NULL; 581 vfree(lv_snap->lv_snapshot_hash_table); 582 lv_snap->lv_snapshot_hash_table = NULL; 583 goto out; 584} 585 586void lvm_snapshot_release(lv_t * lv) 587{ 588 if (lv->lv_block_exception) 589 { 590 vfree(lv->lv_block_exception); 591 lv->lv_block_exception = NULL; 592 } 593 if (lv->lv_snapshot_hash_table) 594 { 595 vfree(lv->lv_snapshot_hash_table); 596 lv->lv_snapshot_hash_table = NULL; 597 lv->lv_snapshot_hash_table_size = 0; 598 } 599 if (lv->lv_iobuf) 600 { 601 kiobuf_wait_for_io(lv->lv_iobuf); 602 unmap_kiobuf(lv->lv_iobuf); 603 free_kiovec(1, &lv->lv_iobuf); 604 lv->lv_iobuf = NULL; 605 } 606 if (lv->lv_COW_table_iobuf) 607 { 608 kiobuf_wait_for_io(lv->lv_COW_table_iobuf); 609 unmap_kiobuf(lv->lv_COW_table_iobuf); 610 free_kiovec(1, &lv->lv_COW_table_iobuf); 611 lv->lv_COW_table_iobuf = NULL; 612 } 613} 614 615 616static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap, 617 int idx, const char **reason) { 618 int blksize_snap; 619 int end_of_table; 620 int idx_COW_table; 621 uint pvn; 622 ulong snap_pe_start, COW_table_sector_offset, 623 COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block; 624 ulong blocks[1]; 625 kdev_t snap_phys_dev; 626 lv_block_exception_t *be; 627 struct kiobuf *COW_table_iobuf = lv_snap->lv_COW_table_iobuf; 628 lv_COW_table_disk_t * lv_COW_table = 629 ( lv_COW_table_disk_t *) page_address(lv_snap->lv_COW_table_iobuf->maplist[0]); 630 631 COW_chunks_per_pe = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv_snap); 632 COW_entries_per_pe = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv_snap); 633 634 /* get physical addresse of destination chunk */ 635 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new; 636 snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size; 637 638 blksize_snap = lvm_sectsize(snap_phys_dev); 639 640 COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t); 641 idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block; 642 643 if ( idx_COW_table == 0) memset(lv_COW_table, 0, blksize_snap); 644 645 /* sector offset into the on disk COW table */ 646 COW_table_sector_offset = (idx % COW_entries_per_pe) / (SECTOR_SIZE / sizeof(lv_COW_table_disk_t)); 647 648 /* COW table block to write next */ 649 blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10); 650 651 /* store new COW_table entry */ 652 be = lv_snap->lv_block_exception + idx; 653 if(_pv_get_number(vg, be->rdev_org, &pvn)) 654 goto fail_pv_get_number; 655 656 lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(pvn); 657 lv_COW_table[idx_COW_table].pv_org_rsector = 658 cpu_to_le64(be->rsector_org); 659 if(_pv_get_number(vg, snap_phys_dev, &pvn)) 660 goto fail_pv_get_number; 661 662 lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(pvn); 663 lv_COW_table[idx_COW_table].pv_snap_rsector = 664 cpu_to_le64(be->rsector_new); 665 666 COW_table_iobuf->length = blksize_snap; 667 /* COW_table_iobuf->nr_pages = 1; */ 668 669 if (__brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev, 670 blocks, blksize_snap, lv_snap) != blksize_snap) 671 goto fail_raw_write; 672 673 /* initialization of next COW exception table block with zeroes */ 674 end_of_table = idx % COW_entries_per_pe == COW_entries_per_pe - 1; 675 if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table) 676 { 677 /* don't go beyond the end */ 678 if (idx + 1 >= lv_snap->lv_remap_end) goto out; 679 680 memset(lv_COW_table, 0, blksize_snap); 681 682 if (end_of_table) 683 { 684 idx++; 685 snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new; 686 snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size; 687 blksize_snap = lvm_sectsize(snap_phys_dev); 688 blocks[0] = snap_pe_start >> (blksize_snap >> 10); 689 } else blocks[0]++; 690 691 if (__brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev, 692 blocks, blksize_snap, lv_snap) != 693 blksize_snap) 694 goto fail_raw_write; 695 } 696 697out: 698 return 0; 699 700fail_raw_write: 701 *reason = "write error"; 702 return 1; 703 704fail_pv_get_number: 705 *reason = "_pv_get_number failed"; 706 return 1; 707} 708 709/* 710 * FIXME_1.2 711 * This function is a bit of a hack; we need to ensure that the 712 * snapshot is never made active again, because it will surely be 713 * corrupt. At the moment we do not have access to the LVM metadata 714 * from within the kernel. So we set the first exception to point to 715 * sector 1 (which will always be within the metadata, and as such 716 * invalid). User land tools will check for this when they are asked 717 * to activate the snapshot and prevent this from happening. 718 */ 719 720static void _disable_snapshot(vg_t *vg, lv_t *lv) { 721 const char *err; 722 lv->lv_block_exception[0].rsector_org = LVM_SNAPSHOT_DROPPED_SECTOR; 723 if(_write_COW_table_block(vg, lv, 0, &err) < 0) { 724 printk(KERN_ERR "%s -- couldn't disable snapshot: %s\n", 725 lvm_name, err); 726 } 727} 728