1*2654012fSReza Sabdar /* 2*2654012fSReza Sabdar * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3*2654012fSReza Sabdar * Use is subject to license terms. 4*2654012fSReza Sabdar */ 5*2654012fSReza Sabdar 6*2654012fSReza Sabdar /* 7*2654012fSReza Sabdar * BSD 3 Clause License 8*2654012fSReza Sabdar * 9*2654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 10*2654012fSReza Sabdar * 11*2654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 12*2654012fSReza Sabdar * modification, are permitted provided that the following conditions 13*2654012fSReza Sabdar * are met: 14*2654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 15*2654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 16*2654012fSReza Sabdar * 17*2654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 18*2654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 19*2654012fSReza Sabdar * the documentation and/or other materials provided with the 20*2654012fSReza Sabdar * distribution. 21*2654012fSReza Sabdar * 22*2654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 23*2654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 24*2654012fSReza Sabdar * products derived from this software without specific prior written 25*2654012fSReza Sabdar * permission. 26*2654012fSReza Sabdar * 27*2654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28*2654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29*2654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30*2654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31*2654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32*2654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33*2654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34*2654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35*2654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36*2654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37*2654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 38*2654012fSReza Sabdar */ 39*2654012fSReza Sabdar #include <stdlib.h> 40*2654012fSReza Sabdar #include "tlm.h" 41*2654012fSReza Sabdar #include "tlm_proto.h" 42*2654012fSReza Sabdar #include <sys/errno.h> 43*2654012fSReza Sabdar 44*2654012fSReza Sabdar 45*2654012fSReza Sabdar extern tlm_chain_link_t *tlm_un_ref(tlm_chain_link_t *old_top, 46*2654012fSReza Sabdar tlm_chain_link_t *link); 47*2654012fSReza Sabdar 48*2654012fSReza Sabdar static tlm_info_t tlm_info; 49*2654012fSReza Sabdar 50*2654012fSReza Sabdar /* 51*2654012fSReza Sabdar * Mutex for concurrent access to job_stats 52*2654012fSReza Sabdar */ 53*2654012fSReza Sabdar mutex_t jstat_mtx; 54*2654012fSReza Sabdar 55*2654012fSReza Sabdar 56*2654012fSReza Sabdar /* 57*2654012fSReza Sabdar * get the number of libraries 58*2654012fSReza Sabdar */ 59*2654012fSReza Sabdar int 60*2654012fSReza Sabdar tlm_library_count(void) 61*2654012fSReza Sabdar { 62*2654012fSReza Sabdar int lib; 63*2654012fSReza Sabdar tlm_library_t *library; 64*2654012fSReza Sabdar 65*2654012fSReza Sabdar for (lib = 1; lib <= tlm_info.ti_library_count; lib++) { 66*2654012fSReza Sabdar library = tlm_library(lib); 67*2654012fSReza Sabdar if (library != NULL && 68*2654012fSReza Sabdar library->tl_drive_count == 0) { 69*2654012fSReza Sabdar return (0); 70*2654012fSReza Sabdar } 71*2654012fSReza Sabdar } 72*2654012fSReza Sabdar return (tlm_info.ti_library_count); 73*2654012fSReza Sabdar } 74*2654012fSReza Sabdar 75*2654012fSReza Sabdar /* 76*2654012fSReza Sabdar * get the library whose number matches 77*2654012fSReza Sabdar */ 78*2654012fSReza Sabdar tlm_library_t * 79*2654012fSReza Sabdar tlm_library(int lib) 80*2654012fSReza Sabdar { 81*2654012fSReza Sabdar tlm_library_t *library = tlm_info.ti_library; 82*2654012fSReza Sabdar while (library != NULL) { 83*2654012fSReza Sabdar if (library->tl_number == lib) { 84*2654012fSReza Sabdar return (library); 85*2654012fSReza Sabdar } 86*2654012fSReza Sabdar library = library->tl_next; 87*2654012fSReza Sabdar } 88*2654012fSReza Sabdar errno = TLM_ERROR_RANGE; 89*2654012fSReza Sabdar return (NULL); 90*2654012fSReza Sabdar } 91*2654012fSReza Sabdar 92*2654012fSReza Sabdar /* 93*2654012fSReza Sabdar * get the info about this drive 94*2654012fSReza Sabdar */ 95*2654012fSReza Sabdar tlm_drive_t * 96*2654012fSReza Sabdar tlm_drive(int lib, int drv) 97*2654012fSReza Sabdar { 98*2654012fSReza Sabdar tlm_drive_t *drive; 99*2654012fSReza Sabdar tlm_library_t *library = tlm_library(lib); 100*2654012fSReza Sabdar 101*2654012fSReza Sabdar if (library == NULL) { 102*2654012fSReza Sabdar return (NULL); 103*2654012fSReza Sabdar } 104*2654012fSReza Sabdar drive = library->tl_drive; 105*2654012fSReza Sabdar while (drive != NULL) { 106*2654012fSReza Sabdar if (drv == drive->td_number) { 107*2654012fSReza Sabdar return (drive); 108*2654012fSReza Sabdar } 109*2654012fSReza Sabdar drive = drive->td_next; 110*2654012fSReza Sabdar } 111*2654012fSReza Sabdar return (NULL); 112*2654012fSReza Sabdar } 113*2654012fSReza Sabdar 114*2654012fSReza Sabdar /* 115*2654012fSReza Sabdar * get the info about this slot 116*2654012fSReza Sabdar */ 117*2654012fSReza Sabdar tlm_slot_t * 118*2654012fSReza Sabdar tlm_slot(int lib, int slt) 119*2654012fSReza Sabdar { 120*2654012fSReza Sabdar tlm_slot_t *slot = NULL; 121*2654012fSReza Sabdar tlm_library_t *library = tlm_library(lib); 122*2654012fSReza Sabdar 123*2654012fSReza Sabdar if (library != NULL) 124*2654012fSReza Sabdar slot = library->tl_slot; 125*2654012fSReza Sabdar while (slot != NULL) { 126*2654012fSReza Sabdar if (slt == slot->ts_number) { 127*2654012fSReza Sabdar return (slot); 128*2654012fSReza Sabdar } 129*2654012fSReza Sabdar slot = slot->ts_next; 130*2654012fSReza Sabdar } 131*2654012fSReza Sabdar return (NULL); 132*2654012fSReza Sabdar } 133*2654012fSReza Sabdar 134*2654012fSReza Sabdar /* 135*2654012fSReza Sabdar * add a link to the INFO chain 136*2654012fSReza Sabdar */ 137*2654012fSReza Sabdar tlm_job_stats_t * 138*2654012fSReza Sabdar tlm_new_job_stats(char *name) 139*2654012fSReza Sabdar { 140*2654012fSReza Sabdar tlm_chain_link_t *new_link; 141*2654012fSReza Sabdar tlm_job_stats_t *job_stats; 142*2654012fSReza Sabdar 143*2654012fSReza Sabdar new_link = ndmp_malloc(sizeof (tlm_chain_link_t)); 144*2654012fSReza Sabdar if (new_link == 0) 145*2654012fSReza Sabdar return (0); 146*2654012fSReza Sabdar 147*2654012fSReza Sabdar job_stats = ndmp_malloc(sizeof (tlm_job_stats_t)); 148*2654012fSReza Sabdar if (job_stats == 0) { 149*2654012fSReza Sabdar free(new_link); 150*2654012fSReza Sabdar return (0); 151*2654012fSReza Sabdar } 152*2654012fSReza Sabdar 153*2654012fSReza Sabdar new_link->tc_ref_count = 1; 154*2654012fSReza Sabdar new_link->tc_data = (void *)job_stats; 155*2654012fSReza Sabdar (void) strlcpy(job_stats->js_job_name, name, TLM_MAX_BACKUP_JOB_NAME); 156*2654012fSReza Sabdar 157*2654012fSReza Sabdar (void) mutex_lock(&jstat_mtx); 158*2654012fSReza Sabdar if (tlm_info.ti_job_stats == 0) { 159*2654012fSReza Sabdar new_link->tc_next = new_link; 160*2654012fSReza Sabdar new_link->tc_prev = new_link; 161*2654012fSReza Sabdar } else { 162*2654012fSReza Sabdar tlm_chain_link_t *next_link = tlm_info.ti_job_stats; 163*2654012fSReza Sabdar tlm_chain_link_t *prev_link = next_link->tc_prev; 164*2654012fSReza Sabdar 165*2654012fSReza Sabdar new_link->tc_next = next_link; 166*2654012fSReza Sabdar new_link->tc_prev = prev_link; 167*2654012fSReza Sabdar prev_link->tc_next = new_link; 168*2654012fSReza Sabdar next_link->tc_prev = new_link; 169*2654012fSReza Sabdar } 170*2654012fSReza Sabdar tlm_info.ti_job_stats = new_link; 171*2654012fSReza Sabdar (void) mutex_unlock(&jstat_mtx); 172*2654012fSReza Sabdar 173*2654012fSReza Sabdar return (job_stats); 174*2654012fSReza Sabdar } 175*2654012fSReza Sabdar 176*2654012fSReza Sabdar /* 177*2654012fSReza Sabdar * make sure this Job Stats buffer is not deleted while we use it 178*2654012fSReza Sabdar */ 179*2654012fSReza Sabdar tlm_job_stats_t * 180*2654012fSReza Sabdar tlm_ref_job_stats(char *name) 181*2654012fSReza Sabdar { 182*2654012fSReza Sabdar static tlm_job_stats_t fake_job_stats; 183*2654012fSReza Sabdar tlm_chain_link_t *link; 184*2654012fSReza Sabdar 185*2654012fSReza Sabdar (void) mutex_lock(&jstat_mtx); 186*2654012fSReza Sabdar link = tlm_info.ti_job_stats; 187*2654012fSReza Sabdar if (link == 0) { 188*2654012fSReza Sabdar /* 189*2654012fSReza Sabdar * our tables are empty 190*2654012fSReza Sabdar */ 191*2654012fSReza Sabdar (void) mutex_unlock(&jstat_mtx); 192*2654012fSReza Sabdar return (&fake_job_stats); 193*2654012fSReza Sabdar } 194*2654012fSReza Sabdar 195*2654012fSReza Sabdar do { 196*2654012fSReza Sabdar tlm_job_stats_t *job_stats; 197*2654012fSReza Sabdar job_stats = (tlm_job_stats_t *)link->tc_data; 198*2654012fSReza Sabdar 199*2654012fSReza Sabdar if (strcmp(job_stats->js_job_name, name) == 0) { 200*2654012fSReza Sabdar link->tc_ref_count++; 201*2654012fSReza Sabdar (void) mutex_unlock(&jstat_mtx); 202*2654012fSReza Sabdar return (job_stats); 203*2654012fSReza Sabdar } 204*2654012fSReza Sabdar link = link->tc_next; 205*2654012fSReza Sabdar } while (link != tlm_info.ti_job_stats); 206*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 207*2654012fSReza Sabdar "TAPE BACKUP> Ref for job [%s] was not found", name); 208*2654012fSReza Sabdar (void) mutex_unlock(&jstat_mtx); 209*2654012fSReza Sabdar 210*2654012fSReza Sabdar return (&fake_job_stats); 211*2654012fSReza Sabdar } 212*2654012fSReza Sabdar 213*2654012fSReza Sabdar /* 214*2654012fSReza Sabdar * remove a link to the INFO chain 215*2654012fSReza Sabdar */ 216*2654012fSReza Sabdar void 217*2654012fSReza Sabdar tlm_un_ref_job_stats(char *name) 218*2654012fSReza Sabdar { 219*2654012fSReza Sabdar tlm_chain_link_t *link; 220*2654012fSReza Sabdar 221*2654012fSReza Sabdar (void) mutex_lock(&jstat_mtx); 222*2654012fSReza Sabdar link = tlm_info.ti_job_stats; 223*2654012fSReza Sabdar if (link == 0) { 224*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "TAPE BACKUP>" 225*2654012fSReza Sabdar " Internal error for job [%s], could not delete", name); 226*2654012fSReza Sabdar return; 227*2654012fSReza Sabdar } 228*2654012fSReza Sabdar do { 229*2654012fSReza Sabdar tlm_job_stats_t *job_stats; 230*2654012fSReza Sabdar job_stats = (tlm_job_stats_t *)link->tc_data; 231*2654012fSReza Sabdar 232*2654012fSReza Sabdar if (strcmp(job_stats->js_job_name, name) == 0) { 233*2654012fSReza Sabdar tlm_info.ti_job_stats = 234*2654012fSReza Sabdar tlm_un_ref(tlm_info.ti_job_stats, link); 235*2654012fSReza Sabdar (void) mutex_unlock(&jstat_mtx); 236*2654012fSReza Sabdar return; 237*2654012fSReza Sabdar } 238*2654012fSReza Sabdar link = link->tc_next; 239*2654012fSReza Sabdar } while (link != tlm_info.ti_job_stats); 240*2654012fSReza Sabdar (void) mutex_unlock(&jstat_mtx); 241*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 242*2654012fSReza Sabdar "TAPE BACKUP> Delete for job [%s] was not found", name); 243*2654012fSReza Sabdar } 244*2654012fSReza Sabdar 245*2654012fSReza Sabdar /* 246*2654012fSReza Sabdar * one party does not care about this blob, can we let it go? 247*2654012fSReza Sabdar */ 248*2654012fSReza Sabdar tlm_chain_link_t * 249*2654012fSReza Sabdar tlm_un_ref(tlm_chain_link_t *old_top, tlm_chain_link_t *link) 250*2654012fSReza Sabdar { 251*2654012fSReza Sabdar tlm_chain_link_t *chain_link = old_top; 252*2654012fSReza Sabdar tlm_chain_link_t *new_top; 253*2654012fSReza Sabdar 254*2654012fSReza Sabdar /* 255*2654012fSReza Sabdar * count down the number of 256*2654012fSReza Sabdar * interested parties for this blob 257*2654012fSReza Sabdar */ 258*2654012fSReza Sabdar link->tc_ref_count--; 259*2654012fSReza Sabdar if (link->tc_ref_count > 0) { 260*2654012fSReza Sabdar /* 261*2654012fSReza Sabdar * there is still interest in this blob, 262*2654012fSReza Sabdar * no change yet 263*2654012fSReza Sabdar * 264*2654012fSReza Sabdar * returning "old_top" means there is no change in the links 265*2654012fSReza Sabdar */ 266*2654012fSReza Sabdar return (old_top); 267*2654012fSReza Sabdar } 268*2654012fSReza Sabdar 269*2654012fSReza Sabdar /* 270*2654012fSReza Sabdar * no one cares about this data anymore 271*2654012fSReza Sabdar * find out how to delete it 272*2654012fSReza Sabdar */ 273*2654012fSReza Sabdar do { 274*2654012fSReza Sabdar if (chain_link == link) { 275*2654012fSReza Sabdar tlm_chain_link_t *next; 276*2654012fSReza Sabdar tlm_chain_link_t *prev; 277*2654012fSReza Sabdar 278*2654012fSReza Sabdar /* 279*2654012fSReza Sabdar * If there are one or two elements in the list, then 280*2654012fSReza Sabdar * the prev and next pointers point to one element in 281*2654012fSReza Sabdar * the list, the element itself and the other element 282*2654012fSReza Sabdar * correspondingly. So we must distinguish if there 283*2654012fSReza Sabdar * are only one or two elements in the list. If 284*2654012fSReza Sabdar * either of the 'prev' or 'next' pointers point to 285*2654012fSReza Sabdar * the link itself, then we have only one element in 286*2654012fSReza Sabdar * the list. 287*2654012fSReza Sabdar */ 288*2654012fSReza Sabdar if (link->tc_next == link->tc_prev && 289*2654012fSReza Sabdar link->tc_next == link) { 290*2654012fSReza Sabdar /* 291*2654012fSReza Sabdar * there is only this one link in the chain 292*2654012fSReza Sabdar * delete this and the chain is empty 293*2654012fSReza Sabdar */ 294*2654012fSReza Sabdar new_top = 0; 295*2654012fSReza Sabdar } else { 296*2654012fSReza Sabdar new_top = link->tc_next; 297*2654012fSReza Sabdar } 298*2654012fSReza Sabdar next = link->tc_next; 299*2654012fSReza Sabdar prev = link->tc_prev; 300*2654012fSReza Sabdar prev->tc_next = next; 301*2654012fSReza Sabdar next->tc_prev = prev; 302*2654012fSReza Sabdar free(link->tc_data); 303*2654012fSReza Sabdar free(link); 304*2654012fSReza Sabdar return (new_top); 305*2654012fSReza Sabdar } 306*2654012fSReza Sabdar chain_link = chain_link->tc_next; 307*2654012fSReza Sabdar } while (chain_link != old_top); 308*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "TAPE BACKUP> un_ref target not found."); 309*2654012fSReza Sabdar return (old_top); 310*2654012fSReza Sabdar } 311*2654012fSReza Sabdar 312*2654012fSReza Sabdar /* 313*2654012fSReza Sabdar * the following section is global, but not really part of the 314*2654012fSReza Sabdar * public interface. Use of this outside of the tlm_*.c files 315*2654012fSReza Sabdar * is for special cases only. 316*2654012fSReza Sabdar */ 317*2654012fSReza Sabdar 318*2654012fSReza Sabdar /* 319*2654012fSReza Sabdar * add a new tape library data blob to the list of libraries 320*2654012fSReza Sabdar * returns the new tape library data blob just created 321*2654012fSReza Sabdar */ 322*2654012fSReza Sabdar int 323*2654012fSReza Sabdar tlm_insert_new_library(scsi_link_t *slink) 324*2654012fSReza Sabdar { 325*2654012fSReza Sabdar tlm_library_t **p_library = &tlm_info.ti_library; 326*2654012fSReza Sabdar tlm_library_t *library = ndmp_malloc(sizeof (tlm_library_t)); 327*2654012fSReza Sabdar 328*2654012fSReza Sabdar while (*p_library != NULL) { 329*2654012fSReza Sabdar p_library = &(*p_library)->tl_next; 330*2654012fSReza Sabdar } 331*2654012fSReza Sabdar tlm_info.ti_library_count++; 332*2654012fSReza Sabdar library->tl_number = tlm_info.ti_library_count; 333*2654012fSReza Sabdar library->tl_slink = slink; 334*2654012fSReza Sabdar library->tl_capability_robot = TRUE; 335*2654012fSReza Sabdar *p_library = library; 336*2654012fSReza Sabdar return (library->tl_number); 337*2654012fSReza Sabdar } 338*2654012fSReza Sabdar 339*2654012fSReza Sabdar /* 340*2654012fSReza Sabdar * add a new tape drive data blob to the list of drives in a library 341*2654012fSReza Sabdar * returns the new tape drive data blob just created 342*2654012fSReza Sabdar */ 343*2654012fSReza Sabdar int 344*2654012fSReza Sabdar tlm_insert_new_drive(int lib) 345*2654012fSReza Sabdar { 346*2654012fSReza Sabdar tlm_library_t *library = tlm_library(lib); 347*2654012fSReza Sabdar tlm_drive_t *drive = ndmp_malloc(sizeof (tlm_drive_t)); 348*2654012fSReza Sabdar tlm_drive_t **p_drive = &library->tl_drive; 349*2654012fSReza Sabdar 350*2654012fSReza Sabdar while (*p_drive != NULL) { 351*2654012fSReza Sabdar p_drive = &(*p_drive)->td_next; 352*2654012fSReza Sabdar } 353*2654012fSReza Sabdar library->tl_drive_count++; 354*2654012fSReza Sabdar library->tl_capability_drives = TRUE; 355*2654012fSReza Sabdar 356*2654012fSReza Sabdar drive->td_library = library; 357*2654012fSReza Sabdar drive->td_number = library->tl_drive_count; 358*2654012fSReza Sabdar *p_drive = drive; 359*2654012fSReza Sabdar return (drive->td_number); 360*2654012fSReza Sabdar } 361*2654012fSReza Sabdar 362*2654012fSReza Sabdar /* 363*2654012fSReza Sabdar * add a new tape slot data blob to the list of slots in a library 364*2654012fSReza Sabdar * returns the new tape slot data blob just created 365*2654012fSReza Sabdar */ 366*2654012fSReza Sabdar int 367*2654012fSReza Sabdar tlm_insert_new_slot(int lib) 368*2654012fSReza Sabdar { 369*2654012fSReza Sabdar tlm_library_t *library = tlm_library(lib); 370*2654012fSReza Sabdar tlm_slot_t *slot = ndmp_malloc(sizeof (tlm_slot_t)); 371*2654012fSReza Sabdar tlm_slot_t **p_slot = &library->tl_slot; 372*2654012fSReza Sabdar 373*2654012fSReza Sabdar while (*p_slot != NULL) { 374*2654012fSReza Sabdar p_slot = &(*p_slot)->ts_next; 375*2654012fSReza Sabdar } 376*2654012fSReza Sabdar library->tl_slot_count++; 377*2654012fSReza Sabdar library->tl_capability_slots = TRUE; 378*2654012fSReza Sabdar 379*2654012fSReza Sabdar slot->ts_library = library; 380*2654012fSReza Sabdar slot->ts_number = library->tl_slot_count; 381*2654012fSReza Sabdar *p_slot = slot; 382*2654012fSReza Sabdar return (slot->ts_number); 383*2654012fSReza Sabdar } 384