pthread_mutex_t vol_glock_mutex;
pthread_mutex_t vol_attach_mutex;
pthread_mutex_t vol_fsync_mutex;
+pthread_mutex_t vol_trans_mutex;
pthread_cond_t vol_put_volume_cond;
pthread_cond_t vol_sleep_cond;
#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_PTHREAD_ENV
assert(pthread_mutex_init(&vol_glock_mutex, NULL) == 0);
assert(pthread_mutex_init(&vol_attach_mutex, NULL) == 0);
+ assert(pthread_mutex_init(&vol_fsync_mutex, NULL) == 0);
+ assert(pthread_mutex_init(&vol_trans_mutex, NULL) == 0);
assert(pthread_cond_init(&vol_put_volume_cond, NULL) == 0);
assert(pthread_cond_init(&vol_sleep_cond, NULL) == 0);
#else /* AFS_PTHREAD_ENV */
extern pthread_mutex_t vol_glock_mutex;
extern pthread_mutex_t vol_attach_mutex;
extern pthread_mutex_t vol_fsync_mutex;
+extern pthread_mutex_t vol_trans_mutex;
extern pthread_cond_t vol_put_volume_cond;
extern pthread_cond_t vol_sleep_cond;
#define VATTACH_LOCK \
assert(pthread_mutex_lock(&vol_fsync_mutex) == 0);
#define VFSYNC_UNLOCK \
assert(pthread_mutex_unlock(&vol_fsync_mutex) == 0);
+#define VTRANS_LOCK \
+ assert(pthread_mutex_lock(&vol_trans_mutex) == 0);
+#define VTRANS_UNLOCK \
+ assert(pthread_mutex_unlock(&vol_trans_mutex) == 0);
#else /* AFS_PTHREAD_ENV */
#define VATTACH_LOCK
#define VATTACH_UNLOCK
#define VOL_UNLOCK
#define VFSYNC_LOCK
#define VFSYNC_UNLOCK
+#define VTRANS_LOCK
+#define VTRANS_UNLOCK
#endif /* AFS_PTHREAD_ENV */
typedef enum { fileServer, volumeUtility, salvager } ProgramType;
static
MyBeforeProc(struct rx_call *acall)
{
+ VTRANS_LOCK;
runningCalls++;
+ VTRANS_UNLOCK;
return 0;
}
static
MyAfterProc(struct rx_call *acall, afs_int32 code)
{
+ VTRANS_LOCK;
runningCalls--;
+ VTRANS_UNLOCK;
return 0;
}
{
/* if there are no running calls, and there are no active transactions, then
* it should be safe to release any partition locks we've accumulated */
+ VTRANS_LOCK;
if (runningCalls == 0 && TransList() == (struct volser_trans *)0) {
+ VTRANS_UNLOCK;
VPFullUnlock(); /* in volprocs.c */
- }
+ } else
+ VTRANS_UNLOCK;
}
/* background daemon for timing out transactions */
#else /* AFS_PTHREAD_ENV */
IOMGR_Sleep(TTrun);
#endif
+ VTRANS_LOCK;
for (tt = TransList(); tt; tt = tt->next) {
if ((strcmp(tt->lastProcName, "DeleteVolume") == 0)
|| (strcmp(tt->lastProcName, "Clone") == 0)
break;
}
if (tt) {
+ VTRANS_UNLOCK;
sleep(TTsleep);
- }
+ } else
+ VTRANS_UNLOCK;
}
}
}
#include <sys/time.h>
#endif
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#ifdef AFS_NT40_ENV
+#include <fcntl.h>
+#include <winsock2.h>
+#else
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#endif
+#include <dirent.h>
+#include <sys/stat.h>
+#include <afs/afsint.h>
+#include <signal.h>
+#ifdef AFS_PTHREAD_ENV
+#include <assert.h>
+#else /* AFS_PTHREAD_ENV */
+#include <afs/assert.h>
+#endif /* AFS_PTHREAD_ENV */
+#include <afs/prs_fs.h>
+#include <afs/nfs.h>
+#include <lwp.h>
+#include <lock.h>
+#include <afs/auth.h>
+#include <afs/cellconfig.h>
+#include <afs/keys.h>
+#include <rx/rx.h>
+#include <ubik.h>
+#include <afs/ihandle.h>
+#ifdef AFS_NT40_ENV
+#include <afs/ntops.h>
+#endif
+#include <afs/vnode.h>
+#include <afs/volume.h>
+
#ifdef HAVE_STRING_H
#include <string.h>
#else
#endif
#endif
-#include <rx/rx.h>
#include "volser.h"
/*@printflike@*/ extern void Log(const char *format, ...);
struct timeval tp;
struct timezone tzp;
+ VTRANS_LOCK;
/* don't allow the same volume to be attached twice */
for (tt = allTrans; tt; tt = tt->next) {
if ((tt->volid == avol) && (tt->partition == apart)) {
+ VTRANS_UNLOCK;
return (struct volser_trans *)0; /* volume busy */
}
}
+ VTRANS_UNLOCK;
tt = (struct volser_trans *)malloc(sizeof(struct volser_trans));
memset(tt, 0, sizeof(struct volser_trans));
tt->volid = avol;
tt->partition = apart;
- tt->next = allTrans;
- tt->tid = transCounter++;
tt->refCount = 1;
tt->rxCallPtr = (struct rx_call *)0;
strcpy(tt->lastProcName, "");
gettimeofday(&tp, &tzp);
tt->creationTime = tp.tv_sec;
- allTrans = tt;
tt->time = FT_ApproxTime();
+ VTRANS_LOCK;
+ tt->tid = transCounter++;
+ tt->next = allTrans;
+ allTrans = tt;
+ VTRANS_UNLOCK;
return tt;
}
register afs_int32 atrans;
{
register struct volser_trans *tt;
+ VTRANS_LOCK;
for (tt = allTrans; tt; tt = tt->next) {
if (tt->tid == atrans) {
tt->time = FT_ApproxTime();
tt->refCount++;
+ VTRANS_UNLOCK;
return tt;
}
}
+ VTRANS_UNLOCK;
return (struct volser_trans *)0;
}
atrans->tflags |= TTDeleted;
return 0;
}
+
/* otherwise we zap it ourselves */
+ VTRANS_LOCK;
lt = &allTrans;
for (tt = *lt; tt; lt = &tt->next, tt = *lt) {
if (tt == atrans) {
tt->volume = NULL;
*lt = tt->next;
free(tt);
+ VTRANS_UNLOCK;
return 0;
}
}
+ VTRANS_UNLOCK;
return -1; /* failed to find the transaction in the generic list */
}
now = FT_ApproxTime();
+ VTRANS_LOCK;
for (tt = allTrans; tt; tt = nt) {
nt = tt->next; /* remember in case we zap it */
if (tt->time + OLDTRANSWARN < now) {
GCDeletes++;
}
}
+ VTRANS_UNLOCK;
return 0;
}