1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * - Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 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 */ 59 int 60 tlm_library_count(void) 61 { 62 int lib; 63 tlm_library_t *library; 64 65 for (lib = 1; lib <= tlm_info.ti_library_count; lib++) { 66 library = tlm_library(lib); 67 if (library != NULL && 68 library->tl_drive_count == 0) { 69 return (0); 70 } 71 } 72 return (tlm_info.ti_library_count); 73 } 74 75 /* 76 * get the library whose number matches 77 */ 78 tlm_library_t * 79 tlm_library(int lib) 80 { 81 tlm_library_t *library = tlm_info.ti_library; 82 while (library != NULL) { 83 if (library->tl_number == lib) { 84 return (library); 85 } 86 library = library->tl_next; 87 } 88 errno = TLM_ERROR_RANGE; 89 return (NULL); 90 } 91 92 /* 93 * get the info about this drive 94 */ 95 tlm_drive_t * 96 tlm_drive(int lib, int drv) 97 { 98 tlm_drive_t *drive; 99 tlm_library_t *library = tlm_library(lib); 100 101 if (library == NULL) { 102 return (NULL); 103 } 104 drive = library->tl_drive; 105 while (drive != NULL) { 106 if (drv == drive->td_number) { 107 return (drive); 108 } 109 drive = drive->td_next; 110 } 111 return (NULL); 112 } 113 114 /* 115 * get the info about this slot 116 */ 117 tlm_slot_t * 118 tlm_slot(int lib, int slt) 119 { 120 tlm_slot_t *slot = NULL; 121 tlm_library_t *library = tlm_library(lib); 122 123 if (library != NULL) 124 slot = library->tl_slot; 125 while (slot != NULL) { 126 if (slt == slot->ts_number) { 127 return (slot); 128 } 129 slot = slot->ts_next; 130 } 131 return (NULL); 132 } 133 134 /* 135 * add a link to the INFO chain 136 */ 137 tlm_job_stats_t * 138 tlm_new_job_stats(char *name) 139 { 140 tlm_chain_link_t *new_link; 141 tlm_job_stats_t *job_stats; 142 143 new_link = ndmp_malloc(sizeof (tlm_chain_link_t)); 144 if (new_link == 0) 145 return (0); 146 147 job_stats = ndmp_malloc(sizeof (tlm_job_stats_t)); 148 if (job_stats == 0) { 149 free(new_link); 150 return (0); 151 } 152 153 new_link->tc_ref_count = 1; 154 new_link->tc_data = (void *)job_stats; 155 (void) strlcpy(job_stats->js_job_name, name, TLM_MAX_BACKUP_JOB_NAME); 156 157 (void) mutex_lock(&jstat_mtx); 158 if (tlm_info.ti_job_stats == 0) { 159 new_link->tc_next = new_link; 160 new_link->tc_prev = new_link; 161 } else { 162 tlm_chain_link_t *next_link = tlm_info.ti_job_stats; 163 tlm_chain_link_t *prev_link = next_link->tc_prev; 164 165 new_link->tc_next = next_link; 166 new_link->tc_prev = prev_link; 167 prev_link->tc_next = new_link; 168 next_link->tc_prev = new_link; 169 } 170 tlm_info.ti_job_stats = new_link; 171 (void) mutex_unlock(&jstat_mtx); 172 173 return (job_stats); 174 } 175 176 /* 177 * make sure this Job Stats buffer is not deleted while we use it 178 */ 179 tlm_job_stats_t * 180 tlm_ref_job_stats(char *name) 181 { 182 static tlm_job_stats_t fake_job_stats; 183 tlm_chain_link_t *link; 184 185 (void) mutex_lock(&jstat_mtx); 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, 262 * no change yet 263 * 264 * returning "old_top" means there is no change in the links 265 */ 266 return (old_top); 267 } 268 269 /* 270 * no one cares about this data anymore 271 * find out how to delete it 272 */ 273 do { 274 if (chain_link == link) { 275 tlm_chain_link_t *next; 276 tlm_chain_link_t *prev; 277 278 /* 279 * If there are one or two elements in the list, then 280 * the prev and next pointers point to one element in 281 * the list, the element itself and the other element 282 * correspondingly. So we must distinguish if there 283 * are only one or two elements in the list. If 284 * either of the 'prev' or 'next' pointers point to 285 * the link itself, then we have only one element in 286 * the list. 287 */ 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) { 329 p_library = &(*p_library)->tl_next; 330 } 331 tlm_info.ti_library_count++; 332 library->tl_number = tlm_info.ti_library_count; 333 library->tl_slink = slink; 334 library->tl_capability_robot = TRUE; 335 *p_library = library; 336 return (library->tl_number); 337 } 338 339 /* 340 * add a new tape drive data blob to the list of drives in a library 341 * returns the new tape drive data blob just created 342 */ 343 int 344 tlm_insert_new_drive(int lib) 345 { 346 tlm_library_t *library = tlm_library(lib); 347 tlm_drive_t *drive = ndmp_malloc(sizeof (tlm_drive_t)); 348 tlm_drive_t **p_drive = &library->tl_drive; 349 350 while (*p_drive != NULL) { 351 p_drive = &(*p_drive)->td_next; 352 } 353 library->tl_drive_count++; 354 library->tl_capability_drives = TRUE; 355 356 drive->td_library = library; 357 drive->td_number = library->tl_drive_count; 358 *p_drive = drive; 359 return (drive->td_number); 360 } 361 362 /* 363 * add a new tape slot data blob to the list of slots in a library 364 * returns the new tape slot data blob just created 365 */ 366 int 367 tlm_insert_new_slot(int lib) 368 { 369 tlm_library_t *library = tlm_library(lib); 370 tlm_slot_t *slot = ndmp_malloc(sizeof (tlm_slot_t)); 371 tlm_slot_t **p_slot = &library->tl_slot; 372 373 while (*p_slot != NULL) { 374 p_slot = &(*p_slot)->ts_next; 375 } 376 library->tl_slot_count++; 377 library->tl_capability_slots = TRUE; 378 379 slot->ts_library = library; 380 slot->ts_number = library->tl_slot_count; 381 *p_slot = slot; 382 return (slot->ts_number); 383 } 384