volser: Tidy header includes
[openafs.git] / src / volser / voltrans.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  *  Module:         Voltrans.c
12  *  System:         Volser
13  *  Instituition:           ITC, CMU
14  *  Date:                   December, 88
15  */
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 #include <roken.h>
21
22 #ifdef AFS_NT40_ENV
23 #include <afs/afsutil.h>
24 #endif
25
26 #include <afs/afsint.h>
27 #include <afs/afs_assert.h>
28 #include <afs/prs_fs.h>
29 #include <afs/nfs.h>
30 #include <lwp.h>
31 #include <lock.h>
32 #include <afs/cellconfig.h>
33 #include <afs/keys.h>
34 #include <rx/rx.h>
35 #include <ubik.h>
36 #include <afs/ihandle.h>
37 #ifdef AFS_NT40_ENV
38 #include <afs/ntops.h>
39 #endif
40 #include <afs/vnode.h>
41 #include <afs/volume.h>
42
43 #include "volint.h"
44 #include "volser.h"
45 #include "volser_internal.h"
46
47 static struct volser_trans *allTrans = 0;
48 static afs_int32 transCounter = 1;
49
50 /* create a new transaction, returning ptr to same with high ref count */
51 struct volser_trans *
52 NewTrans(afs_uint32 avol, afs_int32 apart)
53 {
54     /* set volid, next, partition */
55     struct volser_trans *tt, *newtt;
56     struct timeval tp;
57     struct timezone tzp;
58
59     newtt = (struct volser_trans *)malloc(sizeof(struct volser_trans));
60     VTRANS_LOCK;
61     /* don't allow the same volume to be attached twice */
62     for (tt = allTrans; tt; tt = tt->next) {
63         if ((tt->volid == avol) && (tt->partition == apart)) {
64             VTRANS_UNLOCK;
65             free(newtt);
66             return (struct volser_trans *)0;    /* volume busy */
67         }
68     }
69     tt = newtt;
70     memset(tt, 0, sizeof(struct volser_trans));
71     tt->volid = avol;
72     tt->partition = apart;
73     tt->refCount = 1;
74     tt->rxCallPtr = (struct rx_call *)0;
75     strcpy(tt->lastProcName, "");
76     gettimeofday(&tp, &tzp);
77     tt->creationTime = tp.tv_sec;
78     tt->time = FT_ApproxTime();
79     tt->tid = transCounter++;
80     tt->next = allTrans;
81     VTRANS_OBJ_LOCK_INIT(tt);
82     allTrans = tt;
83     VTRANS_UNLOCK;
84     return tt;
85 }
86
87 /* find a trans, again returning with high ref count */
88 struct volser_trans *
89 FindTrans(afs_int32 atrans)
90 {
91     struct volser_trans *tt;
92     VTRANS_LOCK;
93     for (tt = allTrans; tt; tt = tt->next) {
94         if (tt->tid == atrans) {
95             tt->time = FT_ApproxTime();
96             tt->refCount++;
97             VTRANS_UNLOCK;
98             return tt;
99         }
100     }
101     VTRANS_UNLOCK;
102     return (struct volser_trans *)0;
103 }
104
105 /* delete transaction if refcount == 1, otherwise queue delete for later.  Does implicit TRELE */
106 afs_int32
107 DeleteTrans(struct volser_trans *atrans, afs_int32 lock)
108 {
109     struct volser_trans *tt, **lt;
110     Error error;
111
112     if (lock) VTRANS_LOCK;
113     if (atrans->refCount > 1) {
114         /* someone else is using it now */
115         atrans->refCount--;
116         atrans->tflags |= TTDeleted;
117         if (lock) VTRANS_UNLOCK;
118         return 0;
119     }
120
121     /* otherwise we zap it ourselves */
122     lt = &allTrans;
123     for (tt = *lt; tt; lt = &tt->next, tt = *lt) {
124         if (tt == atrans) {
125             if (tt->volume)
126                 VDetachVolume(&error, tt->volume);
127             tt->volume = NULL;
128             if (tt->rxCallPtr)
129                 rxi_CallError(tt->rxCallPtr, RX_CALL_DEAD);
130             *lt = tt->next;
131             VTRANS_OBJ_LOCK_DESTROY(tt);
132             free(tt);
133             if (lock) VTRANS_UNLOCK;
134             return 0;
135         }
136     }
137     if (lock) VTRANS_UNLOCK;
138     return -1;                  /* failed to find the transaction in the generic list */
139 }
140
141 /* THOLD is a macro defined in volser.h */
142
143 /* put a transaction back */
144 afs_int32
145 TRELE(struct volser_trans *at)
146 {
147     VTRANS_LOCK;
148     if (at->refCount == 0) {
149         Log("TRELE: bad refcount\n");
150         VTRANS_UNLOCK;
151         return VOLSERTRELE_ERROR;
152     }
153
154     at->time = FT_ApproxTime(); /* we're still using it */
155     if (at->refCount == 1 && (at->tflags & TTDeleted)) {
156         DeleteTrans(at, 0);
157         VTRANS_UNLOCK;
158         return 0;
159     }
160     /* otherwise simply drop refcount */
161     at->refCount--;
162     VTRANS_UNLOCK;
163     return 0;
164 }
165
166 /* look for old transactions and delete them */
167 #define OLDTRANSTIME        600 /* seconds */
168 #define OLDTRANSWARN        300 /* seconds */
169 static int GCDeletes = 0;
170 afs_int32
171 GCTrans(void)
172 {
173     struct volser_trans *tt, *nt;
174     afs_int32 now;
175
176     now = FT_ApproxTime();
177
178     VTRANS_LOCK;
179     for (tt = allTrans; tt; tt = nt) {
180         nt = tt->next;          /* remember in case we zap it */
181         if (tt->time + OLDTRANSWARN < now) {
182             Log("trans %u on volume %u %s than %d seconds\n", tt->tid,
183                 tt->volid,
184                 ((tt->refCount > 0) ? "is older" : "has been idle for more"),
185                 (((now - tt->time) / GCWAKEUP) * GCWAKEUP));
186         }
187         if (tt->refCount > 0)
188             continue;
189         if (tt->time + OLDTRANSTIME < now) {
190             Log("trans %u on volume %u has timed out\n", tt->tid, tt->volid);
191
192             tt->refCount++;     /* we're using it now */
193
194             if (tt->volume && V_destroyMe(tt->volume) == DESTROY_ME
195                 && !(tt->vflags & VTDeleted)) {
196
197                 Error error;
198
199                 Log("Deleting timed-out temporary volume %lu\n",
200                     (long unsigned) tt->volid);
201
202                 VTRANS_OBJ_LOCK(tt);
203                 tt->vflags |= VTDeleted;
204                 VTRANS_OBJ_UNLOCK(tt);
205
206                 VTRANS_UNLOCK;
207                 VPurgeVolume(&error, tt->volume);
208                 VTRANS_LOCK;
209             }
210
211             DeleteTrans(tt, 0); /* drops refCount or deletes it */
212             GCDeletes++;
213         }
214     }
215     VTRANS_UNLOCK;
216     return 0;
217 }
218
219 /*return the head of the transaction list */
220 struct volser_trans *
221 TransList(void)
222 {
223     return (allTrans);
224 }