lvm-snap.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:19k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * kernel/lvm-snap.c
  3.  *
  4.  * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
  5.  *                    Heinz Mauelshagen, Sistina Software (persistent snapshots)
  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.  * Changelog
  25.  *
  26.  *    05/07/2000 - implemented persistent snapshot support
  27.  *    23/11/2000 - used cpu_to_le64 rather than my own macro
  28.  *    25/01/2001 - Put LockPage back in
  29.  *    01/02/2001 - A dropped snapshot is now set as inactive
  30.  *    12/03/2001 - lvm_pv_get_number changes:
  31.  *                 o made it static
  32.  *                 o renamed it to _pv_get_number
  33.  *                 o pv number is returned in new uint * arg
  34.  *                 o -1 returned on error
  35.  *                 lvm_snapshot_fill_COW_table has a return value too.
  36.  *
  37.  */
  38. #include <linux/kernel.h>
  39. #include <linux/module.h>
  40. #include <linux/vmalloc.h>
  41. #include <linux/blkdev.h>
  42. #include <linux/smp_lock.h>
  43. #include <linux/types.h>
  44. #include <linux/iobuf.h>
  45. #include <linux/lvm.h>
  46. #include "lvm-internal.h"
  47. static char *lvm_snap_version __attribute__ ((unused)) =
  48.    "LVM "LVM_RELEASE_NAME" snapshot code ("LVM_RELEASE_DATE")n";
  49. extern const char *const lvm_name;
  50. extern int lvm_blocksizes[];
  51. void lvm_snapshot_release(lv_t *);
  52. static int _write_COW_table_block(vg_t *vg, lv_t *lv, int idx,
  53.                                  const char **reason);
  54. static void _disable_snapshot(vg_t *vg, lv_t *lv);
  55. static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) {
  56. uint p;
  57. for(p = 0; p < vg->pv_max; p++) {
  58. if(vg->pv[p] == NULL)
  59. continue;
  60. if(vg->pv[p]->pv_dev == rdev)
  61. break;
  62. }
  63.   if(p >= vg->pv_max) {
  64. /* bad news, the snapshot COW table is probably corrupt */
  65. printk(KERN_ERR
  66.        "%s -- _pv_get_number failed for rdev = %un",
  67.        lvm_name, rdev);
  68. return -1;
  69. }
  70. *pvn = vg->pv[p]->pv_number;
  71. return 0;
  72. }
  73. #define hashfn(dev,block,mask,chunk_size) 
  74. ((HASHDEV(dev)^((block)/(chunk_size))) & (mask))
  75. static inline lv_block_exception_t *
  76. lvm_find_exception_table(kdev_t org_dev, unsigned long org_start, lv_t * lv)
  77. {
  78. struct list_head * hash_table = lv->lv_snapshot_hash_table, * next;
  79. unsigned long mask = lv->lv_snapshot_hash_mask;
  80. int chunk_size = lv->lv_chunk_size;
  81. lv_block_exception_t * ret;
  82. int i = 0;
  83. hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];
  84. ret = NULL;
  85. for (next = hash_table->next; next != hash_table; next = next->next)
  86. {
  87. lv_block_exception_t * exception;
  88. exception = list_entry(next, lv_block_exception_t, hash);
  89. if (exception->rsector_org == org_start &&
  90.     exception->rdev_org == org_dev)
  91. {
  92. if (i)
  93. {
  94. /* fun, isn't it? :) */
  95. list_del(next);
  96. list_add(next, hash_table);
  97. }
  98. ret = exception;
  99. break;
  100. }
  101. i++;
  102. }
  103. return ret;
  104. }
  105. inline void lvm_hash_link(lv_block_exception_t * exception,
  106.   kdev_t org_dev, unsigned long org_start,
  107.   lv_t * lv)
  108. {
  109. struct list_head * hash_table = lv->lv_snapshot_hash_table;
  110. unsigned long mask = lv->lv_snapshot_hash_mask;
  111. int chunk_size = lv->lv_chunk_size;
  112. hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];
  113. list_add(&exception->hash, hash_table);
  114. }
  115. int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector,
  116.      unsigned long pe_start, lv_t * lv)
  117. {
  118. int ret;
  119. unsigned long pe_off, pe_adjustment, __org_start;
  120. kdev_t __org_dev;
  121. int chunk_size = lv->lv_chunk_size;
  122. lv_block_exception_t * exception;
  123. pe_off = pe_start % chunk_size;
  124. pe_adjustment = (*org_sector-pe_off) % chunk_size;
  125. __org_start = *org_sector - pe_adjustment;
  126. __org_dev = *org_dev;
  127. ret = 0;
  128. exception = lvm_find_exception_table(__org_dev, __org_start, lv);
  129. if (exception)
  130. {
  131. *org_dev = exception->rdev_new;
  132. *org_sector = exception->rsector_new + pe_adjustment;
  133. ret = 1;
  134. }
  135. return ret;
  136. }
  137. void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason)
  138. {
  139. kdev_t last_dev;
  140. int i;
  141. /* no exception storage space available for this snapshot
  142.    or error on this snapshot --> release it */
  143. invalidate_buffers(lv_snap->lv_dev);
  144.        /* wipe the snapshot since it's inconsistent now */
  145.        _disable_snapshot(vg, lv_snap);
  146. for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) {
  147. if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) {
  148. last_dev = lv_snap->lv_block_exception[i].rdev_new;
  149. invalidate_buffers(last_dev);
  150. }
  151. }
  152. lvm_snapshot_release(lv_snap);
  153. lv_snap->lv_status &= ~LV_ACTIVE;
  154. printk(KERN_INFO
  155.        "%s -- giving up to snapshot %s on %s: %sn",
  156.        lvm_name, lv_snap->lv_snapshot_org->lv_name, lv_snap->lv_name,
  157.        reason);
  158. }
  159. static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks,
  160.       unsigned long start,
  161.       int nr_sectors,
  162.       int blocksize)
  163. {
  164. int i, sectors_per_block, nr_blocks;
  165. sectors_per_block = blocksize / SECTOR_SIZE;
  166. if(start & (sectors_per_block - 1))
  167. return 0;
  168. nr_blocks = nr_sectors / sectors_per_block;
  169. start /= sectors_per_block;
  170. for (i = 0; i < nr_blocks; i++)
  171. blocks[i] = start++;
  172. return 1;
  173. }
  174. inline int lvm_get_blksize(kdev_t dev)
  175. {
  176. int correct_size = BLOCK_SIZE, i, major;
  177. major = MAJOR(dev);
  178. if (blksize_size[major])
  179. {
  180. i = blksize_size[major][MINOR(dev)];
  181. if (i)
  182. correct_size = i;
  183. }
  184. return correct_size;
  185. }
  186. #ifdef DEBUG_SNAPSHOT
  187. static inline void invalidate_snap_cache(unsigned long start, unsigned long nr,
  188.  kdev_t dev)
  189. {
  190. struct buffer_head * bh;
  191. int sectors_per_block, i, blksize, minor;
  192. minor = MINOR(dev);
  193. blksize = lvm_blocksizes[minor];
  194. sectors_per_block = blksize >> 9;
  195. nr /= sectors_per_block;
  196. start /= sectors_per_block;
  197. for (i = 0; i < nr; i++)
  198. {
  199. bh = get_hash_table(dev, start++, blksize);
  200. if (bh)
  201. bforget(bh);
  202. }
  203. }
  204. #endif
  205. int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
  206. {
  207.        uint pvn;
  208.        int id = 0, is = lv_snap->lv_remap_ptr;
  209.        ulong blksize_snap;
  210.        lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *)
  211.                page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
  212.        if (is == 0)
  213.                return 0;
  214. is--;
  215.         blksize_snap =
  216.                lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);
  217.         is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));
  218. memset(lv_COW_table, 0, blksize_snap);
  219. for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {
  220. /* store new COW_table entry */
  221.                lv_block_exception_t *be = lv_snap->lv_block_exception + is;
  222.                if(_pv_get_number(vg, be->rdev_org, &pvn))
  223.                        goto bad;
  224.                lv_COW_table[id].pv_org_number = cpu_to_le64(pvn);
  225.                lv_COW_table[id].pv_org_rsector = cpu_to_le64(be->rsector_org);
  226.                if(_pv_get_number(vg, be->rdev_new, &pvn))
  227.                        goto bad;
  228.                lv_COW_table[id].pv_snap_number = cpu_to_le64(pvn);
  229.                lv_COW_table[id].pv_snap_rsector =
  230.                        cpu_to_le64(be->rsector_new);
  231. }
  232.        return 0;
  233.  bad:
  234.        printk(KERN_ERR "%s -- lvm_snapshot_fill_COW_page failed", lvm_name);
  235.        return -1;
  236. }
  237. /*
  238.  * writes a COW exception table sector to disk (HM)
  239.  */
  240. int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap)
  241. {
  242. int r;
  243. const char *err;
  244. if((r = _write_COW_table_block(vg, lv_snap,
  245.        lv_snap->lv_remap_ptr - 1, &err)))
  246. lvm_drop_snapshot(vg, lv_snap, err);
  247. return r;
  248. }
  249. /*
  250.  * copy on write handler for one snapshot logical volume
  251.  *
  252.  * read the original blocks and store it/them on the new one(s).
  253.  * if there is no exception storage space free any longer --> release snapshot.
  254.  *
  255.  * this routine gets called for each _first_ write to a physical chunk.
  256.  */
  257. int lvm_snapshot_COW(kdev_t org_phys_dev,
  258.      unsigned long org_phys_sector,
  259.      unsigned long org_pe_start,
  260.      unsigned long org_virt_sector,
  261.      vg_t *vg, lv_t* lv_snap)
  262. {
  263. const char * reason;
  264. unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;
  265. int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size;
  266. struct kiobuf * iobuf;
  267. int blksize_snap, blksize_org, min_blksize, max_blksize;
  268. int max_sectors, nr_sectors;
  269. /* check if we are out of snapshot space */
  270. if (idx >= lv_snap->lv_remap_end)
  271. goto fail_out_of_space;
  272. /* calculate physical boundaries of source chunk */
  273. pe_off = org_pe_start % chunk_size;
  274. org_start = org_phys_sector - ((org_phys_sector-pe_off) % chunk_size);
  275. virt_start = org_virt_sector - (org_phys_sector - org_start);
  276. /* calculate physical boundaries of destination chunk */
  277. snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
  278. snap_start = lv_snap->lv_block_exception[idx].rsector_new;
  279. #ifdef DEBUG_SNAPSHOT
  280. printk(KERN_INFO
  281.        "%s -- COW: "
  282.        "org %s faulting %lu start %lu, snap %s start %lu, "
  283.        "size %d, pe_start %lu pe_off %lu, virt_sec %lun",
  284.        lvm_name,
  285.        kdevname(org_phys_dev), org_phys_sector, org_start,
  286.        kdevname(snap_phys_dev), snap_start,
  287.        chunk_size,
  288.        org_pe_start, pe_off,
  289.        org_virt_sector);
  290. #endif
  291. iobuf = lv_snap->lv_iobuf;
  292. blksize_org = lvm_get_blksize(org_phys_dev);
  293. blksize_snap = lvm_get_blksize(snap_phys_dev);
  294. max_blksize = max(blksize_org, blksize_snap);
  295. min_blksize = min(blksize_org, blksize_snap);
  296. max_sectors = KIO_MAX_SECTORS * (min_blksize>>9);
  297. if (chunk_size % (max_blksize>>9))
  298. goto fail_blksize;
  299. while (chunk_size)
  300. {
  301. nr_sectors = min(chunk_size, max_sectors);
  302. chunk_size -= nr_sectors;
  303. iobuf->length = nr_sectors << 9;
  304. if(!lvm_snapshot_prepare_blocks(iobuf->blocks, org_start,
  305. nr_sectors, blksize_org))
  306. goto fail_prepare;
  307. if (brw_kiovec(READ, 1, &iobuf, org_phys_dev,
  308.        iobuf->blocks, blksize_org) != (nr_sectors<<9))
  309. goto fail_raw_read;
  310. if(!lvm_snapshot_prepare_blocks(iobuf->blocks, snap_start,
  311. nr_sectors, blksize_snap))
  312. goto fail_prepare;
  313. if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
  314.        iobuf->blocks, blksize_snap) != (nr_sectors<<9))
  315. goto fail_raw_write;
  316. }
  317. #ifdef DEBUG_SNAPSHOT
  318. /* invalidate the logical snapshot buffer cache */
  319. invalidate_snap_cache(virt_start, lv_snap->lv_chunk_size,
  320.       lv_snap->lv_dev);
  321. #endif
  322. /* the original chunk is now stored on the snapshot volume
  323.    so update the execption table */
  324. lv_snap->lv_block_exception[idx].rdev_org = org_phys_dev;
  325. lv_snap->lv_block_exception[idx].rsector_org = org_start;
  326. lvm_hash_link(lv_snap->lv_block_exception + idx,
  327.       org_phys_dev, org_start, lv_snap);
  328. lv_snap->lv_remap_ptr = idx + 1;
  329. if (lv_snap->lv_snapshot_use_rate > 0) {
  330. if (lv_snap->lv_remap_ptr * 100 / lv_snap->lv_remap_end >= lv_snap->lv_snapshot_use_rate)
  331. wake_up_interruptible(&lv_snap->lv_snapshot_wait);
  332. }
  333. return 0;
  334. /* slow path */
  335.  out:
  336. lvm_drop_snapshot(vg, lv_snap, reason);
  337. return 1;
  338.  fail_out_of_space:
  339. reason = "out of space";
  340. goto out;
  341.  fail_raw_read:
  342. reason = "read error";
  343. goto out;
  344.  fail_raw_write:
  345. reason = "write error";
  346. goto out;
  347.  fail_blksize:
  348. reason = "blocksize error";
  349. goto out;
  350.  fail_prepare:
  351. reason = "couldn't prepare kiovec blocks "
  352. "(start probably isn't block aligned)";
  353. goto out;
  354. }
  355. int lvm_snapshot_alloc_iobuf_pages(struct kiobuf * iobuf, int sectors)
  356. {
  357. int bytes, nr_pages, err, i;
  358. bytes = sectors * SECTOR_SIZE;
  359. nr_pages = (bytes + ~PAGE_MASK) >> PAGE_SHIFT;
  360. err = expand_kiobuf(iobuf, nr_pages);
  361. if (err) goto out;
  362. err = -ENOMEM;
  363. iobuf->locked = 1;
  364. iobuf->nr_pages = 0;
  365. for (i = 0; i < nr_pages; i++)
  366. {
  367. struct page * page;
  368. page = alloc_page(GFP_KERNEL);
  369. if (!page)
  370. goto out;
  371. iobuf->maplist[i] = page;
  372. LockPage(page);
  373. iobuf->nr_pages++;
  374. }
  375. iobuf->offset = 0;
  376. err = 0;
  377.  out:
  378. return err;
  379. }
  380. static int calc_max_buckets(void)
  381. {
  382. unsigned long mem;
  383. mem = num_physpages << PAGE_SHIFT;
  384. mem /= 100;
  385. mem *= 2;
  386. mem /= sizeof(struct list_head);
  387. return mem;
  388. }
  389. int lvm_snapshot_alloc_hash_table(lv_t * lv)
  390. {
  391. int err;
  392. unsigned long buckets, max_buckets, size;
  393. struct list_head * hash;
  394. buckets = lv->lv_remap_end;
  395. max_buckets = calc_max_buckets();
  396. buckets = min(buckets, max_buckets);
  397. while (buckets & (buckets-1))
  398. buckets &= (buckets-1);
  399. size = buckets * sizeof(struct list_head);
  400. err = -ENOMEM;
  401. hash = vmalloc(size);
  402. lv->lv_snapshot_hash_table = hash;
  403. if (!hash)
  404. goto out;
  405. lv->lv_snapshot_hash_table_size = size;
  406. lv->lv_snapshot_hash_mask = buckets-1;
  407. while (buckets--)
  408. INIT_LIST_HEAD(hash+buckets);
  409. err = 0;
  410. out:
  411. return err;
  412. }
  413. int lvm_snapshot_alloc(lv_t * lv_snap)
  414. {
  415. int ret, max_sectors;
  416. /* allocate kiovec to do chunk io */
  417. ret = alloc_kiovec(1, &lv_snap->lv_iobuf);
  418. if (ret) goto out;
  419. max_sectors = KIO_MAX_SECTORS << (PAGE_SHIFT-9);
  420. ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors);
  421. if (ret) goto out_free_kiovec;
  422. /* allocate kiovec to do exception table io */
  423. ret = alloc_kiovec(1, &lv_snap->lv_COW_table_iobuf);
  424. if (ret) goto out_free_kiovec;
  425. ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_COW_table_iobuf,
  426.                                             PAGE_SIZE/SECTOR_SIZE);
  427. if (ret) goto out_free_both_kiovecs;
  428. ret = lvm_snapshot_alloc_hash_table(lv_snap);
  429. if (ret) goto out_free_both_kiovecs;
  430. out:
  431. return ret;
  432. out_free_both_kiovecs:
  433. unmap_kiobuf(lv_snap->lv_COW_table_iobuf);
  434. free_kiovec(1, &lv_snap->lv_COW_table_iobuf);
  435. lv_snap->lv_COW_table_iobuf = NULL;
  436. out_free_kiovec:
  437. unmap_kiobuf(lv_snap->lv_iobuf);
  438. free_kiovec(1, &lv_snap->lv_iobuf);
  439. lv_snap->lv_iobuf = NULL;
  440. if (lv_snap->lv_snapshot_hash_table != NULL)
  441. vfree(lv_snap->lv_snapshot_hash_table);
  442. lv_snap->lv_snapshot_hash_table = NULL;
  443. goto out;
  444. }
  445. void lvm_snapshot_release(lv_t * lv)
  446. {
  447. if (lv->lv_block_exception)
  448. {
  449. vfree(lv->lv_block_exception);
  450. lv->lv_block_exception = NULL;
  451. }
  452. if (lv->lv_snapshot_hash_table)
  453. {
  454. vfree(lv->lv_snapshot_hash_table);
  455. lv->lv_snapshot_hash_table = NULL;
  456. lv->lv_snapshot_hash_table_size = 0;
  457. }
  458. if (lv->lv_iobuf)
  459. {
  460.         kiobuf_wait_for_io(lv->lv_iobuf);
  461. unmap_kiobuf(lv->lv_iobuf);
  462. free_kiovec(1, &lv->lv_iobuf);
  463. lv->lv_iobuf = NULL;
  464. }
  465. if (lv->lv_COW_table_iobuf)
  466. {
  467.                kiobuf_wait_for_io(lv->lv_COW_table_iobuf);
  468.                unmap_kiobuf(lv->lv_COW_table_iobuf);
  469.                free_kiovec(1, &lv->lv_COW_table_iobuf);
  470.                lv->lv_COW_table_iobuf = NULL;
  471. }
  472. }
  473. static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
  474.   int idx, const char **reason) {
  475. int blksize_snap;
  476. int end_of_table;
  477. int idx_COW_table;
  478. uint pvn;
  479. ulong snap_pe_start, COW_table_sector_offset,
  480. COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block;
  481. ulong blocks[1];
  482. kdev_t snap_phys_dev;
  483. lv_block_exception_t *be;
  484. struct kiobuf * COW_table_iobuf = lv_snap->lv_COW_table_iobuf;
  485. lv_COW_table_disk_t * lv_COW_table =
  486.    ( lv_COW_table_disk_t *) page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
  487. COW_chunks_per_pe = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv_snap);
  488. COW_entries_per_pe = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv_snap);
  489. /* get physical addresse of destination chunk */
  490. snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
  491. snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
  492. blksize_snap = lvm_get_blksize(snap_phys_dev);
  493.         COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
  494.         idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block;
  495. if ( idx_COW_table == 0) memset(lv_COW_table, 0, blksize_snap);
  496.        /* sector offset into the on disk COW table */
  497. COW_table_sector_offset = (idx % COW_entries_per_pe) / (SECTOR_SIZE / sizeof(lv_COW_table_disk_t));
  498.         /* COW table block to write next */
  499. blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
  500. /* store new COW_table entry */
  501.        be = lv_snap->lv_block_exception + idx;
  502.        if(_pv_get_number(vg, be->rdev_org, &pvn))
  503.                goto fail_pv_get_number;
  504.        lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(pvn);
  505.        lv_COW_table[idx_COW_table].pv_org_rsector =
  506.                cpu_to_le64(be->rsector_org);
  507.        if(_pv_get_number(vg, snap_phys_dev, &pvn))
  508.                goto fail_pv_get_number;
  509.        lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(pvn);
  510.        lv_COW_table[idx_COW_table].pv_snap_rsector =
  511.                cpu_to_le64(be->rsector_new);
  512. COW_table_iobuf->length = blksize_snap;
  513. if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
  514.        blocks, blksize_snap) != blksize_snap)
  515. goto fail_raw_write;
  516.        /* initialization of next COW exception table block with zeroes */
  517. end_of_table = idx % COW_entries_per_pe == COW_entries_per_pe - 1;
  518. if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table)
  519. {
  520. /* don't go beyond the end */
  521.                if (idx + 1 >= lv_snap->lv_remap_end) goto out;
  522. memset(lv_COW_table, 0, blksize_snap);
  523. if (end_of_table)
  524. {
  525. idx++;
  526. snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
  527. snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
  528. blksize_snap = lvm_get_blksize(snap_phys_dev);
  529. blocks[0] = snap_pe_start >> (blksize_snap >> 10);
  530. } else blocks[0]++;
  531.                if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
  532.                                  blocks, blksize_snap) !=
  533.                     blksize_snap)
  534. goto fail_raw_write;
  535. }
  536.  out:
  537. return 0;
  538.  fail_raw_write:
  539. *reason = "write error";
  540. return 1;
  541.  fail_pv_get_number:
  542. *reason = "_pv_get_number failed";
  543. return 1;
  544. }
  545. /*
  546.  * FIXME_1.2
  547.  * This function is a bit of a hack; we need to ensure that the
  548.  * snapshot is never made active again, because it will surely be
  549.  * corrupt.  At the moment we do not have access to the LVM metadata
  550.  * from within the kernel.  So we set the first exception to point to
  551.  * sector 1 (which will always be within the metadata, and as such
  552.  * invalid).  User land tools will check for this when they are asked
  553.  * to activate the snapshot and prevent this from happening.
  554.  */
  555. static void _disable_snapshot(vg_t *vg, lv_t *lv) {
  556. const char *err;
  557. lv->lv_block_exception[0].rsector_org = LVM_SNAPSHOT_DROPPED_SECTOR;
  558. if(_write_COW_table_block(vg, lv, 0, &err) < 0) {
  559. printk(KERN_ERR "%s -- couldn't disable snapshot: %sn",
  560.        lvm_name, err);
  561. }
  562. }
  563. MODULE_LICENSE("GPL");