/*
 * tools/lib/lv_setup_COW_table_for_create.c
 *
 * Copyright (C)  2000  Heinz Mauelshagen, Sistina Software
 *
 * July 2000
 *
 * LVM is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * LVM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GNU CC; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA. 
 *
 */

#include <liblvm.h>


int lv_setup_COW_table_for_create ( vg_t *vg,
                                    char *lv_org_name,
                                    int l_new,
                                    int chunk_size) {
   int e, end, index, le, l_org, ret = 0, start, COW_table_chunks_per_PE;
   ulong size;
   lv_t *lv = NULL;

   debug_enter ( "lv_setup_COW_table_for_create -- CALLED\n");

   if ( vg == NULL ||
        vg_check_consistency ( vg) < 0 ||
        lv_org_name == NULL ||
        lv_check_name ( lv_org_name) < 0 ||
        vg->lv[l_new] == NULL) ret = -LVM_EPARAM;
   else {
      l_org = lv_get_index_by_name ( vg, lv_org_name);
      lv = vg->lv[l_new];
      lv->lv_access |= LV_SNAPSHOT;
      lv->lv_snapshot_org = NULL;
      lv->lv_snapshot_minor = MINOR ( vg->lv[l_org]->lv_dev);
      vg->lv[l_org]->lv_access |= LV_SNAPSHOT_ORG;
      vg->lv[l_org]->lv_snapshot_minor = 0;
   
      /* remap chunk size */
      lv->lv_chunk_size = ( chunk_size * 1024) / SECTOR_SIZE;
      COW_table_chunks_per_PE = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv);
      end = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv);
      start = COW_table_chunks_per_PE - end;
      size = end * lv->lv_allocated_le * sizeof ( lv_block_exception_t);

      if ( ( lv->lv_block_exception = malloc ( size)) == NULL) {
         fprintf ( stderr, "%s -- ERROR: malloc at line %d\n\n", cmd, __LINE__);
         ret = LVM_ELV_SETUP_COW_TABLE_FOR_CREATE_MALLOC;
      } else {
         memset ( lv->lv_block_exception, 0, size);
         index = 0;

         for ( le = 0; le < lv->lv_allocated_le; le++) {
            for ( e = start; e <= end; e++) {
               lv->lv_block_exception[index].rdev_new =
                  lv->lv_current_pe[le].dev;
               lv->lv_block_exception[index].rsector_new =
                  lv->lv_current_pe[le].pe + e * lv->lv_chunk_size;
               index++;
            }
         }
         lv->lv_remap_end = index;
         lv->lv_remap_ptr = 0;
      }
   }

   debug_leave ( "lv_setup_COW_table_for_create -- LEAVING with ret: %d\n",
                 ret);
   return ret;
}
