コード例 #1
0
ファイル: writeback_cache.c プロジェクト: weixu8/rozofs
/**
*  API for init of the dirent level 0 cache
 @param cache: pointer to the cache descriptor

 @retval none
 */
void writebck_cache_level0_initialize()
{
    writebck_cache_bucket_t *p;
    writebck_cache_main_t *cache = &writebck_cache_level0;

    if (writebck_cache_initialized) return;
    cache->max = WRITEBCK_BUCKET_MAX_ROOT_DIRENT;
    cache->size = 0;
    list_init(&cache->entries);
    /*
    ** Allocate the memory to handle the buckets
    */
    cache->htable = xmalloc(sizeof(writebck_cache_bucket_t)*(1<<WRITEBCK_BUCKET_DEPTH_IN_BIT));
    if (cache->htable == NULL)
    {
      DIRENT_SEVERE("writebck_cache_level0_initialize out of memory (%u) at line %d\n",(unsigned int)sizeof(writebck_cache_bucket_t)*(1<<WRITEBCK_BUCKET_DEPTH_IN_BIT),
                     __LINE__);
      exit(0);
    }
    /*
    ** allocate the buffers
    */
    cache->mdirents_file_p = xmalloc(((1<<WRITEBCK_BUCKET_DEPTH_IN_BIT)*WRITEBCK_BUCKET_MAX_COLLISIONS*sizeof(mdirents_file_t)));
    /*
    ** init of the buckets
    */
    int i ;
    p = cache->htable;
    for (i = 0; i <  (1<<WRITEBCK_BUCKET_DEPTH_IN_BIT); i++,p++)
    {
      memset(&p->bucket_free_bitmap,0xff,WRITEBCK_BUCKET_MAX_COLLISIONS_BYTES);
      memset(&p->entry,0,WRITEBCK_BUCKET_MAX_COLLISIONS*sizeof(writebck_cache_bucket_entry_t));
    }
    /*
    ** clear statistics
    */
    memset(writebck_cache_access_tb,0,WRITEBCK_BUCKET_DEPTH_IN_BYTE*sizeof(uint64_t));
    memset(writebck_cache_pending_tb,0,WRITE_BACK_MAX_CNT*sizeof(uint64_t));

    writebck_cache_initialized = 1;

}
コード例 #2
0
/**
 * API to repair a faulty dirent file (collision or root)
 *
 * @param fd_dir: file handle of the parent directory
 * @param root: pointer to the mdirent root entry
 * @param cache_entry_p: pointer to the mdirent entry to repair
 * @param bucket_idx : bucket idx for which the issue has been detected
 *
 * @retval  0 on success
 * @retval -1 on failure
 */
