check: allow '-e testid' to exclude a single test
[xfstests-dev.git] / dmapi / src / common / lib / find_session.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
4  * All Rights Reserved.
5  */
6
7 #include <lib/hsm.h>
8
9 #include <string.h>
10
11 /*******************************************************************************
12 *
13 * NAME
14 *       find_test_session - find or create a test DMAPI session.
15 *
16 * DESCRIPTION
17 *       find_test_session() is used to find a test DMAPI session to
18 *       use.  There is only one test session per host; all test processes
19 *       share the same session.  If the session does not already exist,
20 *       then the first process to call find_test_session() causes
21 *       the session to be created.
22 *
23 *       Note: It is possible for N different programs to call this routine
24 *       at the same time.  Each would find that a test session does not
25 *       exist, and each one would then create a new test session.  Since
26 *       excess test sessions are not automatically released on death of
27 *       process, we need to make sure that we don't leave such excess
28 *       sessions around.  So, after creating a session we go back and find
29 *       the test session with the lowest session number.  If it is ours,
30 *       great; we are done.  If not, then we must destroy our session
31 *       and use the one with the lower session ID.  There is still a risk
32 *       here of creating a session and crashing before it can be removed
33 *       again.  To deal with this, the daemon will periodically remove all
34 *       test sessions except for the one with the lowest ID value.
35 *
36 * RETURN VALUE
37 *       None.
38 *
39 *******************************************************************************/
40
41 #define TEST_MSG        "DMAPI test session"
42
43 static int
44 session_compare(
45 const   void    *a,
46 const   void    *b)
47 {
48         return(*((dm_sessid_t *)a) - *((dm_sessid_t *)b));
49 }
50
51 extern void
52 find_test_session(
53         dm_sessid_t     *session)
54 {
55         char            buffer[DM_SESSION_INFO_LEN];
56         dm_sessid_t     *sidbuf = NULL;
57         dm_sessid_t     new_session;
58         u_int           allocelem = 0;
59         u_int           nelem;
60         size_t          rlen;
61         int             error;
62         u_int           i;
63
64         /* Retrieve the list of all active sessions on the host. */
65
66         nelem = 100;            /* a reasonable first guess */
67         do {
68                 if (allocelem < nelem) {
69                         allocelem = nelem;
70                         sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
71                         if (sidbuf == NULL) {
72                                 fprintf(stderr, "realloc of %lu bytes failed\n",
73                                         (unsigned long) nelem * sizeof(*sidbuf));
74                                 exit(1);
75                         }
76                 }
77                 error = dm_getall_sessions(allocelem, sidbuf, &nelem);
78         } while (error < 0 && errno == E2BIG);
79
80         /* If an error occurred, translate it into something meaningful. */
81
82         if (error < 0) {
83                 fprintf(stderr, "unexpected dm_getall_sessions failure, %s\n",
84                         strerror(errno));
85                 free(sidbuf);
86                 exit(1);
87         }
88
89         /* We have the list of all active sessions.  Scan the list looking
90            for an existing "test" session that we can use.  The list must
91            first be sorted in case other processes happen to be creating test
92            sessions at the same time; we need to make sure that we pick the one
93            with the lowest session ID.
94         */
95
96         qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
97
98         for (i = 0; i < nelem; i++) {
99                 error = dm_query_session(sidbuf[i], sizeof(buffer),
100                                 buffer, &rlen);
101                 if (error < 0) {
102                         fprintf(stderr, "unexpected dm_query_session "
103                                 "failure, %s\n", strerror(errno));
104                         free(sidbuf);
105                         exit(1);
106                 }
107
108                 if (!strncmp(buffer, TEST_MSG, strlen(TEST_MSG)))
109                         break;
110         }
111         if (i < nelem) {
112                 *session = (dm_sessid_t)sidbuf[i];
113                 free(sidbuf);
114                 return;
115         }
116
117         /* No test session exists, so we have to create one ourselves. */
118
119         if (dm_create_session(DM_NO_SESSION, TEST_MSG, &new_session) != 0) {
120                 fprintf(stderr, "dm_create_session failed, %s\n",
121                         strerror(errno));
122                 free(sidbuf);
123                 exit(1);
124         }
125
126         /* Now re-retrieve the list of active sessions. */
127
128         do {
129                 if (allocelem < nelem) {
130                         allocelem = nelem;
131                         sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
132                         if (sidbuf == NULL) {
133                                 fprintf(stderr, "realloc of %lu bytes failed\n",
134                                         (unsigned long) nelem * sizeof(*sidbuf));
135                                 exit(1);
136                         }
137                 }
138                 error = dm_getall_sessions(allocelem, sidbuf, &nelem);
139         } while (error < 0 && errno == E2BIG);
140
141         if (error < 0) {
142                 fprintf(stderr, "dm_getall_sessions failed, %s\n",
143                         strerror(errno));
144                 free(sidbuf);
145                 exit(1);
146         }
147
148         /* Sort the session ID list into ascending ID order, then find the
149            test session with the lowest session ID.  We better find at
150            least one since we created one!
151         */
152
153         qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
154
155         for (i = 0; i < nelem; i++) {
156                 error = dm_query_session(sidbuf[i], sizeof(buffer),
157                                 buffer, &rlen);
158                 if (error < 0) {
159                         fprintf(stderr, "dm_query_session failed, %s\n",
160                                 strerror(errno));
161                         free(sidbuf);
162                         exit(1);
163                 }
164                 if (!strncmp(buffer, TEST_MSG, strlen(TEST_MSG)))
165                         break;
166         }
167         if (i == nelem) {
168                 fprintf(stderr, "can't find the session we created\n");
169                 free(sidbuf);
170                 exit(1);
171         }
172         *session = (dm_sessid_t)sidbuf[i];
173         free(sidbuf);
174
175         /* If the session we are going to use is not the one we created,
176            then we need to get rid of the created one.
177         */
178
179         if (*session != new_session) {
180                 if ((new_session) != 0) {
181                         fprintf(stderr, "dm_destroy_session failed, %s\n",
182                                 strerror(errno));
183                         exit(1);
184                 }
185         }
186 }