2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
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
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
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.
41 #include "tlm_proto.h"
42 #include <sys/errno.h>
45 extern tlm_chain_link_t
*tlm_un_ref(tlm_chain_link_t
*old_top
,
46 tlm_chain_link_t
*link
);
48 static tlm_info_t tlm_info
;
51 * Mutex for concurrent access to job_stats
57 * get the number of libraries
60 tlm_library_count(void)
63 tlm_library_t
*library
;
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) {
72 return (tlm_info
.ti_library_count
);
76 * get the library whose number matches
81 tlm_library_t
*library
= tlm_info
.ti_library
;
82 while (library
!= NULL
) {
83 if (library
->tl_number
== lib
) {
86 library
= library
->tl_next
;
88 errno
= TLM_ERROR_RANGE
;
93 * get the info about this drive
96 tlm_drive(int lib
, int drv
)
99 tlm_library_t
*library
= tlm_library(lib
);
101 if (library
== NULL
) {
104 drive
= library
->tl_drive
;
105 while (drive
!= NULL
) {
106 if (drv
== drive
->td_number
) {
109 drive
= drive
->td_next
;
115 * get the info about this slot
118 tlm_slot(int lib
, int slt
)
120 tlm_slot_t
*slot
= NULL
;
121 tlm_library_t
*library
= tlm_library(lib
);
124 slot
= library
->tl_slot
;
125 while (slot
!= NULL
) {
126 if (slt
== slot
->ts_number
) {
129 slot
= slot
->ts_next
;
135 * add a link to the INFO chain
138 tlm_new_job_stats(char *name
)
140 tlm_chain_link_t
*new_link
;
141 tlm_job_stats_t
*job_stats
;
143 new_link
= ndmp_malloc(sizeof (tlm_chain_link_t
));
147 job_stats
= ndmp_malloc(sizeof (tlm_job_stats_t
));
148 if (job_stats
== 0) {
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
);
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
;
162 tlm_chain_link_t
*next_link
= tlm_info
.ti_job_stats
;
163 tlm_chain_link_t
*prev_link
= next_link
->tc_prev
;
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
;
170 tlm_info
.ti_job_stats
= new_link
;
171 (void) mutex_unlock(&jstat_mtx
);
177 * make sure this Job Stats buffer is not deleted while we use it
180 tlm_ref_job_stats(char *name
)
182 static tlm_job_stats_t fake_job_stats
;
183 tlm_chain_link_t
*link
;
185 (void) mutex_lock(&jstat_mtx
);
186 link
= tlm_info
.ti_job_stats
;
189 * our tables are empty
191 (void) mutex_unlock(&jstat_mtx
);
192 return (&fake_job_stats
);
196 tlm_job_stats_t
*job_stats
;
197 job_stats
= (tlm_job_stats_t
*)link
->tc_data
;
199 if (strcmp(job_stats
->js_job_name
, name
) == 0) {
200 link
->tc_ref_count
++;
201 (void) mutex_unlock(&jstat_mtx
);
204 link
= link
->tc_next
;
205 } while (link
!= tlm_info
.ti_job_stats
);
207 "TAPE BACKUP> Ref for job [%s] was not found", name
);
208 (void) mutex_unlock(&jstat_mtx
);
210 return (&fake_job_stats
);
214 * remove a link to the INFO chain
217 tlm_un_ref_job_stats(char *name
)
219 tlm_chain_link_t
*link
;
221 (void) mutex_lock(&jstat_mtx
);
222 link
= tlm_info
.ti_job_stats
;
224 NDMP_LOG(LOG_DEBUG
, "TAPE BACKUP>"
225 " Internal error for job [%s], could not delete", name
);
229 tlm_job_stats_t
*job_stats
;
230 job_stats
= (tlm_job_stats_t
*)link
->tc_data
;
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
);
238 link
= link
->tc_next
;
239 } while (link
!= tlm_info
.ti_job_stats
);
240 (void) mutex_unlock(&jstat_mtx
);
242 "TAPE BACKUP> Delete for job [%s] was not found", name
);
246 * one party does not care about this blob, can we let it go?
249 tlm_un_ref(tlm_chain_link_t
*old_top
, tlm_chain_link_t
*link
)
251 tlm_chain_link_t
*chain_link
= old_top
;
252 tlm_chain_link_t
*new_top
;
255 * count down the number of
256 * interested parties for this blob
258 link
->tc_ref_count
--;
259 if (link
->tc_ref_count
> 0) {
261 * there is still interest in this blob,
264 * returning "old_top" means there is no change in the links
270 * no one cares about this data anymore
271 * find out how to delete it
274 if (chain_link
== link
) {
275 tlm_chain_link_t
*next
;
276 tlm_chain_link_t
*prev
;
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
288 if (link
->tc_next
== link
->tc_prev
&&
289 link
->tc_next
== link
) {
291 * there is only this one link in the chain
292 * delete this and the chain is empty
296 new_top
= link
->tc_next
;
298 next
= link
->tc_next
;
299 prev
= link
->tc_prev
;
300 prev
->tc_next
= next
;
301 next
->tc_prev
= prev
;
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.");
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.
319 * add a new tape library data blob to the list of libraries
320 * returns the new tape library data blob just created
323 tlm_insert_new_library(scsi_link_t
*slink
)
325 tlm_library_t
**p_library
= &tlm_info
.ti_library
;
326 tlm_library_t
*library
= ndmp_malloc(sizeof (tlm_library_t
));
328 while (*p_library
!= NULL
) {
329 p_library
= &(*p_library
)->tl_next
;
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
);
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
344 tlm_insert_new_drive(int lib
)
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
;
350 while (*p_drive
!= NULL
) {
351 p_drive
= &(*p_drive
)->td_next
;
353 library
->tl_drive_count
++;
354 library
->tl_capability_drives
= TRUE
;
356 drive
->td_library
= library
;
357 drive
->td_number
= library
->tl_drive_count
;
359 return (drive
->td_number
);
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
367 tlm_insert_new_slot(int lib
)
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
;
373 while (*p_slot
!= NULL
) {
374 p_slot
= &(*p_slot
)->ts_next
;
376 library
->tl_slot_count
++;
377 library
->tl_capability_slots
= TRUE
;
379 slot
->ts_library
= library
;
380 slot
->ts_number
= library
->tl_slot_count
;
382 return (slot
->ts_number
);