2 * Copyright 2000, International Business Machines Corporation and others.
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
13 * Instituition: ITC, CMU
17 #include <afsconfig.h>
18 #include <afs/param.h>
23 #include <afs/afsutil.h>
26 #include <afs/afsint.h>
27 #include <afs/prs_fs.h>
31 #include <afs/cellconfig.h>
35 #include <afs/ihandle.h>
37 #include <afs/ntops.h>
39 #include <afs/vnode.h>
40 #include <afs/volume.h>
44 #include "volser_internal.h"
46 static struct volser_trans *allTrans = 0;
47 static afs_int32 transCounter = 1;
49 /* create a new transaction, returning ptr to same with high ref count */
51 NewTrans(afs_uint32 avol, afs_int32 apart)
53 /* set volid, next, partition */
54 struct volser_trans *tt, *newtt;
57 newtt = calloc(1, sizeof(struct volser_trans));
59 /* don't allow the same volume to be attached twice */
60 for (tt = allTrans; tt; tt = tt->next) {
61 if ((tt->volid == avol) && (tt->partition == apart)) {
64 return (struct volser_trans *)0; /* volume busy */
69 tt->partition = apart;
71 tt->rxCallPtr = (struct rx_call *)0;
72 strcpy(tt->lastProcName, "");
73 gettimeofday(&tp, NULL);
74 tt->creationTime = tp.tv_sec;
75 tt->time = FT_ApproxTime();
76 tt->tid = transCounter++;
78 VTRANS_OBJ_LOCK_INIT(tt);
84 /* find a trans, again returning with high ref count */
86 FindTrans(afs_int32 atrans)
88 struct volser_trans *tt;
90 for (tt = allTrans; tt; tt = tt->next) {
91 if (tt->tid == atrans) {
92 tt->time = FT_ApproxTime();
99 return (struct volser_trans *)0;
102 /* delete transaction if refcount == 1, otherwise queue delete for later. Does implicit TRELE */
104 DeleteTrans(struct volser_trans *atrans, afs_int32 lock)
106 struct volser_trans *tt, **lt;
109 if (lock) VTRANS_LOCK;
110 if (atrans->refCount > 1) {
111 /* someone else is using it now */
113 atrans->tflags |= TTDeleted;
114 if (lock) VTRANS_UNLOCK;
118 /* otherwise we zap it ourselves */
120 for (tt = *lt; tt; lt = &tt->next, tt = *lt) {
123 VDetachVolume(&error, tt->volume);
126 rxi_CallError(tt->rxCallPtr, RX_CALL_DEAD);
128 VTRANS_OBJ_LOCK_DESTROY(tt);
130 if (lock) VTRANS_UNLOCK;
134 if (lock) VTRANS_UNLOCK;
135 return -1; /* failed to find the transaction in the generic list */
138 /* THOLD is a macro defined in volser.h */
140 /* put a transaction back */
142 TRELE(struct volser_trans *at)
145 if (at->refCount == 0) {
146 Log("TRELE: bad refcount\n");
148 return VOLSERTRELE_ERROR;
151 at->time = FT_ApproxTime(); /* we're still using it */
152 if (at->refCount == 1 && (at->tflags & TTDeleted)) {
157 /* otherwise simply drop refcount */
163 /* look for old transactions and delete them */
164 #define OLDTRANSTIME 600 /* seconds */
165 #define OLDTRANSWARN 300 /* seconds */
166 static int GCDeletes = 0;
170 struct volser_trans *tt, *nt;
173 now = FT_ApproxTime();
176 for (tt = allTrans; tt; tt = nt) {
177 nt = tt->next; /* remember in case we zap it */
178 if (tt->time + OLDTRANSWARN < now) {
179 Log("trans %u on volume %u %s than %d seconds\n", tt->tid,
181 ((tt->refCount > 0) ? "is older" : "has been idle for more"),
182 (((now - tt->time) / GCWAKEUP) * GCWAKEUP));
184 if (tt->refCount > 0)
186 if (tt->time + OLDTRANSTIME < now) {
187 Log("trans %u on volume %u has timed out\n", tt->tid, tt->volid);
189 tt->refCount++; /* we're using it now */
191 if (tt->volume && V_destroyMe(tt->volume) == DESTROY_ME
192 && !(tt->vflags & VTDeleted)) {
196 Log("Deleting timed-out temporary volume %lu\n",
197 (long unsigned) tt->volid);
200 tt->vflags |= VTDeleted;
201 VTRANS_OBJ_UNLOCK(tt);
204 VPurgeVolume(&error, tt->volume);
208 DeleteTrans(tt, 0); /* drops refCount or deletes it */
216 /*return the head of the transaction list */
217 struct volser_trans *