pthread_mutex_t vol_trans_mutex;
pthread_cond_t vol_put_volume_cond;
pthread_cond_t vol_sleep_cond;
+int vol_attach_threads = 1;
#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_OSF_ENV
}
#endif /* !AFS_HAVE_FFS */
+#ifdef AFS_PTHREAD_ENV
+#include "rx/rx_queue.h"
+typedef struct diskpartition_queue_t {
+ struct rx_queue queue;
+ struct DiskPartition * diskP;
+} diskpartition_queue_t;
+typedef struct vinitvolumepackage_thread_t {
+ struct rx_queue queue;
+ pthread_cond_t thread_done_cv;
+ int n_threads_complete;
+} vinitvolumepackage_thread_t;
+static void * VInitVolumePackageThread(void * args);
+#endif /* AFS_PTHREAD_ENV */
+
struct Lock vol_listLock; /* Lock obtained when listing volumes: prevents a volume from being missed if the volume is attached during a list volumes */
extern struct Lock FSYNC_handler_lock;
bit32 VolumeCacheCheck; /* Incremented everytime a volume goes on line--
* used to stamp volume headers and in-core
* vnodes. When the volume goes on-line the
- * vnode will be invalidated */
+ * vnode will be invalidated
+ * access only with VOL_LOCK held */
int VolumeCacheSize = 200, VolumeGets = 0, VolumeReplacements = 0, Vlooks = 0;
return -1;
if (programType == fileServer) {
- DIR *dirp;
- struct dirent *dp;
struct DiskPartition *diskP;
+#ifdef AFS_PTHREAD_ENV
+ struct vinitvolumepackage_thread_t params;
+ struct diskpartition_queue_t * dpq;
+ int i, len;
+ pthread_t tid;
+ pthread_attr_t attrs;
+
+ assert(pthread_cond_init(¶ms.thread_done_cv,NULL) == 0);
+ queue_Init(¶ms);
+ params.n_threads_complete = 0;
+
+ /* create partition work queue */
+ for (len=0, diskP = DiskPartitionList; diskP; diskP = diskP->next, len++) {
+ dpq = (diskpartition_queue_t *) malloc(sizeof(struct diskpartition_queue_t));
+ assert(dpq != NULL);
+ dpq->diskP = diskP;
+ queue_Prepend(¶ms,dpq);
+ }
+
+ assert(pthread_attr_init(&attrs) == 0);
+ assert(pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED) == 0);
+
+ len = MIN(len, vol_attach_threads);
+
+ VOL_LOCK;
+ for (i=0; i < len; i++) {
+ assert(pthread_create
+ (&tid, &attrs, &VInitVolumePackageThread,
+ ¶ms) == 0);
+ }
+
+ while(params.n_threads_complete < len) {
+ pthread_cond_wait(¶ms.thread_done_cv,&vol_glock_mutex);
+ }
+ VOL_UNLOCK;
+ assert(pthread_cond_destroy(¶ms.thread_done_cv) == 0);
+
+#else /* AFS_PTHREAD_ENV */
+ DIR *dirp;
+ struct dirent *dp;
/* Attach all the volumes in this partition */
for (diskP = DiskPartitionList; diskP; diskP = diskP->next) {
Log("Partition %s: attached %d volumes; %d volumes not attached\n", diskP->name, nAttached, nUnattached);
closedir(dirp);
}
+#endif /* AFS_PTHREAD_ENV */
}
VInit = 2; /* Initialized, and all volumes have been attached */
if (programType == volumeUtility && connect) {
if (!VConnectFS()) {
Log("Unable to connect to file server; aborted\n");
+ Lock_Destroy(&FSYNC_handler_lock);
exit(1);
}
}
return 0;
}
+#ifdef AFS_PTHREAD_ENV
+static void *
+VInitVolumePackageThread(void * args) {
+ int errors = 0; /* Number of errors while finding vice partitions. */
+
+ DIR *dirp;
+ struct dirent *dp;
+ struct DiskPartition *diskP;
+ struct vinitvolumepackage_thread_t * params;
+ struct diskpartition_queue_t * dpq;
+
+ params = (vinitvolumepackage_thread_t *) args;
+
+
+ VOL_LOCK;
+ /* Attach all the volumes in this partition */
+ while (queue_IsNotEmpty(params)) {
+ int nAttached = 0, nUnattached = 0;
+
+ dpq = queue_First(params,diskpartition_queue_t);
+ queue_Remove(dpq);
+ VOL_UNLOCK;
+ diskP = dpq->diskP;
+ free(dpq);
+
+ Log("Partition %s: attaching volumes\n", diskP->name);
+ dirp = opendir(VPartitionPath(diskP));
+ assert(dirp);
+ while ((dp = readdir(dirp))) {
+ char *p;
+ p = strrchr(dp->d_name, '.');
+ if (p != NULL && strcmp(p, VHDREXT) == 0) {
+ Error error;
+ Volume *vp;
+ vp = VAttachVolumeByName(&error, diskP->name, dp->d_name,
+ V_VOLUPD);
+ (*(vp ? &nAttached : &nUnattached))++;
+ if (error == VOFFLINE)
+ Log("Volume %d stays offline (/vice/offline/%s exists)\n", VolumeNumber(dp->d_name), dp->d_name);
+ else if (LogLevel >= 5) {
+ Log("Partition %s: attached volume %d (%s)\n",
+ diskP->name, VolumeNumber(dp->d_name),
+ dp->d_name);
+ }
+ if (vp) {
+ VPutVolume(vp);
+ }
+ }
+ }
+ Log("Partition %s: attached %d volumes; %d volumes not attached\n", diskP->name, nAttached, nUnattached);
+ closedir(dirp);
+ VOL_LOCK;
+ }
+
+ params->n_threads_complete++;
+ pthread_cond_signal(¶ms->thread_done_cv);
+ VOL_UNLOCK;
+ return NULL;
+}
+#endif /* AFS_PTHREAD_ENV */
+
/* This must be called by any volume utility which needs to run while the
file server is also running. This is separated from VInitVolumePackage so
that a utility can fork--and each of the children can independently
}
DiskToVolumeHeader(&iheader, &diskHeader);
- if (programType == volumeUtility && mode != V_SECRETLY) {
+ if (programType == volumeUtility && mode != V_SECRETLY && mode != V_PEEK) {
if (FSYNC_askfs(iheader.id, partition, FSYNC_NEEDVOLUME, mode)
== FSYNC_DENIED) {
Log("VAttachVolume: attach of volume %u apparently denied by file server\n", iheader.id);
* takes the volume offline or not. If the volume isn't
* offline, we must not return it when we detach the volume,
* or the server will abort */
- if (mode == V_READONLY
+ if (mode == V_READONLY || mode == V_PEEK
|| (!VolumeWriteable(vp) && (mode == V_CLONE || mode == V_DUMP)))
vp->needsPutBack = 0;
else
* for all of that to happen, but if it does, probably the right
* fix is for the server to allow the return of readonly volumes
* that it doesn't think are really checked out. */
- if (programType == volumeUtility && vp == NULL && mode != V_SECRETLY) {
+ if (programType == volumeUtility && vp == NULL &&
+ mode != V_SECRETLY && mode != V_PEEK) {
FSYNC_askfs(iheader.id, partition, FSYNC_ON, 0);
} else if (programType == fileServer && vp) {
V_needsCallback(vp) = 0;
register Volume *vp;
VOL_UNLOCK;
+
vp = (Volume *) calloc(1, sizeof(Volume));
assert(vp != NULL);
vp->specialStatus = (byte) (isbusy ? VBUSY : 0);
IH_INIT(vp->diskDataHandle, partp->device, header->parent,
header->volumeInfo);
IH_INIT(vp->linkHandle, partp->device, header->parent, header->linkTable);
- vp->cacheCheck = ++VolumeCacheCheck;
- /* just in case this ever rolls over */
- if (!vp->cacheCheck)
- vp->cacheCheck = ++VolumeCacheCheck;
vp->shuttingDown = 0;
vp->goingOffline = 0;
vp->nUsers = 1;
+
VOL_LOCK;
+ vp->cacheCheck = ++VolumeCacheCheck;
+ /* just in case this ever rolls over */
+ if (!vp->cacheCheck)
+ vp->cacheCheck = ++VolumeCacheCheck;
GetVolumeHeader(vp);
VOL_UNLOCK;
+
(void)ReadHeader(ec, V_diskDataHandle(vp), (char *)&V_disk(vp),
sizeof(V_disk(vp)), VOLUMEINFOMAGIC, VOLUMEINFOVERSION);
+
VOL_LOCK;
if (*ec) {
Log("VAttachVolume: Error reading diskDataHandle vol header %s; error=%u\n", path, *ec);
Log("Volume %u: couldn't reread volume header\n",
vp->hashid);
FreeVolume(vp);
- vp = 0;
+ vp = NULL;
break;
}
}
if (vp->shuttingDown) {
V8++;
*ec = VNOVOL;
- vp = 0;
+ vp = NULL;
break;
}
if (programType == fileServer) {
int old;
static int everLogged = 0;
- old = (vp->header != 0); /* old == volume already has a header */
+ old = (vp->header != NULL); /* old == volume already has a header */
if (programType != fileServer) {
if (!vp->header) {
hd = (struct volHeader *)calloc(1, sizeof(*vp->header));
- assert(hd != 0);
+ assert(hd != NULL);
vp->header = hd;
hd->back = vp;
}
VPrintCacheStats_r();
VOL_UNLOCK;
}
+