afs_int32 FindByID(struct ubik_trans *at, afs_int32 aid) { /* returns address of entry if found, 0 otherwise */ afs_int32 code; afs_int32 i; struct prentry tentry; afs_int32 entry; if ((aid == PRBADID) || (aid == 0)) return 0; i = IDHash(aid); entry = ntohl(cheader.idHash[i]); if (entry == 0) return entry; memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(at, 0, entry, &tentry); if (code != 0) return 0; if (aid == tentry.id) return entry; opr_Assert(entry != tentry.nextID); entry = tentry.nextID; while (entry != 0) { memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(at, 0, entry, &tentry); if (code != 0) return 0; if (aid == tentry.id) return entry; opr_Assert(entry != tentry.nextID); entry = tentry.nextID; } return 0; }
afs_int32 FindByName(struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp) { /* ditto */ afs_int32 code; afs_int32 i; afs_int32 entry; i = NameHash(aname); entry = ntohl(cheader.nameHash[i]); if (entry == 0) return entry; memset(tentryp, 0, sizeof(struct prentry)); code = pr_ReadEntry(at, 0, entry, tentryp); if (code != 0) return 0; if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0) return entry; opr_Assert(entry != tentryp->nextName); entry = tentryp->nextName; while (entry != 0) { memset(tentryp, 0, sizeof(struct prentry)); code = pr_ReadEntry(at, 0, entry, tentryp); if (code != 0) return 0; if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0) return entry; opr_Assert(entry != tentryp->nextName); entry = tentryp->nextName; } return 0; }
/** * lock a file on disk for the process. * * @param[in] lf the struct VLockFile representing the file to lock * @param[in] offset the offset in the file to lock * @param[in] locktype READ_LOCK or WRITE_LOCK * @param[in] nonblock 0 to wait for conflicting locks to clear before * obtaining the lock; 1 to fail immediately if a * conflicting lock is held by someone else * * @return operation status * @retval 0 success * @retval EBUSY someone else is holding a conflicting lock and nonblock=1 was * specified * @retval EIO error acquiring file lock * * @note DAFS only * * @note do not try to lock/unlock the same offset in the same file from * different threads; use VGetDiskLock to protect threads from each other in * addition to other processes */ int VLockFileLock(struct VLockFile *lf, afs_uint32 offset, int locktype, int nonblock) { int code; opr_Assert(locktype == READ_LOCK || locktype == WRITE_LOCK); opr_mutex_enter(&lf->mutex); if (lf->fd == INVALID_FD) { lf->fd = _VOpenPath(lf->path); if (lf->fd == INVALID_FD) { opr_mutex_exit(&lf->mutex); return EIO; } } lf->refcount++; opr_mutex_exit(&lf->mutex); code = _VLockFd(lf->fd, offset, locktype, nonblock); if (code) { opr_mutex_enter(&lf->mutex); if (--lf->refcount < 1) { _VCloseFd(lf->fd); lf->fd = INVALID_FD; } opr_mutex_exit(&lf->mutex); } return code; }
/*! * \brief send a Probe to all the network address of this server * * \return 0 if success, else return 1 */ int DoProbe(struct ubik_server *server) { struct rx_connection *conns[UBIK_MAX_INTERFACE_ADDR]; struct rx_connection *connSuccess = 0; int i, j, success_i = -1; afs_uint32 addr; char buffer[32]; char hoststr[16]; UBIK_ADDR_LOCK; for (i = 0; (addr = server->addr[i]) && (i < UBIK_MAX_INTERFACE_ADDR); i++) { conns[i] = rx_NewConnection(addr, ubik_callPortal, DISK_SERVICE_ID, addr_globals.ubikSecClass, addr_globals.ubikSecIndex); /* user requirement to use only the primary interface */ if (ubikPrimaryAddrOnly) { i = 1; break; } } UBIK_ADDR_UNLOCK; opr_Assert(i); /* at least one interface address for this server */ multi_Rx(conns, i) { multi_DISK_Probe(); if (!multi_error) { /* first success */ success_i = multi_i; multi_Abort; } } multi_End_Ignore;
/* strcompose - concatenate strings passed to it. * Input: * buf: storage for the composed string. Any data in it will be lost. * len: length of the buffer. * ...: variable number of string arguments. The last argument must be * (char *)NULL. * Returns buf or NULL if the buffer was not sufficiently large. */ char * strcompose(char *buf, size_t len, ...) { va_list ap; size_t spaceleft = len - 1; char *str; size_t slen; opr_Assert(buf != NULL); if (len <= 0) return NULL; *buf = '\0'; va_start(ap, len); str = va_arg(ap, char *); while (str) { slen = strlen(str); if (spaceleft < slen) /* not enough space left */ return NULL; strcat(buf, str); spaceleft -= slen; str = va_arg(ap, char *); } va_end(ap); return buf; }
void LogCommandLine(int argc, char **argv, const char *progname, const char *version, const char *logstring, void (*log) (const char *format, ...)) { int i, l; char *commandLine, *cx; opr_Assert(argc != 0); for (l = i = 0; i < argc; i++) l += strlen(argv[i]) + 1; if ((commandLine = malloc(l))) { for (cx = commandLine, i = 0; i < argc; i++) { strcpy(cx, argv[i]); cx += strlen(cx); *(cx++) = ' '; } commandLine[l-1] = '\0'; (*log)("%s %s %s%s(%s)\n", logstring, progname, version, strlen(version)>0?" ":"", commandLine); free(commandLine); } else { /* What, we're out of memory already!? */ (*log)("%s %s%s%s\n", logstring, progname, strlen(version)>0?" ":"", version); } }
/*! * Open the log file descriptor or a connection to the system log. * * This function should be called once during program initialization and * must be called before calling FSLog() or WriteLogBuffer(). The * fields of the given argument specify the logging destination and * various optional features. * * The lopt_logLevel value specifies the initial logging level. * * The lopt_dest enum specifies the logging destination; either * file based (logDest_file) or the system log (logDest_syslog). * * File Based Logging * ------------------ * * A file will be opened for log messages when the lopt_dest enum is set * to logDest_file. The file specified by lopt_filename will be opened * for appending log messages. A new file will be created if the log * file does not exist. * * The lopt_rotateOnOpen flag specifies whether an existing log file is * to be renamed and a new log file created during the call to OpenLog. * The lopt_rotateOnOpen flag has no effect if the file given by * lopt_filename is a named pipe (fifo). * * The lopt_rotateOnReset flag specifies whether the log file is renamed * and then reopened when the reset signal (SIGHUP) is caught. * * The lopt_rotateStyle enum specifies how the new log file is renamed when * lopt_rotateOnOpen or lopt_rotateOnReset are set. The lopt_rotateStyle * may be the traditional Transarc style (logRotate_old) or the MR-AFS * style (logRotate_timestamp). * * When lopt_rotateStyle is set to logRotate_old, the suffix ".old" is * appended to the log file name. The existing ".old" log file is * removed. * * When lopt_rotateStyle is set to logRotate_timestamp, a timestamp * string is appended to the log file name and existing files are not * removed. * * \note Messages written to stdout and stderr are redirected to the log * file when file-based logging is in effect. * * System Logging * -------------- * * A connection to the system log (syslog) will be established for log * messages when the lopt_dest enum is set to logDest_syslog. * * The lopt_facility specifies the system log facility to be used when * writing messages to the system log. * * The lopt_tag string specifies the indentification string to be used * when writing messages to the system log. * * \param opts logging options. A copy of the logging * options will be made before returning to * the caller. * * \returns 0 on success */ int OpenLog(struct logOptions *opts) { int code; #if defined(AFS_PTHREAD_ENV) opr_Verify(pthread_once(&serverLogOnce, InitServerLogMutex) == 0); #endif /* AFS_PTHREAD_ENV */ LogLevel = serverLogOpts.logLevel = opts->logLevel; serverLogOpts.dest = opts->dest; switch (serverLogOpts.dest) { case logDest_file: serverLogOpts.lopt_rotateOnOpen = opts->lopt_rotateOnOpen; serverLogOpts.lopt_rotateOnReset = opts->lopt_rotateOnReset; serverLogOpts.lopt_rotateStyle = opts->lopt_rotateStyle; /* OpenLogFile() sets ourName; don't cache filename here. */ code = OpenLogFile(opts->lopt_filename); break; #ifdef HAVE_SYSLOG case logDest_syslog: serverLogOpts.lopt_rotateOnOpen = 0; serverLogOpts.lopt_rotateOnReset = 0; serverLogOpts.lopt_rotateStyle = logRotate_none; openlog(opts->lopt_tag, LOG_PID, opts->lopt_facility); code = 0; break; #endif default: opr_Assert(0); } return code; } /*OpenLog */
/** * initialize a struct VDiskLock. * * @param[in] dl struct VDiskLock to initialize * @param[in] lf the struct VLockFile to associate with this disk lock */ void VDiskLockInit(struct VDiskLock *dl, struct VLockFile *lf, afs_uint32 offset) { opr_Assert(lf); memset(dl, 0, sizeof(*dl)); Lock_Init(&dl->rwlock); opr_mutex_init(&dl->mutex); opr_cv_init(&dl->cv); dl->lockfile = lf; dl->offset = offset; }
/** * initialize a struct VDiskLock. * * @param[in] dl struct VDiskLock to initialize * @param[in] lf the struct VLockFile to associate with this disk lock */ void VDiskLockInit(struct VDiskLock *dl, struct VLockFile *lf, afs_uint32 offset) { opr_Assert(lf); memset(dl, 0, sizeof(*dl)); Lock_Init(&dl->rwlock); MUTEX_INIT(&dl->mutex, "disklock", MUTEX_DEFAULT, 0); CV_INIT(&dl->cv, "disklock cv", CV_DEFAULT, 0); dl->lockfile = lf; dl->offset = offset; }
void softsig_init(void) { int rc; AFS_SIGSET_DECL; AFS_SIGSET_CLEAR(); rc = pthread_create(&softsig_tid, NULL, &softsig_thread, NULL); opr_Assert(0 == rc); AFS_SIGSET_RESTORE(); signal (SIGUSR1, softsig_usr1); }
/*! * Open the log file. * * Open the log file using the options given in OpenLog(). * * \returns 0 on success */ static int OpenLogFile(const char *fileName) { /* * This function should allow various libraries that inconsistently * use stdout/stderr to all go to the same place */ int tempfd; int flags = O_WRONLY | O_CREAT | O_APPEND; opr_Assert(serverLogOpts.dest == logDest_file); opr_Assert(fileName != NULL); if (IsFIFO(fileName)) { /* Support named pipes as logs by not rotating them. */ flags |= O_NONBLOCK; } else if (serverLogOpts.lopt_rotateOnOpen) { /* Old style logging always started a new log file. */ flags |= O_TRUNC; RenameLogFile(fileName); } tempfd = open(fileName, flags, 0666); if (tempfd < 0) { printf("Unable to open log file %s\n", fileName); return -1; } RedirectStdStreams(fileName); /* Save our name for reopening. */ free(ourName); ourName = strdup(fileName); opr_Assert(ourName != NULL); serverLogFD = tempfd; return 0; }
afs_int32 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */ { /* remove entry designated by aid from id hash table */ afs_int32 code; afs_int32 current, trail, i; struct prentry tentry; struct prentry bentry; if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT; i = IDHash(aid); current = ntohl(cheader.idHash[i]); memset(&tentry, 0, sizeof(tentry)); memset(&bentry, 0, sizeof(bentry)); trail = 0; if (current == 0) return PRSUCCESS; /* already gone */ code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; while (aid != tentry.id) { opr_Assert(trail != current); trail = current; current = tentry.nextID; if (current == 0) break; code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; } if (current == 0) return PRSUCCESS; /* we didn't find him, so he's already gone */ if (trail == 0) { /* it's the first entry! */ cheader.idHash[i] = htonl(tentry.nextID); code = pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i], sizeof(cheader.idHash[i])); if (code) return PRDBFAIL; } else { code = pr_ReadEntry(tt, 0, trail, &bentry); if (code) return PRDBFAIL; bentry.nextID = tentry.nextID; code = pr_WriteEntry(tt, 0, trail, &bentry); } *loc = current; return PRSUCCESS; }
static void * SalvageChildReaperThread(void * args) { int slot, pid, status; struct log_cleanup_node * cleanup; MUTEX_ENTER(&worker_lock); /* loop reaping our children */ while (1) { /* wait() won't block unless we have children, so * block on the cond var if we're childless */ while (current_workers == 0) { CV_WAIT(&worker_cv, &worker_lock); } MUTEX_EXIT(&worker_lock); cleanup = malloc(sizeof(struct log_cleanup_node)); while (Reap_Child("salvageserver", &pid, &status) < 0) { /* try to prevent livelock if something goes wrong */ sleep(1); } VOL_LOCK; for (slot = 0; slot < Parallel; slot++) { if (child_slot[slot] == pid) break; } opr_Assert(slot < Parallel); child_slot[slot] = 0; VOL_UNLOCK; SALVSYNC_doneWorkByPid(pid, status); MUTEX_ENTER(&worker_lock); if (cleanup) { cleanup->pid = pid; queue_Append(&log_cleanup_queue, cleanup); CV_SIGNAL(&log_cleanup_queue.queue_change_cv); } /* ok, we've reaped a child */ current_workers--; CV_BROADCAST(&worker_cv); } return NULL; }
/** * release a lock on a file on local disk. * * @param[in] dl the struct VDiskLock to release * @param[in] locktype READ_LOCK if you are unlocking a read lock, or * WRITE_LOCK if you are unlocking a write lock * * @return operation status * @retval 0 success */ void VReleaseDiskLock(struct VDiskLock *dl, int locktype) { opr_Assert(locktype == READ_LOCK || locktype == WRITE_LOCK); opr_mutex_enter(&dl->mutex); opr_Assert(dl->lockers > 0); if (--dl->lockers < 1) { /* no threads are holding this lock anymore, so we can release the * actual disk lock */ VLockFileUnlock(dl->lockfile, dl->offset); dl->flags &= ~VDISKLOCK_ACQUIRED; } opr_mutex_exit(&dl->mutex); if (locktype == READ_LOCK) { ReleaseReadLock(&dl->rwlock); } else { ReleaseWriteLock(&dl->rwlock); } }
struct DiskPartition64 * VGetPartitionById_r(afs_int32 id, int abortp) { struct DiskPartition64 *dp = NULL; if ((id >= 0) && (id <= VOLMAXPARTS)) { dp = DiskPartitionTable[id]; } if (abortp) { opr_Assert(dp != NULL); } return dp; }
afs_int32 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc) { /* remove from name hash */ afs_int32 code; afs_int32 current, trail, i; struct prentry tentry; struct prentry bentry; i = NameHash(aname); current = ntohl(cheader.nameHash[i]); memset(&tentry, 0, sizeof(tentry)); memset(&bentry, 0, sizeof(bentry)); trail = 0; if (current == 0) return PRSUCCESS; /* already gone */ code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; while (strcmp(aname, tentry.name)) { opr_Assert(trail != current); trail = current; current = tentry.nextName; if (current == 0) break; code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; } if (current == 0) return PRSUCCESS; /* we didn't find him, already gone */ if (trail == 0) { /* it's the first entry! */ cheader.nameHash[i] = htonl(tentry.nextName); code = pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i], sizeof(cheader.nameHash[i])); if (code) return PRDBFAIL; } else { code = pr_ReadEntry(tt, 0, trail, &bentry); if (code) return PRDBFAIL; bentry.nextName = tentry.nextName; code = pr_WriteEntry(tt, 0, trail, &bentry); } *loc = current; return PRSUCCESS; }
void VLockPartition_r(char *name) { struct DiskPartition64 *dp = VGetPartition_r(name, 0); OVERLAPPED lap; if (!dp) return; if (dp->lock_fd == INVALID_FD) { char path[64]; int rc; (void)sprintf(path, "%s\\%s", VPartitionPath(dp), LOCKFILE); dp->lock_fd = (FD_t)CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL); opr_Assert(dp->lock_fd != INVALID_FD); memset(&lap, 0, sizeof(lap)); rc = LockFileEx((HANDLE) dp->lock_fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &lap); opr_Assert(rc); } }
void VLockFileUnlock(struct VLockFile *lf, afs_uint32 offset) { opr_mutex_enter(&lf->mutex); opr_Assert(lf->fd != INVALID_FD); if (--lf->refcount < 1) { _VCloseFd(lf->fd); lf->fd = INVALID_FD; } else { _VUnlockFd(lf->fd, offset); } opr_mutex_exit(&lf->mutex); }
/* get partition structure, abortp tells us if we should abort on failure */ struct DiskPartition64 * VGetPartition_r(char *name, int abortp) { struct DiskPartition64 *dp; #ifdef AFS_DEMAND_ATTACH_FS dp = VLookupPartition_r(name); #else /* AFS_DEMAND_ATTACH_FS */ for (dp = DiskPartitionList; dp; dp = dp->next) { if (strcmp(dp->name, name) == 0) break; } #endif /* AFS_DEMAND_ATTACH_FS */ if (abortp) opr_Assert(dp != NULL); return dp; }
void VLockFileUnlock(struct VLockFile *lf, afs_uint32 offset) { MUTEX_ENTER(&lf->mutex); opr_Assert(lf->fd != INVALID_FD); if (--lf->refcount < 1) { _VCloseFd(lf->fd); lf->fd = INVALID_FD; } else { _VUnlockFd(lf->fd, offset); } MUTEX_EXIT(&lf->mutex); }
/* * Given two arrays of addresses, masks and mtus find the common ones * and return them in the first buffer. Return number of common * entries. */ static int filterAddrs(afs_uint32 addr1[], afs_uint32 addr2[], afs_uint32 mask1[], afs_uint32 mask2[], afs_uint32 mtu1[], afs_uint32 mtu2[], int n1, int n2) { afs_uint32 taddr[MAXIPADDRS]; afs_uint32 tmask[MAXIPADDRS]; afs_uint32 tmtu[MAXIPADDRS]; int count = 0, i = 0, j = 0, found = 0; opr_Assert(addr1); opr_Assert(addr2); opr_Assert(mask1); opr_Assert(mask2); opr_Assert(mtu1); opr_Assert(mtu2); for (i = 0; i < n1; i++) { found = 0; for (j = 0; j < n2; j++) { if (addr1[i] == addr2[j]) { found = 1; break; } } /* Always mask loopback address */ if (found && rx_IsLoopbackAddr(addr1[i])) found = 0; if (found) { taddr[count] = addr1[i]; tmask[count] = mask1[i]; tmtu[count] = mtu1[i]; count++; } } /* copy everything into addr1, mask1 and mtu1 */ for (i = 0; i < count; i++) { addr1[i] = taddr[i]; if (mask1) { mask1[i] = tmask[i]; mtu1[i] = tmtu[i]; } } /* and zero out the rest */ for (i = count; i < n1; i++) { addr1[i] = 0; if (mask1) { mask1[i] = 0; mtu1[i] = 0; } } return count; }
/*! * Move the current log file out of the way so a new one can be started. * * The format of the new name depends on the logging style. The traditional * Transarc style appends ".old" to the log file name. When MR-AFS style * logging is in effect, a time stamp is appended to the log file name instead * of ".old". * * \bug Unfortunately, no check is made to avoid overwriting * old logs in the traditional Transarc mode. * * \param fileName fully qualified log file path */ static void RenameLogFile(const char *fileName) { int code; char *nextName = NULL; int tries; time_t t; struct stat buf; struct tm *timeFields; switch (serverLogOpts.lopt_rotateStyle) { case logRotate_none: break; case logRotate_old: code = asprintf(&nextName, "%s.old", fileName); if (code < 0) { nextName = NULL; } break; case logRotate_timestamp: time(&t); for (tries = 0; nextName == NULL && tries < 100; t++, tries++) { timeFields = localtime(&t); code = asprintf(&nextName, "%s.%d%02d%02d%02d%02d%02d", fileName, timeFields->tm_year + 1900, timeFields->tm_mon + 1, timeFields->tm_mday, timeFields->tm_hour, timeFields->tm_min, timeFields->tm_sec); if (code < 0) { nextName = NULL; break; } if (lstat(nextName, &buf) == 0) { /* Avoid clobbering a log. */ free(nextName); nextName = NULL; } } break; default: opr_Assert(0); } if (nextName != NULL) { rk_rename(fileName, nextName); /* Don't check the error code. */ free(nextName); } }
char * ucstring(char *d, const char *s, int n) { char *original_d = d; char c; opr_Assert(s != NULL && d != NULL); while (n) { c = *s++; if (islower(c)) c = toupper(c); *d++ = c; if (c == 0) break; if (--n == 0) *(d - 1) = 0; /* make sure null terminated */ } return original_d; }
static int common_volop_prolog(struct cmd_syndesc * as, struct fssync_state * state) { struct cmd_item *ti; state->vop = (struct volop_state *) calloc(1, sizeof(struct volop_state)); opr_Assert(state->vop != NULL); if ((ti = as->parms[COMMON_VOLOP_PARMS_OFFSET].items)) { /* -volumeid */ state->vop->volume = atoi(ti->data); } else { fprintf(stderr, "required argument -volumeid not given\n"); } if ((ti = as->parms[COMMON_VOLOP_PARMS_OFFSET+1].items)) { /* -partition */ strlcpy(state->vop->partName, ti->data, sizeof(state->vop->partName)); } else { memset(state->vop->partName, 0, sizeof(state->vop->partName)); } return 0; }
/** * acquire a lock on a file on local disk. * * @param[in] dl the VDiskLock structure corresponding to the file on disk * @param[in] locktype READ_LOCK if you want a read lock, or WRITE_LOCK if * you want a write lock * @param[in] nonblock 0 to wait for conflicting locks to clear before * obtaining the lock; 1 to fail immediately if a * conflicting lock is held by someone else * * @return operation status * @retval 0 success * @retval EBUSY someone else is holding a conflicting lock and nonblock=1 was * specified * @retval EIO error acquiring file lock * * @note DAFS only * * @note while normal fcntl-y locks on Unix systems generally only work per- * process, this interface also deals with locks between threads in the * process in addition to different processes acquiring the lock */ int VGetDiskLock(struct VDiskLock *dl, int locktype, int nonblock) { int code = 0; opr_Assert(locktype == READ_LOCK || locktype == WRITE_LOCK); if (nonblock) { if (locktype == READ_LOCK) { ObtainReadLockNoBlock(&dl->rwlock, code); } else { ObtainWriteLockNoBlock(&dl->rwlock, code); } if (code) { return EBUSY; } } else if (locktype == READ_LOCK) { ObtainReadLock(&dl->rwlock); } else { ObtainWriteLock(&dl->rwlock); } opr_mutex_enter(&dl->mutex); if ((dl->flags & VDISKLOCK_ACQUIRING)) { /* Some other thread is waiting to acquire an fs lock. If nonblock=1, * we can return immediately, since we know we'll need to wait to * acquire. Otherwise, wait for the other thread to finish acquiring * the fs lock */ if (nonblock) { code = EBUSY; } else { while ((dl->flags & VDISKLOCK_ACQUIRING)) { opr_cv_wait(&dl->cv, &dl->mutex); } } } if (code == 0 && !(dl->flags & VDISKLOCK_ACQUIRED)) { /* no other thread holds the lock on the actual file; so grab one */ /* first try, don't block on the lock to see if we can get it without * waiting */ code = VLockFileLock(dl->lockfile, dl->offset, locktype, 1); if (code == EBUSY && !nonblock) { /* mark that we are waiting on the fs lock */ dl->flags |= VDISKLOCK_ACQUIRING; opr_mutex_exit(&dl->mutex); code = VLockFileLock(dl->lockfile, dl->offset, locktype, nonblock); opr_mutex_enter(&dl->mutex); dl->flags &= ~VDISKLOCK_ACQUIRING; if (code == 0) { dl->flags |= VDISKLOCK_ACQUIRED; } opr_cv_broadcast(&dl->cv); } } if (code) { if (locktype == READ_LOCK) { ReleaseReadLock(&dl->rwlock); } else { ReleaseWriteLock(&dl->rwlock); } } else { /* successfully got the lock, so inc the number of unlocks we need * to do before we can unlock the actual file */ ++dl->lockers; } opr_mutex_exit(&dl->mutex); return code; }
/** * Get a list of IP addresses for this host allowing only addresses found * in the config file (fileName parameter): /usr/vice/etc/NetInfo for * clients and /usr/afs/local/NetInfo for servers. * * All addresses should be in network byte order as returned by * rx_getAllAddrMaskMtu() and parsed by extract_Addr(). * * @param[out] outAddrs * All the address that are found to be valid. * @param[out] outMask * Associated netmask for interface * @param[out] outMtu * Associated MTU for interface * @param[in] max * Length of the output above arrays * @param[out] reason * Reason for the parsing failure * @param[in] fileName * File to parse * @param[in] fakeonly * Only return addresses if they are marked as fake * * @return * The number of valid address on success or < 0 on fatal failure. */ static int ParseNetInfoFile_int(afs_uint32 outAddrs[], afs_uint32 outMask[], afs_uint32 outMtu[], int max, char reason[], const char *fileName, int fakeonly) { afs_uint32 existingAddr[MAXIPADDRS], existingMask[MAXIPADDRS], existingMtu[MAXIPADDRS]; char line[MAX_NETFILE_LINE]; FILE *fp; int i, existNu, count = 0; afs_uint32 addr; int lineNo = 0; int l; opr_Assert(fileName); opr_Assert(outAddrs); opr_Assert(outMask); opr_Assert(outMtu); opr_Assert(reason); /* get all network interfaces from the kernel */ existNu = rx_getAllAddrMaskMtu(existingAddr, existingMask, existingMtu, MAXIPADDRS); if (existNu < 0) return existNu; if ((fp = fopen(fileName, "r")) == 0) { /* If file does not exist or is not readable, then * use all interface addresses. */ sprintf(reason, "Failed to open %s(%s)\nUsing all configured addresses\n", fileName, strerror(errno)); for (i = 0; i < existNu; i++) { outAddrs[i] = existingAddr[i]; outMask[i] = existingMask[i]; outMtu[i] = existingMtu[i]; } return existNu; } /* For each line in the NetInfo file */ while (fgets(line, MAX_NETFILE_LINE, fp) != NULL) { int fake = 0; /* See if first char is an 'F' for fake */ /* Added to allow the fileserver to advertise fake IPS for use with * the translation tables for NAT-like firewalls - defect 12462 */ for (fake = 0; ((fake < strlen(line)) && isspace(line[fake])); fake++); if ((fake < strlen(line)) && ((line[fake] == 'f') || (line[fake] == 'F'))) { fake++; } else { fake = 0; } lineNo++; /* input line number */ addr = extract_Addr(&line[fake], strlen(&line[fake])); if (addr == AFS_IPINVALID) { /* syntactically invalid */ fprintf(stderr, "afs:%s : line %d : parse error\n", fileName, lineNo); continue; } if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */ continue; } /* See if it is an address that really exists */ for (i = 0; i < existNu; i++) { if (existingAddr[i] == addr) break; } if ((i >= existNu) && (!fake)) continue; /* not found/fake - ignore */ /* Check if it is a duplicate address we alread have */ for (l = 0; l < count; l++) { if (outAddrs[l] == addr) break; } if (l < count) { fprintf(stderr, "afs:%x specified twice in NetInfo file\n", ntohl(addr)); continue; /* duplicate addr - ignore */ } if (count > max) { /* no more space */ fprintf(stderr, "afs:Too many interfaces. The current kernel configuration supports a maximum of %d interfaces\n", max); } else if (fake) { if (!fake) fprintf(stderr, "Client (2) also has address %s\n", line); outAddrs[count] = addr; outMask[count] = 0xffffffff; outMtu[count] = htonl(1500); count++; } else if (!fakeonly) { outAddrs[count] = existingAddr[i]; outMask[count] = existingMask[i]; outMtu[count] = existingMtu[i]; count++; } } /* while */ /* in case of any error, we use all the interfaces present */ if (count <= 0) { sprintf(reason, "Error in reading/parsing Interface file\nUsing all configured interface addresses \n"); for (i = 0; i < existNu; i++) { outAddrs[i] = existingAddr[i]; outMask[i] = existingMask[i]; outMtu[i] = existingMtu[i]; } return existNu; } return count; }
/** * Get a list of IP addresses for this host removing any address found * in the config file (fileName parameter): /usr/vice/etc/NetRestrict * for clients and /usr/afs/local/NetRestrict for servers. * * Returns the number of valid addresses in outAddrs[] and count in * nAddrs. Returns 0 on success; or 1 if the config file was not * there or empty (we still return the host's IP addresses). Returns * -1 on fatal failure with reason in the reason argument (so the * caller can choose to ignore the entire file but should write * something to a log file). * * All addresses should be in network byte order as returned by * rx_getAllAddrMaskMtu() and parsed by extract_Addr(). * * @param[out] outAddrs * All the address that are found to be valid. * @param[out] outMask * Optional associated netmask for address * @param[out] outMtu * Optional associated MTU for address * @param[in] maxAddres * Length of the above output arrays * @param[out] nAddrs * Count of valid addresses * @param[out] reason * Reason (if any) for the parsing failure * @param[in] fileName * Configuration file to parse * * @return * 0 on success; 1 if the config file was not used; -1 on * fatal failure. */ static int parseNetRestrictFile_int(afs_uint32 outAddrs[], afs_uint32 outMask[], afs_uint32 outMtu[], afs_uint32 maxAddrs, afs_uint32 *nAddrs, char reason[], const char *fileName, const char *fileName_ni) { FILE *fp; char line[MAX_NETFILE_LINE]; int lineNo, usedfile = 0; afs_uint32 i, neaddrs, nOutaddrs; afs_uint32 addr, eAddrs[MAXIPADDRS], eMask[MAXIPADDRS], eMtu[MAXIPADDRS]; opr_Assert(outAddrs); opr_Assert(reason); opr_Assert(fileName); opr_Assert(nAddrs); if (outMask) opr_Assert(outMtu); /* Initialize */ *nAddrs = 0; for (i = 0; i < maxAddrs; i++) outAddrs[i] = 0; strcpy(reason, ""); /* get all network interfaces from the kernel */ neaddrs = rx_getAllAddrMaskMtu(eAddrs, eMask, eMtu, MAXIPADDRS); if (neaddrs <= 0) { sprintf(reason, "No existing IP interfaces found"); return -1; } i = 0; if ((neaddrs < MAXIPADDRS) && fileName_ni) i = ParseNetInfoFile_int(&(eAddrs[neaddrs]), &(eMask[neaddrs]), &(eMtu[neaddrs]), MAXIPADDRS-neaddrs, reason, fileName_ni, 1); if (i > 0) neaddrs += i; if ((fp = fopen(fileName, "r")) == 0) { sprintf(reason, "Could not open file %s for reading:%s", fileName, strerror(errno)); goto done; } /* For each line in the NetRestrict file */ lineNo = 0; usedfile = 0; while (fgets(line, MAX_NETFILE_LINE, fp) != NULL) { lineNo++; /* input line number */ addr = extract_Addr(line, strlen(line)); if (addr == AFS_IPINVALID) { /* syntactically invalid */ fprintf(stderr, "%s : line %d : parse error - invalid IP\n", fileName, lineNo); continue; } if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */ fprintf(stderr, "%s : line %d : invalid address ... ignoring\n", fileName, lineNo); continue; } usedfile = 1; /* Check if we need to exclude this address */ for (i = 0; i < neaddrs; i++) { if (eAddrs[i] && (eAddrs[i] == addr)) { eAddrs[i] = 0; /* Yes - exclude it by zeroing it for now */ } } } /* while */ fclose(fp); if (!usedfile) { sprintf(reason, "No valid IP addresses in %s\n", fileName); goto done; } done: /* Collect the addresses we have left to return */ nOutaddrs = 0; for (i = 0; i < neaddrs; i++) { if (!eAddrs[i]) continue; outAddrs[nOutaddrs] = eAddrs[i]; if (outMask) { outMask[nOutaddrs] = eMask[i]; outMtu[nOutaddrs] = eMtu[i]; } if (++nOutaddrs >= maxAddrs) break; } if (nOutaddrs == 0) { sprintf(reason, "No addresses to use after parsing %s", fileName); return -1; } *nAddrs = nOutaddrs; return (usedfile ? 0 : 1); /* 0=>used the file. 1=>didn't use file */ }
void Afs_Lock_Obtain(struct Lock *lock, int how) { switch (how) { case READ_LOCK: lock->num_waiting++; do { lock->wait_states |= READ_LOCK; #ifdef AFS_PTHREAD_ENV opr_Verify(pthread_cond_wait(&lock->read_cv, &lock->mutex) == 0); #else /* AFS_PTHREAD_ENV */ LWP_WaitProcess(&lock->readers_reading); #endif /* AFS_PTHREAD_ENV */ } while (lock->excl_locked & WRITE_LOCK); lock->num_waiting--; lock->readers_reading++; break; case WRITE_LOCK: lock->num_waiting++; do { lock->wait_states |= WRITE_LOCK; #ifdef AFS_PTHREAD_ENV opr_Verify(pthread_cond_wait(&lock->write_cv, &lock->mutex) == 0); #else /* AFS_PTHREAD_ENV */ LWP_WaitProcess(&lock->excl_locked); #endif /* AFS_PTHREAD_ENV */ } while (lock->excl_locked || lock->readers_reading); lock->num_waiting--; lock->excl_locked = WRITE_LOCK; break; case SHARED_LOCK: lock->num_waiting++; do { lock->wait_states |= SHARED_LOCK; #ifdef AFS_PTHREAD_ENV opr_Verify(pthread_cond_wait(&lock->write_cv, &lock->mutex) == 0); #else /* AFS_PTHREAD_ENV */ LWP_WaitProcess(&lock->excl_locked); #endif /* AFS_PTHREAD_ENV */ } while (lock->excl_locked); lock->num_waiting--; lock->excl_locked = SHARED_LOCK; break; case BOOSTED_LOCK: lock->num_waiting++; do { lock->wait_states |= WRITE_LOCK; #ifdef AFS_PTHREAD_ENV opr_Verify(pthread_cond_wait(&lock->write_cv, &lock->mutex) == 0); #else /* AFS_PTHREAD_ENV */ LWP_WaitProcess(&lock->excl_locked); #endif /* AFS_PTHREAD_ENV */ } while (lock->readers_reading); lock->num_waiting--; lock->excl_locked = WRITE_LOCK; break; default: printf("Can't happen, bad LOCK type: %d\n", how); opr_Assert(0); } }
void opr_rbtree_remove(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node *child, *parent; int red; if (node->left == NULL && node->right == NULL) { /* A node with no non-leaf children */ update_parent_ptr(head, node, NULL); if (!node->red) remove_recolour(head, node->parent, NULL); return; } if (node->left != NULL && node->right != NULL) { /* A node with two children. * * Move the next node in the tree (which will be a leaf node) * onto our tree current position, then rebalance as required */ struct opr_rbtree_node *old, *left; old = node; /* Set node to the next node in the tree from the current * position, where the next node is the left-most leaf node * in our right child */ node = node->right; while ((left = node->left) != NULL) node = left; /* Move 'node' into the position occupied by 'old', which is being * removed */ update_parent_ptr(head, old, node); child = node->right; parent = node->parent; red = node->red; /* As we're logically just copying the value, must preserve the * old node's colour */ node->red = old->red; /* ... and the old node's linkage */ if (parent == old) parent = node; else { if (child) child->parent = parent; parent->left = child; node->right = old->right; old->right->parent = node; } node->parent = old->parent; node->left = old->left; old->left->parent = node; /* If the node being removed was black, then we must recolour the * tree to maintain balance */ if (!red) remove_recolour(head, parent, child); return; } /* Only remaining option - node with a single child */ if (node->left == NULL) child = node->right; else { opr_Assert(node->right == NULL); child = node->left; } child->parent = node->parent; update_parent_ptr(head, node, child); if (!node->red) remove_recolour(head, node->parent, child); }
static int usd_FileOpen(const char *path, int flags, int mode, usd_handle_t * usdP) { int fd; int oflags; usd_handle_t usd; int code; if (usdP) *usdP = NULL; oflags = (flags & USD_OPEN_RDWR) ? O_RDWR : O_RDONLY; #ifdef O_SYNC /* AFS_DARWIN_ENV XXX */ if (flags & USD_OPEN_SYNC) oflags |= O_SYNC; #endif if (flags & USD_OPEN_CREATE) oflags |= O_CREAT; #ifdef O_LARGEFILE fd = open64(path, oflags | O_LARGEFILE, mode); #else /* O_LARGEFILE */ fd = open(path, oflags, mode); #endif /* O_LARGEFILE */ if (fd == -1) return errno; usd = calloc(1, sizeof(*usd)); usd->handle = (void *)(intptr_t)fd; usd->read = usd_FileRead; usd->write = usd_FileWrite; usd->seek = usd_FileSeek; usd->ioctl = usd_FileIoctl; usd->close = usd_FileClose; usd->fullPathName = strdup(path); usd->openFlags = flags; code = 0; if (flags & (USD_OPEN_RLOCK | USD_OPEN_WLOCK)) { #ifdef O_LARGEFILE struct flock64 fl; #else /* O_LARGEFILE */ struct flock fl; #endif /* O_LARGEFILE */ /* make sure both lock bits aren't set */ opr_Assert(~flags & (USD_OPEN_RLOCK | USD_OPEN_WLOCK)); fl.l_type = ((flags & USD_OPEN_RLOCK) ? F_RDLCK : F_WRLCK); fl.l_whence = SEEK_SET; fl.l_start = (osi_lloff_t) 0; fl.l_len = (osi_lloff_t) 0; /* whole file */ #ifdef O_LARGEFILE code = fcntl(fd, F_SETLK64, &fl); #else /* O_LARGEFILE */ code = fcntl(fd, F_SETLK, &fl); #endif /* O_LARGEFILE */ if (code == -1) code = errno; /* If we're trying to obtain a write lock on a real disk, then the * aggregate must not be attached by the kernel. If so, unlock it * and fail. * WARNING: The code to check for the above has been removed when this * file was ported from DFS src. It should be put back if * this library is used to access hard disks */ } if (code == 0 && usdP) *usdP = usd; else usd_FileClose(usd); return code; }