xref: /illumos-gate/usr/src/cmd/ndmpd/tlm/tlm_info.c (revision 2654012f)
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
tlm_library_count(void)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 *
tlm_library(int lib)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 *
tlm_drive(int lib,int drv)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 *
tlm_slot(int lib,int slt)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	*
tlm_new_job_stats(char * name)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	*
tlm_ref_job_stats(char * name)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
tlm_un_ref_job_stats(char * name)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 *
tlm_un_ref(tlm_chain_link_t * old_top,tlm_chain_link_t * link)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
tlm_insert_new_library(scsi_link_t * slink)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
tlm_insert_new_drive(int lib)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
tlm_insert_new_slot(int lib)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