19  *        the documentation and/or other materials provided with the
  20  *        distribution.
  21  *
  22  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  23  *        nor the names of its contributors may be used to endorse or promote
  24  *        products derived from this software without specific prior written
  25  *        permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37  * POSSIBILITY OF SUCH DAMAGE.
  38  */
  39 #include <stdlib.h>
  40 #include "tlm.h"
  41 #include "tlm_proto.h"
  42 #include <sys/errno.h>
  43 
  44 
  45 extern  tlm_chain_link_t *tlm_un_ref(tlm_chain_link_t *old_top,
  46     tlm_chain_link_t *link);
  47 
  48 static  tlm_info_t tlm_info;
  49 
  50 /*
  51  * Mutex for concurrent access to job_stats
  52  */
  53 mutex_t jstat_mtx;
  54 
  55 
  56 /*
  57  * get the number of libraries
  58  */
 
 
 186         link = tlm_info.ti_job_stats;
 187         if (link == 0) {
 188                 /*
 189                  * our tables are empty
 190                  */
 191                 (void) mutex_unlock(&jstat_mtx);
 192                 return (&fake_job_stats);
 193         }
 194 
 195         do {
 196                 tlm_job_stats_t *job_stats;
 197                 job_stats = (tlm_job_stats_t *)link->tc_data;
 198 
 199                 if (strcmp(job_stats->js_job_name, name) == 0) {
 200                         link->tc_ref_count++;
 201                         (void) mutex_unlock(&jstat_mtx);
 202                         return (job_stats);
 203                 }
 204                 link = link->tc_next;
 205         } while (link != tlm_info.ti_job_stats);
 206         NDMP_LOG(LOG_DEBUG,
 207             "TAPE BACKUP> Ref for job [%s] was not found", name);
 208         (void) mutex_unlock(&jstat_mtx);
 209 
 210         return (&fake_job_stats);
 211 }
 212 
 213 /*
 214  * remove a link to the INFO chain
 215  */
 216 void
 217 tlm_un_ref_job_stats(char *name)
 218 {
 219         tlm_chain_link_t *link;
 220 
 221         (void) mutex_lock(&jstat_mtx);
 222         link = tlm_info.ti_job_stats;
 223         if (link == 0) {
 224                 NDMP_LOG(LOG_DEBUG, "TAPE BACKUP>"
 225                     " Internal error for job [%s], could not delete", name);
 226                 return;
 227         }
 228         do {
 229                 tlm_job_stats_t *job_stats;
 230                 job_stats = (tlm_job_stats_t *)link->tc_data;
 231 
 232                 if (strcmp(job_stats->js_job_name, name) == 0) {
 233                         tlm_info.ti_job_stats =
 234                             tlm_un_ref(tlm_info.ti_job_stats, link);
 235                         (void) mutex_unlock(&jstat_mtx);
 236                         return;
 237                 }
 238                 link = link->tc_next;
 239         } while (link != tlm_info.ti_job_stats);
 240         (void) mutex_unlock(&jstat_mtx);
 241         NDMP_LOG(LOG_DEBUG,
 242             "TAPE BACKUP> Delete for job [%s] was not found", name);
 243 }
 244 
 245 /*
 246  * one party does not care about this blob, can we let it go?
 247  */
 248 tlm_chain_link_t *
 249 tlm_un_ref(tlm_chain_link_t *old_top, tlm_chain_link_t *link)
 250 {
 251         tlm_chain_link_t *chain_link = old_top;
 252         tlm_chain_link_t *new_top;
 253 
 254         /*
 255          * count down the number of
 256          * interested parties for this blob
 257          */
 258         link->tc_ref_count--;
 259         if (link->tc_ref_count > 0) {
 260                 /*
 261                  * there is still interest in this blob,
 
 288                         if (link->tc_next == link->tc_prev &&
 289                             link->tc_next == link) {
 290                                 /*
 291                                  * there is only this one link in the chain
 292                                  * delete this and the chain is empty
 293                                  */
 294                                 new_top = 0;
 295                         } else {
 296                                 new_top = link->tc_next;
 297                         }
 298                         next = link->tc_next;
 299                         prev = link->tc_prev;
 300                         prev->tc_next = next;
 301                         next->tc_prev = prev;
 302                         free(link->tc_data);
 303                         free(link);
 304                         return (new_top);
 305                 }
 306                 chain_link = chain_link->tc_next;
 307         } while (chain_link != old_top);
 308         NDMP_LOG(LOG_DEBUG, "TAPE BACKUP> un_ref target not found.");
 309         return (old_top);
 310 }
 311 
 312 /*
 313  * the following section is global, but not really part of the
 314  * public interface.  Use of this outside of the tlm_*.c files
 315  * is for special cases only.
 316  */
 317 
 318 /*
 319  * add a new tape library data blob to the list of libraries
 320  * returns the new tape library data blob just created
 321  */
 322 int
 323 tlm_insert_new_library(scsi_link_t *slink)
 324 {
 325         tlm_library_t **p_library = &tlm_info.ti_library;
 326         tlm_library_t *library = ndmp_malloc(sizeof (tlm_library_t));
 327 
 328         while (*p_library != NULL) {
 
 | 
 
 
  19  *        the documentation and/or other materials provided with the
  20  *        distribution.
  21  *
  22  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  23  *        nor the names of its contributors may be used to endorse or promote
  24  *        products derived from this software without specific prior written
  25  *        permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37  * POSSIBILITY OF SUCH DAMAGE.
  38  */
  39 #include <syslog.h>
  40 #include <stdlib.h>
  41 #include "tlm.h"
  42 #include "tlm_proto.h"
  43 #include <sys/errno.h>
  44 
  45 
  46 extern  tlm_chain_link_t *tlm_un_ref(tlm_chain_link_t *old_top,
  47     tlm_chain_link_t *link);
  48 
  49 static  tlm_info_t tlm_info;
  50 
  51 /*
  52  * Mutex for concurrent access to job_stats
  53  */
  54 mutex_t jstat_mtx;
  55 
  56 
  57 /*
  58  * get the number of libraries
  59  */
 
 
 187         link = tlm_info.ti_job_stats;
 188         if (link == 0) {
 189                 /*
 190                  * our tables are empty
 191                  */
 192                 (void) mutex_unlock(&jstat_mtx);
 193                 return (&fake_job_stats);
 194         }
 195 
 196         do {
 197                 tlm_job_stats_t *job_stats;
 198                 job_stats = (tlm_job_stats_t *)link->tc_data;
 199 
 200                 if (strcmp(job_stats->js_job_name, name) == 0) {
 201                         link->tc_ref_count++;
 202                         (void) mutex_unlock(&jstat_mtx);
 203                         return (job_stats);
 204                 }
 205                 link = link->tc_next;
 206         } while (link != tlm_info.ti_job_stats);
 207         syslog(LOG_DEBUG,
 208             "TAPE BACKUP> Ref for job [%s] was not found", name);
 209         (void) mutex_unlock(&jstat_mtx);
 210 
 211         return (&fake_job_stats);
 212 }
 213 
 214 /*
 215  * remove a link to the INFO chain
 216  */
 217 void
 218 tlm_un_ref_job_stats(char *name)
 219 {
 220         tlm_chain_link_t *link;
 221 
 222         (void) mutex_lock(&jstat_mtx);
 223         link = tlm_info.ti_job_stats;
 224         if (link == 0) {
 225                 syslog(LOG_DEBUG, "TAPE BACKUP>"
 226                     " Internal error for job [%s], could not delete", name);
 227                 return;
 228         }
 229         do {
 230                 tlm_job_stats_t *job_stats;
 231                 job_stats = (tlm_job_stats_t *)link->tc_data;
 232 
 233                 if (strcmp(job_stats->js_job_name, name) == 0) {
 234                         tlm_info.ti_job_stats =
 235                             tlm_un_ref(tlm_info.ti_job_stats, link);
 236                         (void) mutex_unlock(&jstat_mtx);
 237                         return;
 238                 }
 239                 link = link->tc_next;
 240         } while (link != tlm_info.ti_job_stats);
 241         (void) mutex_unlock(&jstat_mtx);
 242         syslog(LOG_DEBUG,
 243             "TAPE BACKUP> Delete for job [%s] was not found", name);
 244 }
 245 
 246 /*
 247  * one party does not care about this blob, can we let it go?
 248  */
 249 tlm_chain_link_t *
 250 tlm_un_ref(tlm_chain_link_t *old_top, tlm_chain_link_t *link)
 251 {
 252         tlm_chain_link_t *chain_link = old_top;
 253         tlm_chain_link_t *new_top;
 254 
 255         /*
 256          * count down the number of
 257          * interested parties for this blob
 258          */
 259         link->tc_ref_count--;
 260         if (link->tc_ref_count > 0) {
 261                 /*
 262                  * there is still interest in this blob,
 
 289                         if (link->tc_next == link->tc_prev &&
 290                             link->tc_next == link) {
 291                                 /*
 292                                  * there is only this one link in the chain
 293                                  * delete this and the chain is empty
 294                                  */
 295                                 new_top = 0;
 296                         } else {
 297                                 new_top = link->tc_next;
 298                         }
 299                         next = link->tc_next;
 300                         prev = link->tc_prev;
 301                         prev->tc_next = next;
 302                         next->tc_prev = prev;
 303                         free(link->tc_data);
 304                         free(link);
 305                         return (new_top);
 306                 }
 307                 chain_link = chain_link->tc_next;
 308         } while (chain_link != old_top);
 309         syslog(LOG_DEBUG, "TAPE BACKUP> un_ref target not found.");
 310         return (old_top);
 311 }
 312 
 313 /*
 314  * the following section is global, but not really part of the
 315  * public interface.  Use of this outside of the tlm_*.c files
 316  * is for special cases only.
 317  */
 318 
 319 /*
 320  * add a new tape library data blob to the list of libraries
 321  * returns the new tape library data blob just created
 322  */
 323 int
 324 tlm_insert_new_library(scsi_link_t *slink)
 325 {
 326         tlm_library_t **p_library = &tlm_info.ti_library;
 327         tlm_library_t *library = ndmp_malloc(sizeof (tlm_library_t));
 328 
 329         while (*p_library != NULL) {
 
 |