1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2012 STRATO AG. All rights reserved.
  23  */
  24 #include <sys/zfs_context.h>
  25 #include <sys/errno.h>
  26 #include <sys/fits_impl.h>
  27 
  28 int
  29 fits_add_count(fits_counter_t *fc, uint64_t ino, uint64_t inc,
  30                uint64_t aux, uint64_t *new_count, uint64_t *old_aux)
  31 {
  32         fits_count_elem_t *fce = fc->fc_head;
  33 
  34         while (fce && fce->fce_ino != ino)
  35                 fce = fce->fce_next;
  36 
  37         if (!fce) {
  38                 fce = kmem_alloc(sizeof(*fce), KM_SLEEP);
  39                 fce->fce_ino = ino;
  40                 fce->fce_count = 0;
  41                 fce->fce_next = fc->fc_head;
  42                 fc->fc_head = fce;
  43         }
  44 
  45         if (old_aux) {
  46                 *old_aux = fce->fce_aux;
  47                 fce->fce_aux = aux;
  48         }
  49         fce->fce_count += inc;
  50 
  51         if (new_count)
  52                 *new_count = fce->fce_count;
  53 
  54         return 0;
  55 }
  56 
  57 int
  58 fits_get_count(fits_counter_t *fc, uint64_t ino, uint64_t *new_count,
  59                uint64_t *old_aux)
  60 {
  61         fits_count_elem_t *fce = fc->fc_head;
  62 
  63         while (fce && fce->fce_ino != ino)
  64                 fce = fce->fce_next;
  65 
  66         if (!fce) {
  67                 if (new_count)
  68                         *new_count = 0;
  69                 if (old_aux)
  70                         *old_aux = 0;
  71                 return ENOENT;
  72         } else {
  73                 if (new_count)
  74                         *new_count = fce->fce_count;
  75                 if (old_aux)
  76                         *old_aux = fce->fce_aux;
  77         }
  78 
  79         return 0;
  80 }
  81 
  82 void
  83 fits_free_count(fits_counter_t *fc, uint64_t ino)
  84 {
  85         fits_count_elem_t *fce = fc->fc_head;
  86         fits_count_elem_t *prev = NULL;
  87 
  88         while (fce && fce->fce_ino != ino) {
  89                 prev = fce;
  90                 fce = fce->fce_next;
  91         }
  92 
  93         if (!fce)
  94                 return;
  95 
  96         if (prev)
  97                 prev->fce_next = fce->fce_next;
  98         else
  99                 fc->fc_head = fce->fce_next;
 100 
 101         kmem_free(fce, sizeof(*fce));
 102 }
 103 
 104 int
 105 fits_assert_count_empty(fits_counter_t *fc)
 106 {
 107         fits_count_elem_t *fce = fc->fc_head;
 108         int ret = 0;
 109 
 110         while (fce) {
 111                 printf("!fits_assert_count_empty: %s ino %"PRIu64" count %"PRIu64"\n",
 112                        fc->fc_name, fce->fce_ino, fce->fce_count);
 113                 if (fce->fce_count != 0)
 114                         ++ret;
 115                 fce = fce->fce_next;
 116                 /* XXX TODO free count */
 117                 /* XXX known leftover: if a file had > 1 links and be replaced
 118                  * by a file with > 1 link, but no same_name replacements, the
 119                  * link_add_cnt leaks with being 0
 120                  */
 121         }
 122 
 123         return ret;
 124 }