void dirent_cache_repair_cache_entry_for_bucket_idx(int fd_dir,
        mdirents_cache_entry_t *root, mdirents_cache_entry_t *cache_entry_p,
        int bucket_idx, mdirents_hash_entry_t **hash_entry_last_p,
        int *first_index) 
{
    mdirent_sector0_not_aligned_t *sect0_p;
    int hash_entry_idx = 0;
    int next_hash_entry_idx;
    int table_idx = 0;
    int hash_entry_bucket_idx;
    mdirents_hash_entry_t *hash_entry_p = NULL;
    mdirents_hash_ptr_t *hash_bucket_p;

    /*
     ** clear the returned parameters first
     */
    *hash_entry_last_p = NULL;
    *first_index = 0;
    /*
     ** clean up the tracking buffer
     */
    memset(dirent_cache_repair_hash_entry_list_tab, 0,
            sizeof(dirent_cache_repair_hash_entry_list_t)
                    * MDIRENTS_ENTRIES_COUNT);

    sect0_p = DIRENT_VIRT_TO_PHY_OFF(cache_entry_p,sect0_p)
    ;
    if (sect0_p == (mdirent_sector0_not_aligned_t*) NULL ) {
        DIRENT_SEVERE("dirent_cache_repair_cache_entry sector 0 ptr does not exist( line %d\n)",__LINE__)
        ;
        return;
    }
    /*
    **_________________________________________________________________________________________
    ** go through the bitmap to find out the entry that belongs to the requested linked list
    **_________________________________________________________________________________________
    */
    while (hash_entry_idx < MDIRENTS_ENTRIES_COUNT) 
    {
      next_hash_entry_idx =DIRENT_CACHE_GETNEXT_ALLOCATED_HASH_ENTRY_IDX(&sect0_p->hash_bitmap,hash_entry_idx);
      if (next_hash_entry_idx < 0) 
      {
          /*
           ** all the entry of that dirent cache entry have been scanned,
           */
          break;
      }
      hash_entry_idx = next_hash_entry_idx;
      /*
       ** need to get the hash entry context and then the pointer to the name entry. The hash entry context is
       ** needed since it contains the reference of the starting chunk of the name entry
       */
      hash_entry_p =(mdirents_hash_entry_t*) DIRENT_CACHE_GET_HASH_ENTRY_PTR(cache_entry_p,hash_entry_idx)
      ;
      if (hash_entry_p == NULL ) 
      {
         /*
          ** something wrong!! (either the index is out of range and the memory array has been released
          */
         DIRENT_SEVERE("list_mdirentries pointer does not exist at %d\n",__LINE__) ;
         /*
          ** ok, let check the next hash_entry
          */
         hash_entry_idx++;
         continue;
      }
      hash_entry_bucket_idx = DIRENT_HASH_ENTRY_GET_BUCKET_IDX(hash_entry_p);
      if ((hash_entry_bucket_idx == bucket_idx)  && (hash_entry_p->next.type != MDIRENTS_HASH_PTR_FREE)) 
      {
         /*
          ** store it since it matches the searched linked list
          */
         dirent_cache_repair_hash_entry_list_tab[table_idx].hash_entry_p = hash_entry_p;
         dirent_cache_repair_hash_entry_list_tab[table_idx].local_idx = hash_entry_idx;
         table_idx++;
      }
      /*
       ** ok, let check the next hash_entry
       */
      hash_entry_idx++;
      continue;
    }
    dirent_cache_repair_cache_entry_for_bucket_idx_print(bucket_idx, "BEFORE");
    /*
    **___________________________________________________________________
    ** OK, now repair the current dirent cache entry in memory
    **___________________________________________________________________
    */
    {
       int i;
       mdirents_hash_entry_t *hash_entry_p_next = NULL;

       dirent_repair_file_count += table_idx;

      for (i = 0; i < table_idx; i++) 
      {
        hash_entry_p = dirent_cache_repair_hash_entry_list_tab[i].hash_entry_p;
        if (i == 0) 
        {
          /*
          ** update the hash bucket entry
          */
          hash_bucket_p = DIRENT_CACHE_GET_BUCKET_PTR(cache_entry_p,bucket_idx)
          ;
          if (hash_bucket_p == NULL ) 
          {
             /*
              ** That case Must not occur since we have elready scanned the entry
              ** One solution, if it happens is to skip that cache entry or to create one memory
              ** array for the range of bucket_idx.
              */
              hash_bucket_p = DIRENT_CACHE_ALLOCATE_BUCKET_ARRAY(cache_entry_p,bucket_idx);
              if (hash_bucket_p == NULL ) 
	      {
        	DIRENT_SEVERE("hash_bucket_p is null for bucket_idx %d ",bucket_idx);
        	return;	     
	      }
          }
          hash_bucket_p->type = MDIRENTS_HASH_PTR_LOCAL;
          hash_bucket_p->idx =  dirent_cache_repair_hash_entry_list_tab[i].local_idx;
        }
        /*
        ** Update the next pointer
        */
        hash_entry_p->next.type = MDIRENTS_HASH_PTR_LOCAL;
        hash_entry_p_next = dirent_cache_repair_hash_entry_list_tab[i+1].hash_entry_p;
        if (hash_entry_p_next == NULL ) 
        {
          /*
           ** end of list case: 
           ** we set eof because the system is assumed to check the bucket linked
           ** list when it loads the file from disk. If there is no check all the file behind
           ** will be hidden. That situation might happen if the system is reloaded just after
           ** the re-write of that current file.
           ** Another approach could be to make it pointed to itself. By the way, when the system
           ** we goo through the linked list it will detect a loop and it will proceed with we
           ** the linked list repair (That behaviour is only needed if the checked of the 
           ** linked list is disabled when the file is read from disk).
           */
          hash_entry_p->next.type = MDIRENTS_HASH_PTR_EOF;
          *hash_entry_last_p = hash_entry_p;
          break;
        }
	hash_entry_p->next.idx = dirent_cache_repair_hash_entry_list_tab[i+1].local_idx; 
      }            
    }
    /*
    ** check if there was no entry to be sure that the beginning of the local head of list is EOF
    ** this is applicable for an entry that is not root only
    */
   if (cache_entry_p != root) 
   {
     if (table_idx == 0) 
     {
       /*
        ** check if the current bucket is EOF, if not set it and re-write the file
        */
       hash_bucket_p =DIRENT_CACHE_GET_BUCKET_PTR(cache_entry_p,bucket_idx)
       ;
       if ((hash_bucket_p != NULL )&&(hash_bucket_p->type != MDIRENTS_HASH_PTR_EOF))
       {
         hash_bucket_p->type =MDIRENTS_HASH_PTR_EOF;
         hash_bucket_p->idx =0;
         /*
         ** re-write the file on disk
         */
         write_mdirents_file(fd_dir,cache_entry_p);
       }
     }
   }
   dirent_cache_repair_cache_entry_for_bucket_idx_print(bucket_idx, "AFTER");
}
コード例 #3
0
void dirent_file_repair(int dir_fd, mdirents_cache_entry_t *root_entry_p,
        int bucket_idx, dirent_file_repair_cause_e cause) {
    mdirents_cache_entry_t *cache_entry_p;
    mdirents_cache_entry_t *cache_entry_p_next;
    mdirents_hash_entry_t *hash_entry_p = NULL;
    //int hash_entry_idx = 0;
    int cache_entry_tb_idx = 0;
    int coll_idx;
    int loop_cnt = 0;
    int next_coll_idx = 0;
    int first_index;
    int bit_idx;
    int chunk_u8_idx;
    uint8_t *coll_bitmap_p;
    mdirents_hash_ptr_t *hash_bucket_p;
    int i;
    mdirent_sector0_not_aligned_t *sect0_p;

    dirent_repair_file_stats[cause]++;

    memset(dirent_cache_repair_cache_entry_list_tab, 0,
            sizeof(dirent_cache_repair_cache_entry_list_t)
                    * MDIRENTS_MAX_COLLS_IDX+1);



    info("dirent_file_repair bucket %d cause %s",bucket_idx,dirent_file_repair_cause_e2String(cause));


    /*
    ** set the different parameters
    */
    cache_entry_tb_idx = 0;
    coll_idx = 0;
    /*
     ** get the pointer to the collision file bitmap
     */
    sect0_p = DIRENT_VIRT_TO_PHY_OFF(root_entry_p,sect0_p);
    coll_bitmap_p = (uint8_t*) &sect0_p->coll_bitmap;
    /*
    **_____________________________________________________
    ** First of all do the recovery for the root entry
    **_____________________________________________________
    */
    dirent_cache_repair_cache_entry_for_bucket_idx(dir_fd, root_entry_p,
            root_entry_p, bucket_idx, &hash_entry_p, &first_index);
    /*
    ** insert the result in the rescue table: we always inserts the root even if there is
    ** no hash entry belonging to that least. This is needed it address the case where
    ** the pointer at the bucket level is the reference of the first collision file
    ** on which we have hash entries belonging to that list
    */
    dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].coll_idx = -1; // indicate root
    dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].first_index       = first_index;
    dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].cache_entry_p     = root_entry_p;
    dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].hash_entry_last_p = hash_entry_p;
    cache_entry_tb_idx++;

    /*
    **_______________________________________________________________________
    ** case of the collision file, so need to go through the bitmap of the
    ** dirent root file
    **_______________________________________________________________________
     */
    cache_entry_p = NULL;
    while (coll_idx < MDIRENTS_MAX_COLLS_IDX) {
        chunk_u8_idx = coll_idx / 8;
        bit_idx = coll_idx % 8;
        /*
         ** there is no collision dirent entry or the collision dirent entry exist and is not full
         */
        if ((coll_bitmap_p[chunk_u8_idx] & (1 << bit_idx)) != 0) {
            /*
             ** That entry is free, need to find out the next entry that is busy (0: busy, 1:free)
             */
            if (coll_idx % 8 == 0) {
                next_coll_idx = check_bytes_val(coll_bitmap_p, coll_idx,
                        MDIRENTS_MAX_COLLS_IDX, &loop_cnt, 1);
                if (next_coll_idx < 0)
                    break;
                /*
                 ** next  chunk
                 */
                if (next_coll_idx == coll_idx)
                    coll_idx++;
                else
                    coll_idx = next_coll_idx;
                continue;
            }
            /*
             ** next chunk
             */
            coll_idx++;
            continue;
        }
        /*
         ** one collision idx has been found
         ** need to get the entry associated with the collision index
         */
        cache_entry_p = dirent_cache_get_collision_ptr(root_entry_p, coll_idx);
        if (cache_entry_p == NULL ) {
            /*
            ** OK, do not break the analysis, skip that collision entry and try the next if any
            */
            coll_idx++;
            continue;
        }
        /*
        **_______________________________________________________________________
        ** OK, let's try to repair that current dirent cache entry for that bucket idx
        **_______________________________________________________________________
        */
        dirent_cache_repair_cache_entry_for_bucket_idx(dir_fd, root_entry_p,
                cache_entry_p, bucket_idx, &hash_entry_p, &first_index);
        /*
         ** insert the result in the rescue table if there is at least one valid entry for that bucket idx
         */
        if (hash_entry_p != NULL ) 
        {
          dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].coll_idx =  coll_idx;
          dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].first_index = first_index;
          dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].cache_entry_p = cache_entry_p;
          dirent_cache_repair_cache_entry_list_tab[cache_entry_tb_idx].hash_entry_last_p = hash_entry_p;
          cache_entry_tb_idx++;
        }
        coll_idx++;
    }
    /*
    **________________________________________________________________________________________________
    ** OK now go through that table to find out the order of the cache entries to update each of the
    ** local end of hash entries
    **________________________________________________________________________________________________
    */
    for (i = 0; i < cache_entry_tb_idx; i++) 
    {
        cache_entry_p = dirent_cache_repair_cache_entry_list_tab[i].cache_entry_p;
        hash_entry_p =  dirent_cache_repair_cache_entry_list_tab[i].hash_entry_last_p;
        if (hash_entry_p == NULL ) 
        {
          if (i == 0) 
          {
            /*
             ** case of the root cache entry :get the pointer to hash bucket table
             */
            hash_bucket_p = DIRENT_CACHE_GET_BUCKET_PTR(cache_entry_p,bucket_idx) ;
            if (hash_bucket_p == NULL ) 
            {
              /*
               ** That case Must not occur since we have elready scanned the entry
               ** One solution, if it happens is to skip that cache entry or to create one memory
               ** array for the range of bucket_idx.
               */
              DIRENT_SEVERE("dirent_file_repair: hash_bucket_p is null for bucket_idx %d in root dirent file  ",bucket_idx);
              hash_bucket_p = DIRENT_CACHE_ALLOCATE_BUCKET_ARRAY(cache_entry_p,bucket_idx);
	      if (hash_bucket_p == NULL)
	      {            
        	  fatal("dirent_file_repair: system error, out of memory!!");
	      }
            }
            /*
             ** check the end of list case
             */
            cache_entry_p_next = dirent_cache_repair_cache_entry_list_tab[i+ 1].cache_entry_p;
            if (cache_entry_p_next == NULL ) 
            {
              /*
              ** end of list case
              */
              break;
            }
            hash_bucket_p->type = MDIRENTS_HASH_PTR_COLL;
            hash_bucket_p->idx = dirent_cache_repair_cache_entry_list_tab[i+ 1].coll_idx;
            dirent_cache_repair_printf_cache_entry_for_bucket_idx(cache_entry_p, bucket_idx, -1);
            /*
            ** ____________________________________________________________
            ** re-write on disk the corresponding image of the dirent file
            ** ____________________________________________________________
            */
            write_mdirents_file(dir_fd, cache_entry_p);
            continue;
          }
          DIRENT_SEVERE("dirent_file_repair: hash_bucket_p is null for bucket_idx %d (line %d)\n",bucket_idx,__LINE__);
          severe("memory corruption!!");
        }
        /*
        ** Check if there is a cache entry in the next entry of the rescue table: end of list check
        */
        cache_entry_p_next = dirent_cache_repair_cache_entry_list_tab[i + 1].cache_entry_p;
        if (cache_entry_p_next == NULL ) 
        {
            /*
            ** end of list case
            */
            break;
        }
        /*
        ** there is an entry so update our current last hash_entry and eventually our bucket entry
        ** index according to the value of first_index
        */
        hash_entry_p->next.type = MDIRENTS_HASH_PTR_COLL;
        hash_entry_p->next.idx = dirent_cache_repair_cache_entry_list_tab[i + 1].coll_idx;
        dirent_cache_repair_printf_cache_entry_for_bucket_idx(cache_entry_p,
                                                              bucket_idx,
                                                              dirent_cache_repair_cache_entry_list_tab[i].coll_idx);
        /*
        ** ____________________________________________________________
        ** re-write on disk the corresponding image of the dirent file
        ** ____________________________________________________________
        */        
        write_mdirents_file(dir_fd, cache_entry_p);
    }
    /*
     ** ____________________________________________________________
     ** All the last hash entries of the dirent files have been updated
     ** expected the last one so now, update the last one
     ** ____________________________________________________________
     */
    if (cache_entry_p == NULL ) 
    {
        /*
         ** We must have at least the root !!
         */
        DIRENT_SEVERE("dirent_file_repair: empty list for bucket %d (line %d)\n",bucket_idx,__LINE__);
        severe("memory corruption!!");
    }
    if (hash_entry_p == NULL ) {
        /*
         ** this is possible for the case of the root only
         */
        if (cache_entry_p != root_entry_p) {
            DIRENT_SEVERE("dirent_file_repair: collision entry empty for bucket %d (line %d)\n",bucket_idx,__LINE__);
            severe("memory corruption!!");
        }
        hash_bucket_p = DIRENT_CACHE_GET_BUCKET_PTR(cache_entry_p,bucket_idx)
        ;
        if (hash_bucket_p == NULL ) {
            /*
             ** That case Must not occur since we have elready scanned the entry
             ** One solution, if it happens is to skip that cache entry or to create one memory
             ** array for the range of bucket_idx.
             */
            DIRENT_SEVERE("dirent_file_repair: hash_bucket_p is null for bucket_idx %d (line %d)\n",bucket_idx,__LINE__);
            severe("memory corruption!!");
        }
        hash_bucket_p->type = MDIRENTS_HASH_PTR_EOF;
        hash_bucket_p->idx = 0;
        /*
        ** _______________________________________________________________________________
        ** re-write dirent root file on disk the corresponding image of the dirent file
        ** _______________________________________________________________________________
        */               
        write_mdirents_file(dir_fd, cache_entry_p);

    } else {
        /*
        ** re-write last file on disk
        */
        hash_entry_p->next.type = MDIRENTS_HASH_PTR_EOF;
        hash_entry_p->next.idx = 0;
        write_mdirents_file(dir_fd, cache_entry_p);

    }
    /*
    ** _______________________________________________________________________________
    ** re-write last dirent colision file on disk the corresponding image of the dirent file
    ** _______________________________________________________________________________
    */ 
    write_mdirents_file(dir_fd, root_entry_p);

    dirent_cache_repair_printf_cache_entry_for_bucket_idx(cache_entry_p,
            bucket_idx, dirent_cache_repair_cache_entry_list_tab[i].coll_idx);

}