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