/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include RCSID ("$Header$"); #include #include #ifdef HAVE_STRING_H #include #else #ifdef HAVE_STRINGS_H #include #endif #endif #include #ifdef AFS_NT40_ENV #include #include #else #include #include #include #include #include #include #endif #include "afs_vosAdmin.h" #include "../adminutil/afs_AdminInternal.h" #include #include #include #include #include #include #include "vosutils.h" #include "vsprocs.h" #include "lockprocs.h" typedef struct file_server { int begin_magic; int is_valid; struct rx_connection *serv; int end_magic; } file_server_t, *file_server_p; /* * IsValidServerHandle - test a server handle for validity. * * PARAMETERS * * IN serverHandle - the serverHandle to be validated. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ static int IsValidServerHandle(file_server_p serverHandle, afs_status_p st) { int rc = 0; afs_status_t tst = 0; if (serverHandle == NULL) { tst = ADMVOSSERVERHANDLENULL; goto fail_IsValidServerHandle; } if (serverHandle->is_valid != 1) { tst = ADMVOSSERVERHANDLEINVALID; goto fail_IsValidServerHandle; } if ((serverHandle->begin_magic != BEGIN_MAGIC) || (serverHandle->end_magic != END_MAGIC)) { tst = ADMVOSSERVERHANDLEBADMAGIC; goto fail_IsValidServerHandle; } rc = 1; fail_IsValidServerHandle: if (st != NULL) { *st = tst; } return rc; } /* * IsValidCellHandle - verify that a cell handle can be used to make vos * requests. * * PARAMETERS * * IN cellHandle - the cellHandle to be validated. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ static int IsValidCellHandle(afs_cell_handle_p cellHandle, afs_status_p st) { int rc = 0; afs_status_t tst = 0; if (!CellHandleIsValid((void *)cellHandle, &tst)) { goto fail_IsValidCellHandle; } if (cellHandle->vos_valid == 0) { tst = ADMVOSCELLHANDLEINVALIDVOS; goto fail_IsValidCellHandle; } rc = 1; fail_IsValidCellHandle: if (st != NULL) { *st = tst; } return rc; } /* set and to the correct values depending on * and */ static void GetServerAndPart(struct nvldbentry *entry, int voltype, afs_int32 * server, afs_int32 * part, int *previdx) { int i, istart, vtype; *server = -1; *part = -1; /* Doesn't check for non-existance of backup volume */ if ((voltype == RWVOL) || (voltype == BACKVOL)) { vtype = ITSRWVOL; istart = 0; /* seach the entire entry */ } else { vtype = ITSROVOL; /* Seach from beginning of entry or pick up where we left off */ istart = ((*previdx < 0) ? 0 : *previdx + 1); } for (i = istart; i < entry->nServers; i++) { if (entry->serverFlags[i] & vtype) { *server = entry->serverNumber[i]; *part = entry->serverPartition[i]; *previdx = i; return; } } /* Didn't find any, return -1 */ *previdx = -1; return; } /* * vos_BackupVolumeCreate - create a backup volume for a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the volume to create the back up for. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_BackupVolumeCreate(const void *cellHandle, vos_MessageCallBack_t callBack, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; struct nvldbentry rw_vol_entry; afs_int32 rw_server; afs_int32 rw_partition; afs_int32 rw_vol_type; struct nvldbentry bk_vol_entry; afs_int32 bk_server; afs_int32 bk_partition; afs_int32 bk_vol_type; int equal; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_BackupVolumeCreate; } /* * Get the volume information and verify that we've been passed * a read write volume id */ if (!GetVolumeInfo (c_handle, volumeId, &rw_vol_entry, &rw_server, &rw_partition, &rw_vol_type, &tst)) { goto fail_vos_BackupVolumeCreate; } if (rw_vol_type != RWVOL) { tst = ADMVOSMUSTBERWVOL; goto fail_vos_BackupVolumeCreate; } /* * Check to see that if a backup volume exists, it exists on the * same server as volumeId */ if (rw_vol_entry.flags & BACK_EXISTS) { if (!GetVolumeInfo (c_handle, rw_vol_entry.volumeId[BACKVOL], &bk_vol_entry, &bk_server, &bk_partition, &bk_vol_type, &tst)) { goto fail_vos_BackupVolumeCreate; } if (!VLDB_IsSameAddrs(c_handle, bk_server, rw_server, &equal, &tst)) { goto fail_vos_BackupVolumeCreate; } if (!equal) { tst = ADMVOSBACKUPVOLWRONGSERVER; goto fail_vos_BackupVolumeCreate; } } /* * Create the new backup volume */ rc = UV_BackupVolume(c_handle, rw_server, rw_partition, volumeId, &tst); fail_vos_BackupVolumeCreate: if (st != NULL) { *st = tst; } return rc; } /* * vos_BackupVolumeCreateMultiple - create backup volumes en masse. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volumes exist. * * IN serverHandle - the server where the backups are to be created. Can be * null. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the backups are to be created. Can be * null. * * IN volumePrefix - all volumes with this prefix will have backup volumes * created. Can be null. * * IN excludePrefix - exclude the volumes that match volumePrefix. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_BackupVolumeCreateMultiple(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, const unsigned int *partition, const char *volumePrefix, vos_exclude_t excludePrefix, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; struct VldbListByAttributes attr; int exclude = 0; int prefix = 0; size_t prefix_len = 0; nbulkentries arrayEntries; afs_int32 nentries = 0; register struct nvldbentry *entry; int i; afs_int32 rw_volid, rw_server, rw_partition; int previdx; int equal = 0; char backbuf[1024]; memset((void *)&attr, 0, sizeof(attr)); /* * Validate arguments * * The only required argument to this function is the cellHandle. * If the excludePrefix is set to VOS_EXCLUDE, volumePrefix must * be non-null. */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_BackupVolumeCreateMultiple; } if ((excludePrefix == VOS_EXCLUDE) && ((volumePrefix == NULL) || (*volumePrefix == 0))) { tst = ADMVOSEXCLUDEREQUIRESPREFIX; goto fail_vos_BackupVolumeCreateMultiple; } if (f_server != NULL) { if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_BackupVolumeCreateMultiple; } attr.server = ntohl(rx_HostOf(rx_PeerOf(f_server->serv))); attr.Mask |= VLLIST_SERVER; } if (partition != NULL) { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_BackupVolumeCreateMultiple; } attr.partition = *partition; attr.Mask |= VLLIST_PARTITION; } if (excludePrefix == VOS_EXCLUDE) { exclude = 1; } if ((volumePrefix != NULL) && (*volumePrefix != 0)) { prefix = 1; prefix_len = strlen(volumePrefix); } memset((void *)&arrayEntries, 0, sizeof(arrayEntries)); /* * Get a list of all the volumes in the cell */ if (!VLDB_ListAttributes(c_handle, &attr, &nentries, &arrayEntries, &tst)) { goto fail_vos_BackupVolumeCreateMultiple; } /* * Cycle through the list of volumes and see if we should create a backup * for each individual volume */ for (i = 0; i < nentries; i++) { entry = &arrayEntries.nbulkentries_val[i]; /* * Skip entries that don't have a RW volume */ if (!(entry->flags & RW_EXISTS)) { if (callBack != NULL) { const char *messageText; if (util_AdminErrorCodeTranslate (ADMVOSVOLUMENOREADWRITE, 0, &messageText, &tst)) { sprintf(backbuf, "%s %s", messageText, entry->name); (**callBack) (VOS_VERBOSE_MESSAGE, backbuf); } } continue; } /* * See if we should skip this entry because of the prefix/exclude * combination we've been passed */ if (prefix) { if (exclude) { if (!strncmp(entry->name, volumePrefix, prefix_len)) { continue; } } else { if (strncmp(entry->name, volumePrefix, prefix_len)) { continue; } } } rw_volid = entry->volumeId[RWVOL]; GetServerAndPart(entry, RWVOL, &rw_server, &rw_partition, &previdx); if ((rw_server == -1) || (rw_partition == -1)) { if (callBack != NULL) { const char *messageText; if (util_AdminErrorCodeTranslate (ADMVOSVLDBBADENTRY, 0, &messageText, &tst)) { sprintf(backbuf, "%s %s", messageText, entry->name); (**callBack) (VOS_ERROR_MESSAGE, backbuf); } } continue; } /* * Check that the RW volume is on the same server that we were * passed */ if (serverHandle != NULL) { if (!VLDB_IsSameAddrs (c_handle, ntohl(rx_HostOf(rx_PeerOf(f_server->serv))), rw_server, &equal, &tst)) { if (callBack != NULL) { const char *messageText; if (util_AdminErrorCodeTranslate (ADMVOSVLDBBADSERVER, 0, &messageText, &tst)) { sprintf(backbuf, "%s %x %d", messageText, ntohl(rx_HostOf(rx_PeerOf(f_server->serv))), tst); (**callBack) (VOS_ERROR_MESSAGE, backbuf); } } continue; } if (!equal) { if (callBack != NULL) { const char *messageText; if (util_AdminErrorCodeTranslate (ADMVOSVLDBDIFFERENTADDR, 0, &messageText, &tst)) { sprintf(backbuf, "%s %s", messageText, entry->name); (**callBack) (VOS_ERROR_MESSAGE, backbuf); } } continue; } } /* * Check that the RW volume is on the same partition we were * passed */ if (partition != NULL) { if (*partition != rw_partition) { continue; } } /* * Backup the volume */ rc = UV_BackupVolume(c_handle, rw_server, rw_partition, rw_volid, &tst); } fail_vos_BackupVolumeCreateMultiple: if (arrayEntries.nbulkentries_val) { free(arrayEntries.nbulkentries_val); } if (st != NULL) { *st = tst; } return rc; } /* * vos_PartitionGet - get information about a single partition. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the server lives. * * IN serverHandle - a previously open vos server handle that holds * the partition of interest. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the integer that represents the partition of interest. * * OUT partitionP - a pointer to a vos_partitionEntry_t that upon successful * completion contains information regarding the partition. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_PartitionGet(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, vos_partitionEntry_p partitionP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; struct diskPartition part_info; file_server_p f_server = (file_server_p) serverHandle; char partitionName[10]; /* this rpc requires a character partition name */ /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_PartitionGet; } if (partitionP == NULL) { tst = ADMVOSPARTITIONPNULL; goto fail_vos_PartitionGet; } if (!vos_PartitionIdToName(partition, partitionName, &tst)) { goto fail_vos_PartitionGet; } tst = AFSVolPartitionInfo(f_server->serv, partitionName, &part_info); if (tst) { goto fail_vos_PartitionGet; } strcpy(partitionP->name, part_info.name); strcpy(partitionP->deviceName, part_info.devName); partitionP->lockFileDescriptor = part_info.lock_fd; partitionP->totalSpace = part_info.minFree; partitionP->totalFreeSpace = part_info.free; rc = 1; fail_vos_PartitionGet: if (st != NULL) { *st = tst; } return rc; } /* * The iterator functions and data for the partition retrieval functions. */ typedef struct partition_get { afs_int32 total_received; /* the total number of valid partiions retrieved */ int number_processed; /* the number of valid paritions we've handed out */ int index; /* the current index into the part_list array */ struct partList part_list; /* the list of partitions */ vos_partitionEntry_t partition[CACHED_ITEMS]; /* the cache of partitions */ const void *server; /* the server where the parititions exist */ } partition_get_t, *partition_get_p; static int GetPartitionInfoRPC(void *rpc_specific, int slot, int *last_item, int *last_item_contains_data, afs_status_p st) { int rc = 0; afs_status_t tst = 0; partition_get_p part = (partition_get_p) rpc_specific; vos_partitionEntry_p ptr = (vos_partitionEntry_p) & part->partition[slot]; /* * Skip partition entries that are not valid */ while (!(part->part_list.partFlags[part->index] & PARTVALID)) { part->index++; } /* * Get information for the next partition */ if (!vos_PartitionGet (0, part->server, 0, (unsigned int)part->part_list.partId[part->index], ptr, &tst)) { goto fail_GetPartitionInfoRPC; } part->index++; part->number_processed++; if (part->number_processed == part->total_received) { *last_item = 1; *last_item_contains_data = 1; } rc = 1; fail_GetPartitionInfoRPC: if (st != NULL) { *st = tst; } return rc; } static int GetPartitionInfoFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; partition_get_p part = (partition_get_p) rpc_specific; memcpy(dest, (const void *)&part->partition[slot], sizeof(vos_partitionEntry_t)); rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_PartitionGetBegin - begin to iterate over the partitions at a * particular server. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the server exists. * * IN serverHandle - the server that houses the partitions of interest. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * OUT iterationIdP - upon successful completion, contains an iterator that can * be passed to vos_PartitionGetNext. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_PartitionGetBegin(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, void **iterationIdP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t)); partition_get_p part = (partition_get_p) calloc(1, sizeof(partition_get_t)); /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_PartitionGetBegin; } if (iterationIdP == NULL) { goto fail_vos_PartitionGetBegin; } if ((iter == NULL) || (part == NULL)) { tst = ADMNOMEM; goto fail_vos_PartitionGetBegin; } /* * Fill in the part structure */ part->server = serverHandle; if (!UV_ListPartitions (f_server->serv, &part->part_list, &part->total_received, &tst)) { goto fail_vos_PartitionGetBegin; } /* * If we didn't receive any partitions, don't spawn a background thread. * Mark the iterator complete. */ if (part->total_received == 0) { if (!IteratorInit(iter, (void *)part, NULL, NULL, NULL, NULL, &tst)) { goto fail_vos_PartitionGetBegin; } iter->done_iterating = 1; iter->st = ADMITERATORDONE; } else { if (!IteratorInit (iter, (void *)part, GetPartitionInfoRPC, GetPartitionInfoFromCache, NULL, NULL, &tst)) { goto fail_vos_PartitionGetBegin; } } *iterationIdP = (void *)iter; rc = 1; fail_vos_PartitionGetBegin: if (rc == 0) { if (iter != NULL) { free(iter); } if (part != NULL) { free(part); } } if (st != NULL) { *st = tst; } return rc; } /* * vos_PartitionGetNext - get the next partition at a server. * * PARAMETERS * * IN iterationId - an iterator previously returned by vos_PartitionGetBegin * * OUT partitionP - a pointer to a vos_partitionEntry_t that upon successful * completion contains the next partition. * * LOCKS * * The iterator is locked while the next parition is retrieved. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_PartitionGetNext(const void *iterationId, vos_partitionEntry_p partitionP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_PartitionGetNext; } if (partitionP == NULL) { tst = ADMVOSPARTITIONPNULL; goto fail_vos_PartitionGetNext; } rc = IteratorNext(iter, (void *)partitionP, &tst); fail_vos_PartitionGetNext: if (st != NULL) { *st = tst; } return rc; } /* * vos_PartitionGetDone - finish using a partition iterator. * * PARAMETERS * * IN iterationId - an iterator previously returned by vos_PartitionGetBegin * * LOCKS * * The iterator is locked and then destroyed. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_PartitionGetDone(const void *iterationId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; /* * Validate arguments */ if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_PartitionGetDone; } rc = IteratorDone(iter, &tst); fail_vos_PartitionGetDone: if (st != NULL) { *st = tst; } return rc; } /* * vos_ServerOpen - open a handle to an individual server for future * operations * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the server lives. * * IN serverName - the machine name of the server * * OUT serverHandleP - a void pointer that upon successful completion * contains a handle that is used in future operations upon the server. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ServerOpen(const void *cellHandle, const char *serverName, void **serverHandleP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) malloc(sizeof(file_server_t)); int server_address; struct rx_securityClass *sc[3]; int scIndex; if (f_server == NULL) { tst = ADMNOMEM; goto fail_vos_ServerOpen; } /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_ServerOpen; } if (!c_handle->tokens->afs_token_set) { tst = ADMVOSCELLHANDLENOAFSTOKENS; goto fail_vos_ServerOpen; } if (!util_AdminServerAddressGetFromName (serverName, &server_address, &tst)) { goto fail_vos_ServerOpen; } scIndex = c_handle->tokens->sc_index; sc[scIndex] = c_handle->tokens->afs_sc[scIndex]; f_server->serv = rx_GetCachedConnection(htonl(server_address), htons(AFSCONF_VOLUMEPORT), VOLSERVICE_ID, sc[scIndex], scIndex); if (f_server->serv != NULL) { f_server->begin_magic = BEGIN_MAGIC; f_server->end_magic = END_MAGIC; f_server->is_valid = 1; *serverHandleP = (void *)f_server; rc = 1; } else { tst = ADMVOSSERVERNOCONNECTION; goto fail_vos_ServerOpen; } fail_vos_ServerOpen: if (st != NULL) { *st = tst; } return rc; } /* * vos_ServerClose - close a handle previously obtained from vos_ServerOpen * * PARAMETERS * * IN serverHandle - an existing server handle. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ServerClose(const void *serverHandle, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_ServerClose; } rx_ReleaseCachedConnection(f_server->serv); f_server->is_valid = 0; free(f_server); rc = 1; fail_vos_ServerClose: if (st != NULL) { *st = tst; } return rc; } /* * vos_ServerSync - synchronize the vldb and the fileserver at a particular * server. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the server lives. * * IN serverHandle - a handle to the server machine. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition to synchronize. Can be NULL. * * IN force - force deletion of bad volumes. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ServerSync(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, const unsigned int *partition, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; afs_int32 part = 0; int flags = 0; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_ServerSync; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_ServerSync; } if (partition != NULL) { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_ServerSync; } part = (afs_int32) * partition; flags = 1; } /* * sync the server */ rc = UV_SyncServer(c_handle, f_server->serv, part, flags, &tst); fail_vos_ServerSync: if (st != NULL) { *st = tst; } return rc; } /* * vos_FileServerAddressChange - change an existing file server address. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the address should be changed. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN oldAddress - the old server address in host byte order * * IN newAddress - the new server address in host byte order * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_FileServerAddressChange(const void *cellHandle, vos_MessageCallBack_t callBack, int oldAddress, int newAddress, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_FileServerAddressChange; } tst = ubik_Call_New(VL_ChangeAddr, c_handle->vos, 0, oldAddress, newAddress); if (tst) { goto fail_vos_FileServerAddressChange; } rc = 1; fail_vos_FileServerAddressChange: if (st != NULL) { *st = tst; } return rc; } /* * vos_FileServerAddressRemove - remove an existing file server address. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the address should be removed. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN serverAddress - the server address to remove in host byte order. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_FileServerAddressRemove(const void *cellHandle, vos_MessageCallBack_t callBack, int serverAddress, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; int dummyAddress = 0xffffffff; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_FileServerAddressRemove; } tst = ubik_Call_New(VL_ChangeAddr, c_handle->vos, 0, dummyAddress, serverAddress); if (tst) { goto fail_vos_FileServerAddressRemove; } rc = 1; fail_vos_FileServerAddressRemove: if (st != NULL) { *st = tst; } return rc; } /* * The iterator functions and data for the server retrieval functions. * * These functions are very similar to the FileServerAddressGet * functions. The main difference being that instead of returning * a single address at a time for a server, we fill an array with * all the addresses of a server. */ typedef struct server_get { struct ubik_client *vldb; /* connection for future rpc's if neccessary */ afs_int32 total_addresses; /* total number of addresses */ bulkaddrs addresses; /* the list of addresses */ int address_index; /* current index into address list */ vos_fileServerEntry_t server[CACHED_ITEMS]; /* the cache of servers */ } server_get_t, *server_get_p; static int GetServerRPC(void *rpc_specific, int slot, int *last_item, int *last_item_contains_data, afs_status_p st) { int rc = 0; afs_status_t tst = 0; server_get_p serv = (server_get_p) rpc_specific; afs_uint32 *addrP = &serv->addresses.bulkaddrs_val[serv->address_index]; afs_int32 base, index; afsUUID m_uuid; afs_int32 m_unique; ListAddrByAttributes m_attrs; afs_int32 total_multi; bulkaddrs addr_multi; int i; /* * Check to see if this is a multihomed address server */ if (((*addrP & 0xff000000) == 0xff000000) && ((*addrP) & 0xffff)) { base = (*addrP >> 16) & 0xff; index = (*addrP) & 0xffff; if ((base >= 0) && (base <= VL_MAX_ADDREXTBLKS) && (index >= 1) && (index <= VL_MHSRV_PERBLK)) { /* * This is a multihomed server. Make an rpc to retrieve * all its addresses. Copy the addresses into the cache. */ m_attrs.Mask = VLADDR_INDEX; m_attrs.index = (base * VL_MHSRV_PERBLK) + index; total_multi = 0; addr_multi.bulkaddrs_val = 0; addr_multi.bulkaddrs_len = 0; tst = ubik_Call(VL_GetAddrsU, serv->vldb, 0, &m_attrs, &m_uuid, &m_unique, &total_multi, &addr_multi); if (tst) { goto fail_GetServerRPC; } /* * Remove any bogus IP addresses which the user may have * been unable to remove. */ RemoveBadAddresses(&total_multi, &addr_multi); /* * Copy all the addresses into the cache */ for (i = 0; i < total_multi; i++) { serv->server[slot].serverAddress[i] = addr_multi.bulkaddrs_val[i]; } serv->server[slot].count = total_multi; serv->address_index++; free(addr_multi.bulkaddrs_val); } /* * The next address is just a plain old address */ } else { serv->server[slot].serverAddress[0] = *addrP; serv->server[slot].count = 1; serv->address_index++; } /* * See if we've processed all the entries */ if (serv->address_index == serv->total_addresses) { *last_item = 1; *last_item_contains_data = 1; } rc = 1; fail_GetServerRPC: if (st != NULL) { *st = tst; } return rc; } static int GetServerFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; server_get_p serv = (server_get_p) rpc_specific; memcpy(dest, (const void *)&serv->server[slot], sizeof(vos_fileServerEntry_t)); rc = 1; if (st != NULL) { *st = tst; } return rc; } static int DestroyServer(void *rpc_specific, afs_status_p st) { int rc = 0; afs_status_t tst = 0; server_get_p serv = (server_get_p) rpc_specific; if (serv->addresses.bulkaddrs_val != NULL) { free(serv->addresses.bulkaddrs_val); } rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_FileServerGetBegin - begin to iterate over the file servers in a cell. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the file servers exist. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * OUT iterationIdP - upon successful completion, contains an iterator that * can be passed to vos_FileServerGetNext. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_FileServerGetBegin(const void *cellHandle, vos_MessageCallBack_t callBack, void **iterationIdP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t)); server_get_p serv = (server_get_p) calloc(1, sizeof(server_get_t)); struct VLCallBack unused; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_FileServerGetBegin; } if (iterationIdP == NULL) { goto fail_vos_FileServerGetBegin; } if ((iter == NULL) || (serv == NULL)) { tst = ADMNOMEM; goto fail_vos_FileServerGetBegin; } /* * Fill in the serv structure */ serv->vldb = c_handle->vos; tst = ubik_Call_New(VL_GetAddrs, c_handle->vos, 0, 0, 0, &unused, &serv->total_addresses, &serv->addresses); if (tst) { goto fail_vos_FileServerGetBegin; } /* * Remove any bogus IP addresses which the user may have * been unable to remove. */ RemoveBadAddresses(&serv->total_addresses, &serv->addresses); if (serv->total_addresses == 0) { if (!IteratorInit(iter, (void *)serv, NULL, NULL, NULL, NULL, &tst)) { goto fail_vos_FileServerGetBegin; } iter->done_iterating = 1; iter->st = ADMITERATORDONE; } else { if (!IteratorInit (iter, (void *)serv, GetServerRPC, GetServerFromCache, NULL, DestroyServer, &tst)) { goto fail_vos_FileServerGetBegin; } } *iterationIdP = (void *)iter; rc = 1; fail_vos_FileServerGetBegin: if (rc == 0) { if (iter != NULL) { free(iter); } if (serv != NULL) { if (serv->addresses.bulkaddrs_val != NULL) { free(serv->addresses.bulkaddrs_val); } free(serv); } } if (st != NULL) { *st = tst; } return rc; } /* * vos_FileServerGetNext - get information about the next fileserver in the cell. * * PARAMETERS * * IN iterationId - an iterator previously returned by * vos_FileServerGetBegin * * OUT serverEntryP - a pointer to a vos_fileServerEntry_t that upon successful * completion contains information about the next server in the cell. * * LOCKS * * The iterator is locked while the next server is retrieved. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_FileServerGetNext(void *iterationId, vos_fileServerEntry_p serverEntryP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_FileServerGetNext; } if (serverEntryP == NULL) { tst = ADMVOSSERVERENTRYPNULL; goto fail_vos_FileServerGetNext; } rc = IteratorNext(iter, (void *)serverEntryP, &tst); fail_vos_FileServerGetNext: if (st != NULL) { *st = tst; } return rc; } /* * vos_FileServerGetDone - finish using a partition iterator. * * PARAMETERS * * IN iterationId - an iterator previously returned by vos_FileServerGetBegin * * LOCKS * * The iterator is locked and then destroyed. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_FileServerGetDone(void *iterationId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; /* * Validate arguments */ if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_FileServerGetDone; } rc = IteratorDone(iter, &tst); fail_vos_FileServerGetDone: if (st != NULL) { *st = tst; } return rc; } /* * The iterator functions and data for the transation retrieval functions. */ typedef struct transaction_get { afs_int32 total; /* total number of transactions */ afs_int32 index; /* index to the current transaction */ transDebugInfo *cur; /* the current transaction */ vos_serverTransactionStatus_t tran[CACHED_ITEMS]; /* the cache of trans */ } transaction_get_t, *transaction_get_p; static int GetTransactionRPC(void *rpc_specific, int slot, int *last_item, int *last_item_contains_data, afs_status_p st) { int rc = 0; afs_status_t tst = 0; transaction_get_p t = (transaction_get_p) rpc_specific; int index = t->index; /* * Copy the next transaction into the cache */ t->tran[slot].transactionId = t->cur[index].tid; t->tran[slot].lastActiveTime = t->cur[index].time; t->tran[slot].creationTime = t->cur[index].creationTime; t->tran[slot].errorCode = t->cur[index].returnCode; t->tran[slot].volumeId = t->cur[index].volid; t->tran[slot].partition = t->cur[index].partition; strcpy(t->tran[slot].lastProcedureName, t->cur[index].lastProcName); t->tran[slot].nextReceivePacketSequenceNumber = t->cur[index].readNext; t->tran[slot].nextSendPacketSequenceNumber = t->cur[index].transmitNext; t->tran[slot].lastReceiveTime = t->cur[index].lastReceiveTime; t->tran[slot].lastSendTime = t->cur[index].lastSendTime; t->tran[slot].volumeAttachMode = VOS_VOLUME_ATTACH_MODE_OK; switch (t->cur[index].iflags) { case ITOffline: t->tran[slot].volumeAttachMode = VOS_VOLUME_ATTACH_MODE_OFFLINE; break; case ITBusy: t->tran[slot].volumeAttachMode = VOS_VOLUME_ATTACH_MODE_BUSY; break; case ITReadOnly: t->tran[slot].volumeAttachMode = VOS_VOLUME_ATTACH_MODE_READONLY; break; case ITCreate: t->tran[slot].volumeAttachMode = VOS_VOLUME_ATTACH_MODE_CREATE; break; case ITCreateVolID: t->tran[slot].volumeAttachMode = VOS_VOLUME_ATTACH_MODE_CREATE_VOLID; break; } t->tran[slot].volumeActiveStatus = VOS_VOLUME_ACTIVE_STATUS_OK; switch (t->cur[index].vflags) { case VTDeleteOnSalvage: t->tran[slot].volumeActiveStatus = VOS_VOLUME_ACTIVE_STATUS_DELETE_ON_SALVAGE; break; case VTOutOfService: t->tran[slot].volumeActiveStatus = VOS_VOLUME_ACTIVE_STATUS_OUT_OF_SERVICE; break; case VTDeleted: t->tran[slot].volumeActiveStatus = VOS_VOLUME_ACTIVE_STATUS_DELETED; break; } t->tran[slot].volumeTransactionStatus = VOS_VOLUME_TRANSACTION_STATUS_OK; if (t->cur[index].tflags) { t->tran[slot].volumeTransactionStatus = VOS_VOLUME_TRANSACTION_STATUS_DELETED; } t->index++; /* * See if we've processed all the entries */ if (t->index == t->total) { *last_item = 1; *last_item_contains_data = 1; } rc = 1; if (st != NULL) { *st = tst; } return rc; } static int GetTransactionFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; transaction_get_p tran = (transaction_get_p) rpc_specific; memcpy(dest, (const void *)&tran->tran[slot], sizeof(vos_serverTransactionStatus_p)); rc = 1; if (st != NULL) { *st = tst; } return rc; } static int DestroyTransaction(void *rpc_specific, afs_status_p st) { int rc = 0; afs_status_t tst = 0; transaction_get_p tran = (transaction_get_p) rpc_specific; if (tran->cur != NULL) { free(tran->cur); } rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_ServerTransactionStatusGetBegin - begin to iterate over the transactions * at a volume server. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume server exists. * * IN serverHandle - a handle to the server to query. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * OUT iterationIdP - upon successful completion, contains an iterator that * can be passed to vos_ServerTransactionStatusGetNext. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ServerTransactionStatusGetBegin(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, void **iterationIdP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t)); transaction_get_p tran = (transaction_get_p) calloc(1, sizeof(transaction_get_t)); /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_ServerTransactionStatusGetBegin; } if (iterationIdP == NULL) { goto fail_vos_ServerTransactionStatusGetBegin; } if ((iter == NULL) || (tran == NULL)) { tst = ADMNOMEM; goto fail_vos_ServerTransactionStatusGetBegin; } /* * Fill in the tran structure */ if (!UV_VolserStatus(f_server->serv, &tran->cur, &tran->total, &tst)) { goto fail_vos_ServerTransactionStatusGetBegin; } if (tran->total == 0) { if (!IteratorInit(iter, (void *)tran, NULL, NULL, NULL, NULL, &tst)) { goto fail_vos_ServerTransactionStatusGetBegin; } iter->done_iterating = 1; iter->st = ADMITERATORDONE; } else { if (!IteratorInit (iter, (void *)tran, GetTransactionRPC, GetTransactionFromCache, NULL, DestroyTransaction, &tst)) { goto fail_vos_ServerTransactionStatusGetBegin; } } *iterationIdP = (void *)iter; rc = 1; fail_vos_ServerTransactionStatusGetBegin: if (rc == 0) { if (iter != NULL) { free(iter); } if (tran != NULL) { if (tran->cur != NULL) { free(tran->cur); } free(tran); } } if (st != NULL) { *st = tst; } return rc; } /* * vos_ServerTransactionStatusGetNext - get information about the next * active transaction. * * PARAMETERS * * IN iterationId - an iterator previously returned by * vos_ServerTransactionStatusGetBegin * * OUT serverTransactionStatusP - a pointer to a vos_serverTransactionStatus_p * that upon successful completion contains information about the * next transaction. * * LOCKS * * The iterator is locked while the next item is retrieved. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ServerTransactionStatusGetNext(const void *iterationId, vos_serverTransactionStatus_p serverTransactionStatusP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_ServerTransactionStatusGetNext; } if (serverTransactionStatusP == NULL) { tst = ADMVOSSERVERTRANSACTIONSTATUSPNULL; goto fail_vos_ServerTransactionStatusGetNext; } rc = IteratorNext(iter, (void *)serverTransactionStatusP, &tst); fail_vos_ServerTransactionStatusGetNext: if (st != NULL) { *st = tst; } return rc; } /* * vos_ServerTransactionStatusGetDone - finish using a transaction iterator. * * PARAMETERS * * IN iterationId - an iterator previously returned by * vos_ServerTransactionStatusGetBegin * * LOCKS * * The iterator is locked and then destroyed. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ServerTransactionStatusGetDone(const void *iterationId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; /* * Validate arguments */ if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_ServerTransactionStatusGetDone; } rc = IteratorDone(iter, &tst); fail_vos_ServerTransactionStatusGetDone: if (st != NULL) { *st = tst; } return rc; } static int copyVLDBEntry(struct nvldbentry *source, vos_vldbEntry_p dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; int i; dest->numServers = source->nServers; for (i = 0; i < VOS_MAX_VOLUME_TYPES; i++) { dest->volumeId[i] = source->volumeId[i]; } dest->cloneId = source->cloneId; dest->status = VOS_VLDB_ENTRY_OK; if (source->flags & VLOP_ALLOPERS) { dest->status |= VOS_VLDB_ENTRY_LOCKED; } else { if (source->flags & VLOP_MOVE) { dest->status |= VOS_VLDB_ENTRY_MOVE; } if (source->flags & VLOP_RELEASE) { dest->status |= VOS_VLDB_ENTRY_RELEASE; } if (source->flags & VLOP_BACKUP) { dest->status |= VOS_VLDB_ENTRY_BACKUP; } if (source->flags & VLOP_DELETE) { dest->status |= VOS_VLDB_ENTRY_DELETE; } if (source->flags & VLOP_DUMP) { dest->status |= VOS_VLDB_ENTRY_DUMP; } } if (source->flags & VLF_RWEXISTS) { dest->status |= VOS_VLDB_ENTRY_RWEXISTS; } if (source->flags & VLF_ROEXISTS) { dest->status |= VOS_VLDB_ENTRY_ROEXISTS; } if (source->flags & VLF_BACKEXISTS) { dest->status |= VOS_VLDB_ENTRY_BACKEXISTS; } strcpy(dest->name, source->name); for (i = 0; i < VOS_MAX_REPLICA_SITES; i++) { dest->volumeSites[i].serverAddress = source->serverNumber[i]; dest->volumeSites[i].serverPartition = source->serverPartition[i]; dest->volumeSites[i].serverFlags = 0; if (source->serverFlags[i] & NEW_REPSITE) { dest->volumeSites[i].serverFlags |= VOS_VLDB_NEW_REPSITE; } if (source->serverFlags[i] & ITSROVOL) { dest->volumeSites[i].serverFlags |= VOS_VLDB_READ_ONLY; } if (source->serverFlags[i] & ITSRWVOL) { dest->volumeSites[i].serverFlags |= VOS_VLDB_READ_WRITE; } if (source->serverFlags[i] & ITSBACKVOL) { dest->volumeSites[i].serverFlags |= VOS_VLDB_BACKUP; } if (source->serverFlags[i] & RO_DONTUSE) { dest->volumeSites[i].serverFlags |= VOS_VLDB_DONT_USE; } } rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBGet- get a volume's vldb entry. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume entries exist. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the id of the volume to retrieve. * * IN volumeName - the name of the volume to retrieve. * * OUT vldbEntry - upon successful completion, contains the information regarding * the volume. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBGet(const void *cellHandle, vos_MessageCallBack_t callBack, const unsigned int *volumeId, const char *volumeName, vos_vldbEntry_p vldbEntry, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; struct nvldbentry entry; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBGet; } if (vldbEntry == NULL) { tst = ADMVOSVLDBENTRYNULL; goto fail_vos_VLDBGet; } if (((volumeName == NULL) || (*volumeName == 0)) && (volumeId == NULL)) { tst = ADMVOSVOLUMENAMEANDVOLUMEIDNULL; goto fail_vos_VLDBGet; } /* * Retrieve the entry */ if (!((volumeName == NULL) || (*volumeName == 0))) { if (!ValidateVolumeName(volumeName, &tst)) { goto fail_vos_VLDBGet; } if (!VLDB_GetEntryByName(c_handle, volumeName, &entry, &tst)) { goto fail_vos_VLDBGet; } } else { if (!VLDB_GetEntryByID(c_handle, *volumeId, -1, &entry, &tst)) { goto fail_vos_VLDBGet; } } /* * Copy the entry into our structure */ if (!copyVLDBEntry(&entry, vldbEntry, &tst)) { goto fail_vos_VLDBGet; } rc = 1; fail_vos_VLDBGet: if (st != NULL) { *st = tst; } return rc; } /* * The iterator functions and data for the vldb entry retrieval functions. */ typedef struct vldb_entry_get { afs_int32 total; /* total number of vldb entries */ afs_int32 index; /* index to the current vldb entry */ nbulkentries entries; /* the list of entries retrieved */ vos_vldbEntry_t entry[CACHED_ITEMS]; /* the cache of entries */ } vldb_entry_get_t, *vldb_entry_get_p; static int GetVLDBEntryRPC(void *rpc_specific, int slot, int *last_item, int *last_item_contains_data, afs_status_p st) { int rc = 0; afs_status_t tst = 0; vldb_entry_get_p entry = (vldb_entry_get_p) rpc_specific; /* * Copy the next entry into the cache */ if (!copyVLDBEntry (&entry->entries.nbulkentries_val[entry->index], &entry->entry[slot], &tst)) { goto fail_GetVLDBEntryRPC; } entry->index++; /* * See if we've processed all the entries */ if (entry->index == entry->total) { *last_item = 1; *last_item_contains_data = 1; } rc = 1; fail_GetVLDBEntryRPC: if (st != NULL) { *st = tst; } return rc; } static int GetVLDBEntryFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; vldb_entry_get_p entry = (vldb_entry_get_p) rpc_specific; memcpy(dest, (const void *)&entry->entry[slot], sizeof(vos_vldbEntry_t)); rc = 1; if (st != NULL) { *st = tst; } return rc; } static int DestroyVLDBEntry(void *rpc_specific, afs_status_p st) { int rc = 0; afs_status_t tst = 0; vldb_entry_get_p entry = (vldb_entry_get_p) rpc_specific; if (entry->entries.nbulkentries_val != NULL) { free(entry->entries.nbulkentries_val); } rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBGetBegin - begin to iterate over the VLDB. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume entries exist. * * IN serverHandle - a handle to the server whose entries should be listed. * Can be null. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition whose entries should be listed. * Can be null. * * OUT iterationIdP - upon successful completion, contains an iterator that * can be passed to vos_VLDBGetNext. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBGetBegin(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int *partition, void **iterationIdP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t)); vldb_entry_get_p entry = (vldb_entry_get_p) calloc(1, sizeof(vldb_entry_get_t)); struct VldbListByAttributes attr; attr.Mask = 0; memset(&attr, 0, sizeof(attr)); /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBGetBegin; } if ((iter == NULL) || (entry == NULL)) { tst = ADMNOMEM; goto fail_vos_VLDBGetBegin; } if (f_server != NULL) { if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VLDBGetBegin; } attr.server = ntohl(rx_HostOf(rx_PeerOf(f_server->serv))); attr.Mask |= VLLIST_SERVER; } if (partition != NULL) { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VLDBGetBegin; } attr.partition = *partition; attr.Mask |= VLLIST_PARTITION; } if (!VLDB_ListAttributes (c_handle, &attr, &entry->total, &entry->entries, &tst)) { goto fail_vos_VLDBGetBegin; } if (entry->total <= 0) { if (!IteratorInit(iter, (void *)entry, NULL, NULL, NULL, NULL, &tst)) { goto fail_vos_VLDBGetBegin; } iter->done_iterating = 1; iter->st = ADMITERATORDONE; } else { if (!IteratorInit (iter, (void *)entry, GetVLDBEntryRPC, GetVLDBEntryFromCache, NULL, DestroyVLDBEntry, &tst)) { goto fail_vos_VLDBGetBegin; } } *iterationIdP = (void *)iter; rc = 1; fail_vos_VLDBGetBegin: if (rc == 0) { if (iter != NULL) { free(iter); } if (entry->entries.nbulkentries_val != NULL) { free(entry->entries.nbulkentries_val); } if (entry != NULL) { free(entry); } } if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBGetNext - get information about the next volume. * * PARAMETERS * * IN iterationId - an iterator previously returned by * vos_VLDBGetBegin * * OUT vldbEntry - a pointer to a vos_vldbEntry_t * that upon successful completion contains information about the * next volume. * * LOCKS * * The iterator is locked while the next item is retrieved. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBGetNext(const void *iterationId, vos_vldbEntry_p vldbEntry, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_VLDBGetNext; } if (vldbEntry == NULL) { tst = ADMVOSVLDBENTRYNULL; goto fail_vos_VLDBGetNext; } rc = IteratorNext(iter, (void *)vldbEntry, &tst); fail_vos_VLDBGetNext: if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBGetDone - finish using a volume iterator. * * PARAMETERS * * IN iterationId - an iterator previously returned by vos_VLDBGetBegin * * LOCKS * * The iterator is locked and then destroyed. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBGetDone(const void *iterationId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; /* * Validate arguments */ if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_VLDBGetDone; } rc = IteratorDone(iter, &tst); fail_vos_VLDBGetDone: if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBEntryRemove - remove a vldb entry. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the vldb entry exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the vldb entry exists. Can be null. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the vldb entry exists. Can be null. * * IN volumeId - the volume id of the vldb entry to be deleted. Can be null. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBEntryRemove(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, const unsigned int *partition, unsigned int *volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; struct VldbListByAttributes attr; nbulkentries entries; afs_int32 nentries; int i; memset(&attr, 0, sizeof(attr)); memset(&entries, 0, sizeof(entries)); /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBEntryRemove; } /* * If the volume is specified, just delete it */ if (volumeId != NULL) { tst = ubik_Call(VL_DeleteEntry, c_handle->vos, 0, *volumeId, -1); if (tst != 0) { goto fail_vos_VLDBEntryRemove; } } if (f_server != NULL) { if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VLDBEntryRemove; } attr.server = ntohl(rx_HostOf(rx_PeerOf(f_server->serv))); attr.Mask |= VLLIST_SERVER; } if (partition != NULL) { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VLDBEntryRemove; } attr.partition = *partition; attr.Mask |= VLLIST_PARTITION; } if ((f_server == NULL) && (partition == NULL)) { tst = ADMVOSVLDBDELETEALLNULL; goto fail_vos_VLDBEntryRemove; } if (!VLDB_ListAttributes(c_handle, &attr, &nentries, &entries, &tst)) { goto fail_vos_VLDBEntryRemove; } if (nentries <= 0) { tst = ADMVOSVLDBNOENTRIES; goto fail_vos_VLDBEntryRemove; } for (i = 0; i < nentries; i++) { ubik_Call(VL_DeleteEntry, c_handle->vos, 0, entries.nbulkentries_val[i].volumeId[RWVOL]); } rc = 1; fail_vos_VLDBEntryRemove: if (entries.nbulkentries_val) { free(entries.nbulkentries_val); } if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBUnlock - unlock vldb entries en masse. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the vldb entries exist. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the vldb entries exist. Can be null. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the vldb entries exist. Can be null. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBUnlock(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, const unsigned int *partition, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; struct VldbListByAttributes attr; nbulkentries entries; afs_int32 nentries; int i; memset(&attr, 0, sizeof(attr)); memset(&entries, 0, sizeof(entries)); /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBUnlock; } if (f_server != NULL) { if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VLDBUnlock; } attr.server = ntohl(rx_HostOf(rx_PeerOf(f_server->serv))); attr.Mask |= VLLIST_SERVER; } if (partition != NULL) { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VLDBUnlock; } attr.partition = *partition; attr.Mask |= VLLIST_PARTITION; } attr.flag = VLOP_ALLOPERS; attr.Mask |= VLLIST_FLAG; if (!VLDB_ListAttributes(c_handle, &attr, &nentries, &entries, &tst)) { goto fail_vos_VLDBUnlock; } if (nentries <= 0) { tst = ADMVOSVLDBNOENTRIES; goto fail_vos_VLDBUnlock; } for (i = 0; i < nentries; i++) { vos_VLDBEntryUnlock(cellHandle, 0, entries.nbulkentries_val[i].volumeId[RWVOL], &tst); } rc = 1; fail_vos_VLDBUnlock: if (entries.nbulkentries_val) { free(entries.nbulkentries_val); } if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBEntryLock - lock a vldb entry. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the vldb entry exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the volume id of the vldb entry to be deleted. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBEntryLock(const void *cellHandle, vos_MessageCallBack_t callBack, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBEntryLock; } tst = ubik_Call(VL_SetLock, c_handle->vos, 0, volumeId, -1, VLOP_DELETE); if (tst != 0) { goto fail_vos_VLDBEntryLock; } rc = 1; fail_vos_VLDBEntryLock: if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBEntryUnlock - unlock a vldb entry. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the vldb entry exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the volume id of the vldb entry to be unlocked. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBEntryUnlock(const void *cellHandle, vos_MessageCallBack_t callBack, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBEntryUnlock; } tst = ubik_Call(VL_ReleaseLock, c_handle->vos, 0, volumeId, -1, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP); if (tst != 0) { goto fail_vos_VLDBEntryUnlock; } rc = 1; fail_vos_VLDBEntryUnlock: if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBReadOnlySiteCreate - create a readonly site for a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the new volume should be created. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where then new volume should be created. * * IN volumeId - the volume id of the volume to be replicated. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBReadOnlySiteCreate(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBReadOnlySiteCreate; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VLDBReadOnlySiteCreate; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VLDBReadOnlySiteCreate; } if (!UV_AddSite (c_handle, ntohl(rx_HostOf(rx_PeerOf(f_server->serv))), partition, volumeId, &tst)) { goto fail_vos_VLDBReadOnlySiteCreate; } rc = 1; fail_vos_VLDBReadOnlySiteCreate: if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBReadOnlySiteDelete - delete a replication site for a volume. * * PARAMETERS * * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume should be deleted. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where then volume should be deleted. * * IN volumeId - the volume id of the volume to be deleted. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBReadOnlySiteDelete(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBReadOnlySiteDelete; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VLDBReadOnlySiteDelete; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VLDBReadOnlySiteDelete; } if (!UV_RemoveSite (c_handle, ntohl(rx_HostOf(rx_PeerOf(f_server->serv))), partition, volumeId, &tst)) { goto fail_vos_VLDBReadOnlySiteDelete; } rc = 1; fail_vos_VLDBReadOnlySiteDelete: if (st != NULL) { *st = tst; } return rc; } /* * vos_VLDBSync - synchronize the vldb with the fileserver. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the sync should occur. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the sync should occur. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the sync should occur. Can be null. * * IN force - force deletion of bad volumes. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VLDBSync(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, const unsigned int *partition, vos_force_t force, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; afs_int32 part = 0; int flags = 0; int force_flag = 0; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VLDBSync; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VLDBSync; } if (partition != NULL) { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VLDBSync; } part = (afs_int32) * partition; flags = 1; } if (force == VOS_FORCE) { force_flag = 1; } /* * sync the vldb */ rc = UV_SyncVldb(c_handle, f_server->serv, part, flags, force_flag, &tst); fail_vos_VLDBSync: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeCreate - create a new partition. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the server lives. * * IN serverHandle - a previously open vos server handle that holds * the partition where the volume should be create. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the integer that represents the partition that will * house the new volume. * * IN volumeName - the name of the new volume. * * IN quota - the quota of the new volume. * * OUT volumeId - the volume id of the newly created volume. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeCreate(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, const char *volumeName, unsigned int quota, unsigned int *volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; vos_partitionEntry_t pinfo; struct nvldbentry vinfo; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeCreate; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeCreate; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VolumeCreate; } if (!ValidateVolumeName(volumeName, &tst)) { goto fail_vos_VolumeCreate; } if (volumeId == NULL) { tst = ADMVOSVOLUMEID; goto fail_vos_VolumeCreate; } /* * Check that partition is valid at the server */ if (!vos_PartitionGet (cellHandle, serverHandle, 0, partition, &pinfo, &tst)) { goto fail_vos_VolumeCreate; } /* * Check that the volume doesn't already exist */ if (VLDB_GetEntryByName(c_handle, volumeName, &vinfo, &tst)) { tst = ADMVOSVOLUMENAMEDUP; goto fail_vos_VolumeCreate; } /* * Create the new volume */ rc = UV_CreateVolume(c_handle, f_server->serv, partition, volumeName, quota, volumeId, &tst); fail_vos_VolumeCreate: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeDelete - remove a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be deleted. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeDelete(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; vos_partitionEntry_t pinfo; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeDelete; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeDelete; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VolumeDelete; } /* * Check that partition is valid at the server */ if (!vos_PartitionGet (cellHandle, serverHandle, 0, partition, &pinfo, &tst)) { goto fail_vos_VolumeDelete; } rc = UV_DeleteVolume(c_handle, f_server->serv, partition, volumeId, &tst); fail_vos_VolumeDelete: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeRename - rename a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the vldb entry exists. Can be null. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN readWriteVolumeId - the volume id of the volume to be renamed. * * IN newVolumeName - the new name. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeRename(const void *cellHandle, vos_MessageCallBack_t callBack, unsigned int readWriteVolumeId, const char *newVolumeName, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; struct nvldbentry entry; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeRename; } if ((newVolumeName == NULL) || (*newVolumeName == 0)) { tst = ADMVOSNEWVOLUMENAMENULL; goto fail_vos_VolumeRename; } /* * Retrieve the entry */ if (!VLDB_GetEntryByID(c_handle, readWriteVolumeId, -1, &entry, &tst)) { goto fail_vos_VolumeRename; } rc = UV_RenameVolume(c_handle, &entry, newVolumeName, &tst); fail_vos_VolumeRename: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeDump - dump a volume * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. Can be null. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the volume id of the volume to be dumped. * * IN startTime - files with modification times >= this time will be dumped. * * IN dumpFile - the file to dump the volume to. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeDump(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int *partition, unsigned int volumeId, unsigned int startTime, const char *dumpFile, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; afs_int32 server, part, voltype; struct nvldbentry entry; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeDump; } if (serverHandle != NULL) { if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeDump; } } /* * You must specify both the serverHandle and the partition */ if (serverHandle || partition) { if (!serverHandle || !partition) { tst = ADMVOSSERVERANDPARTITION; goto fail_vos_VolumeDump; } else { if (*partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VolumeDump; } server = ntohl(rx_HostOf(rx_PeerOf(f_server->serv))); part = *partition; } } else { if (!GetVolumeInfo (c_handle, volumeId, &entry, &server, &part, &voltype, &tst)) { goto fail_vos_VolumeDump; } } if ((dumpFile == NULL) || (*dumpFile == 0)) { tst = ADMVOSDUMPFILENULL; goto fail_vos_VolumeDump; } rc = UV_DumpVolume(c_handle, volumeId, server, part, startTime, dumpFile, &tst); fail_vos_VolumeDump: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeRestore - restore a volume from a dump * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be restored. * * IN volumeName - the volume name of the volume to be restored. * * IN dumpFile - the file from which to restore the volume. * * IN dumpType - the type of dump to perform. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeRestore(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int *volumeId, const char *volumeName, const char *dumpFile, vos_volumeRestoreType_t dumpType, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; struct nvldbentry entry; afs_int32 volid, server; int fd; struct stat status; int restoreflags = 0; afs_int32 Oserver, Opart, Otype; struct nvldbentry Oentry; int equal; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeRestore; } if (serverHandle != NULL) { if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeRestore; } } /* * Must pass volumeName */ if ((volumeName == NULL) || (*volumeName == 0)) { tst = ADMVOSVOLUMENAMENULL; goto fail_vos_VolumeRestore; } if (!ValidateVolumeName(volumeName, &tst)) { goto fail_vos_VolumeRestore; } /* * If volumeId is passed, it must be a valid volume id */ if (volumeId != NULL) { if (!VLDB_GetEntryByID(c_handle, *volumeId, -1, &entry, &tst)) { goto fail_vos_VolumeRestore; } volid = *volumeId; } else { volid = 0; } server = ntohl(rx_HostOf(rx_PeerOf(f_server->serv))); if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONTOOLARGE; goto fail_vos_VolumeRestore; } /* * Check that dumpFile exists and can be accessed */ fd = open(dumpFile, 0); if ((fd < 0) || (fstat(fd, &status) < 0)) { close(fd); tst = ADMVOSDUMPFILEOPENFAIL; goto fail_vos_VolumeRestore; } else { close(fd); } if (!VLDB_GetEntryByName(c_handle, volumeName, &entry, &tst)) { restoreflags = RV_FULLRST; } else if (Lp_GetRwIndex(c_handle, &entry, 0) == -1) { restoreflags = RV_FULLRST; if (volid == 0) { volid = entry.volumeId[RWVOL]; } else if ((entry.volumeId[RWVOL] != 0) && (entry.volumeId[RWVOL] != volid)) { volid = entry.volumeId[RWVOL]; } } else { if (volid == 0) { volid = entry.volumeId[RWVOL]; } else if ((entry.volumeId[RWVOL] != 0) && (entry.volumeId[RWVOL] != volid)) { volid = entry.volumeId[RWVOL]; } /* * If the vldb says the same volume exists somewhere else * the caller must specify a full restore, not an incremental */ if (dumpType == VOS_RESTORE_FULL) { restoreflags = RV_FULLRST; } else { /* * Check to see if the volume exists where the caller said */ if (!GetVolumeInfo (c_handle, volid, &Oentry, &Oserver, &Opart, &Otype, &tst)) { goto fail_vos_VolumeRestore; } if (!VLDB_IsSameAddrs(c_handle, Oserver, server, &equal, &tst)) { goto fail_vos_VolumeRestore; } if (!equal) { tst = ADMVOSRESTOREVOLEXIST; goto fail_vos_VolumeRestore; } } } rc = UV_RestoreVolume(c_handle, server, partition, volid, volumeName, restoreflags, dumpFile, &tst); fail_vos_VolumeRestore: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeOnline - bring a volume online. * * PARAMETERS * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be brought online. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeOnline(const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, unsigned int sleepTime, vos_volumeOnlineType_t volumeStatus, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; int up = ITOffline; /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeOnline; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeOnline; } if (volumeStatus == VOS_ONLINE_BUSY) { up = ITBusy; } rc = UV_SetVolume(f_server->serv, partition, volumeId, up, 0, sleepTime, &tst); fail_vos_VolumeOnline: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeOffline - take a volume offline. * * PARAMETERS * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be taken offline. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeOffline(const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeOffline; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeOffline; } rc = UV_SetVolume(f_server->serv, partition, volumeId, ITOffline, VTOutOfService, 0, &tst); fail_vos_VolumeOffline: if (st != NULL) { *st = tst; } return rc; } /* * copyvolintXInfo - copy a struct volintXInfo to a vos_volumeEntry_p. * * PARAMETERS * * IN source - the volintXInfo structure to copy. * * OUT dest - the vos_volumeEntry_t to fill * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ static int copyvolintXInfo(struct volintXInfo *source, vos_volumeEntry_p dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; int i; /* * If the volume is not marked OK, all the other fields are invalid * We take the extra step of blanking out dest here to prevent the * user from seeing stale data from a previous call */ memset(dest, 0, sizeof(dest)); switch (source->status) { case VOK: dest->status = VOS_OK; break; case VSALVAGE: dest->status = VOS_SALVAGE; break; case VNOVNODE: dest->status = VOS_NO_VNODE; break; case VNOVOL: dest->status = VOS_NO_VOL; break; case VVOLEXISTS: dest->status = VOS_VOL_EXISTS; break; case VNOSERVICE: dest->status = VOS_NO_SERVICE; break; case VOFFLINE: dest->status = VOS_OFFLINE; break; case VONLINE: dest->status = VOS_ONLINE; break; case VDISKFULL: dest->status = VOS_DISK_FULL; break; case VOVERQUOTA: dest->status = VOS_OVER_QUOTA; break; case VBUSY: dest->status = VOS_BUSY; break; case VMOVED: dest->status = VOS_MOVED; break; } /* * Check to see if the entry is marked ok before copying all the * fields */ if (dest->status == VOS_OK) { strcpy(dest->name, source->name); dest->id = source->volid; if (source->type == 0) { dest->type = VOS_READ_WRITE_VOLUME; } else if (source->type == 1) { dest->type = VOS_READ_ONLY_VOLUME; } else if (source->type == 2) { dest->type = VOS_BACKUP_VOLUME; } dest->backupId = source->backupID; dest->readWriteId = source->parentID; dest->readOnlyId = source->cloneID; dest->copyCreationDate = source->copyDate; dest->creationDate = source->creationDate; dest->lastAccessDate = source->accessDate; dest->lastUpdateDate = source->updateDate; dest->lastBackupDate = source->backupDate; dest->accessesSinceMidnight = source->dayUse; dest->fileCount = source->filecount; dest->maxQuota = source->maxquota; dest->currentSize = source->size; if (source->inUse == 1) { dest->volumeDisposition = VOS_ONLINE; } else { dest->volumeDisposition = VOS_OFFLINE; } for (i = 0; i < VOS_VOLUME_READ_WRITE_STATS_NUMBER; i++) { dest->readStats[i] = source->stat_reads[i]; dest->writeStats[i] = source->stat_writes[i]; } for (i = 0; i < VOS_VOLUME_TIME_STATS_NUMBER; i++) { dest->fileAuthorWriteSameNetwork[i] = source->stat_fileSameAuthor[i]; dest->fileAuthorWriteDifferentNetwork[i] = source->stat_fileDiffAuthor[i]; dest->dirAuthorWriteSameNetwork[i] = source->stat_dirSameAuthor[i]; dest->dirAuthorWriteDifferentNetwork[i] = source->stat_dirDiffAuthor[i]; } } rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeGet - get information about a particular volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be retrieved. * * OUT volumeP - upon successful completion, contains the information about the * specified volume. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeGet(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, vos_volumeEntry_p volumeP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; struct volintXInfo *info = NULL; /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeGet; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeGet; } if (volumeP == NULL) { tst = ADMVOSVOLUMEPNULL; goto fail_vos_VolumeGet; } /* * Retrieve the information for the volume */ if (!UV_XListOneVolume(f_server->serv, partition, volumeId, &info, &tst)) { goto fail_vos_VolumeGet; } /* * Copy the volume info to our structure */ if (!copyvolintXInfo(info, volumeP, &tst)) { goto fail_vos_VolumeGet; } rc = 1; fail_vos_VolumeGet: if (info != NULL) { free(info); } if (st != NULL) { *st = tst; } return rc; } /* * The iterator functions and data for the volume retrieval functions. */ typedef struct volume_get { struct volintXInfo *vollist; afs_int32 total; /* total number of volumes at this partition */ afs_int32 index; /* index to the current volume */ vos_volumeEntry_t entry[CACHED_ITEMS]; /* the cache of entries */ } volume_get_t, *volume_get_p; static int GetVolumeRPC(void *rpc_specific, int slot, int *last_item, int *last_item_contains_data, afs_status_p st) { int rc = 0; afs_status_t tst = 0; volume_get_p entry = (volume_get_p) rpc_specific; /* * Copy the next entry into the cache */ if (!copyvolintXInfo (&entry->vollist[entry->index], &entry->entry[slot], &tst)) { goto fail_GetVolumeRPC; } entry->index++; /* * See if we've processed all the entries */ if (entry->index == entry->total) { *last_item = 1; *last_item_contains_data = 1; } rc = 1; fail_GetVolumeRPC: if (st != NULL) { *st = tst; } return rc; } static int GetVolumeFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st) { int rc = 0; afs_status_t tst = 0; volume_get_p entry = (volume_get_p) rpc_specific; memcpy(dest, (const void *)&entry->entry[slot], sizeof(vos_volumeEntry_t)); rc = 1; if (st != NULL) { *st = tst; } return rc; } static int DestroyVolume(void *rpc_specific, afs_status_p st) { int rc = 0; afs_status_t tst = 0; volume_get_p entry = (volume_get_p) rpc_specific; if (entry->vollist != NULL) { free(entry->vollist); } rc = 1; if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeGetBegin - begin to iterator over the list of volumes at a server. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volumes exist. * * IN serverHandle - a handle to the server where the volumes exist. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition whose volumes should be listed. Can be null. * * OUT iterationIdP - upon successful completion, contains an iterator that * can be passed to vos_VolumeGetBegin. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeGetBegin(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, void **iterationIdP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t)); volume_get_p entry = (volume_get_p) calloc(1, sizeof(volume_get_t)); /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeGetBegin; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeGetBegin; } if ((iter == NULL) || (entry == NULL)) { tst = ADMNOMEM; goto fail_vos_VolumeGetBegin; } /* * Get a list of all the volumes contained in the partition at the * server */ if (!UV_XListVolumes (f_server->serv, partition, 1, &entry->vollist, &entry->total, &tst)) { goto fail_vos_VolumeGetBegin; } if (entry->total == 0) { if (!IteratorInit(iter, (void *)entry, NULL, NULL, NULL, NULL, &tst)) { goto fail_vos_VolumeGetBegin; } iter->done_iterating = 1; iter->st = ADMITERATORDONE; } else { if (!IteratorInit (iter, (void *)entry, GetVolumeRPC, GetVolumeFromCache, NULL, DestroyVolume, &tst)) { goto fail_vos_VolumeGetBegin; } } *iterationIdP = (void *)iter; rc = 1; fail_vos_VolumeGetBegin: if (rc == 0) { if (iter != NULL) { free(iter); } if (entry != NULL) { free(entry); } } if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeGetNext - get information about the next volume. * * PARAMETERS * * IN iterationId - an iterator previously returned by * vos_VolumeGetBegin * * OUT volumeP - a pointer to a vos_volumeEntry_t * that upon successful completion contains information about the * next volume. * * LOCKS * * The iterator is locked while the next item is retrieved. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeGetNext(const void *iterationId, vos_volumeEntry_p volumeP, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_VolumeGetNext; } if (volumeP == NULL) { tst = ADMVOSVOLUMEPNULL; goto fail_vos_VolumeGetNext; } rc = IteratorNext(iter, (void *)volumeP, &tst); fail_vos_VolumeGetNext: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeGetDone - finish using a volume iterator. * * PARAMETERS * * IN iterationId - an iterator previously returned by vos_VolumeGetBegin * * LOCKS * * The iterator is locked and then destroyed. * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeGetDone(const void *iterationId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId; /* * Validate arguments */ if (iter == NULL) { tst = ADMITERATORNULL; goto fail_vos_VolumeGetDone; } rc = IteratorDone(iter, &tst); fail_vos_VolumeGetDone: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeMove - move a volume from one server to another. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the volume id of the volume to be moved. * * IN fromServer - a previously opened serverHandle that corresponds * to the server where the volume currently resides. * * IN fromPartition - the partition where the volume currently resides. * * IN toServer - a previously opened serverHandle that corresponds * to the server where the volume will be moved. * * IN toPartition - the partition where the volume will be moved. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeMove(const void *cellHandle, vos_MessageCallBack_t callBack, unsigned int volumeId, const void *fromServer, unsigned int fromPartition, const void *toServer, unsigned int toPartition, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p from_server = (file_server_p) fromServer; file_server_p to_server = (file_server_p) toServer; afs_int32 from_server_addr = ntohl(rx_HostOf(rx_PeerOf(from_server->serv))); afs_int32 to_server_addr = ntohl(rx_HostOf(rx_PeerOf(to_server->serv))); afs_int32 from_partition = fromPartition; afs_int32 to_partition = toPartition; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeMove; } if (!IsValidServerHandle(from_server, &tst)) { goto fail_vos_VolumeMove; } if (!IsValidServerHandle(to_server, &tst)) { goto fail_vos_VolumeMove; } if (fromPartition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeMove; } if (toPartition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeMove; } /* * Move the volume */ rc = UV_MoveVolume(c_handle, volumeId, from_server_addr, from_partition, to_server_addr, to_partition, &tst); fail_vos_VolumeMove: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeRelease - release a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN volumeId - the volume to be released. * * IN force - force a complete release. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeRelease(const void *cellHandle, vos_MessageCallBack_t callBack, unsigned int volumeId, vos_force_t force, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; afs_int32 server, part, forc = 0, voltype, volume; struct nvldbentry entry; /* * Validate arguments */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeRelease; } if (!GetVolumeInfo (c_handle, volumeId, &entry, &server, &part, &voltype, &tst)) { goto fail_vos_VolumeRelease; } if (force == VOS_FORCE) { forc = 1; } volume = volumeId; rc = UV_ReleaseVolume(c_handle, volume, server, part, forc, &tst); fail_vos_VolumeRelease: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeZap - forcibly delete a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the vldb entry to be deleted. * * IN force - force the deletion of bad volumes. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeZap(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, vos_force_t force, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; /* * Verify that the cellHandle is capable of making vos rpc's */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeZap; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeZap; } if (force == VOS_FORCE) { rc = UV_NukeVolume(c_handle, f_server->serv, partition, volumeId, &tst); } else { rc = UV_VolumeZap(c_handle, f_server->serv, partition, volumeId, &tst); } fail_vos_VolumeZap: if (st != NULL) { *st = tst; } return rc; } /* * vos_PartitionNameToId - translate a string representing a partition * to a number. * * PARAMETERS * * IN partitionName - a string representing a partition. Must be of * the form /vicep.. * * OUT partitionId - a number containing the partition id upon successful * completion. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_PartitionNameToId(const char *partitionName, unsigned int *partitionId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; size_t partition_name_len; int i; /* * Validate arguments */ if (partitionName == NULL) { tst = ADMVOSPARTITIONNAMENULL; goto fail_vos_PartitionNameToId; } if (partitionId == NULL) { tst = ADMVOSPARTITIONIDNULL; goto fail_vos_PartitionNameToId; } /* * Check that string begins with /vicep */ if (strncmp(partitionName, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) { tst = ADMVOSPARTITIONNAMEINVALID; goto fail_vos_PartitionNameToId; } /* * Check that the string is either one or two characters * longer than VICE_PREFIX_SIZE */ partition_name_len = strlen(partitionName); if (partition_name_len == VICE_PREFIX_SIZE) { tst = ADMVOSPARTITIONNAMETOOSHORT; goto fail_vos_PartitionNameToId; } if (partition_name_len > (VICE_PREFIX_SIZE + 2)) { tst = ADMVOSPARTITIONNAMETOOLONG; goto fail_vos_PartitionNameToId; } /* * Check that all characters past the prefix are lower case */ for (i = VICE_PREFIX_SIZE; i < partition_name_len; i++) { if (!islower(partitionName[i])) { tst = ADMVOSPARTITIONNAMENOTLOWER; goto fail_vos_PartitionNameToId; } } /* * Convert the name to a number */ if (partitionName[VICE_PREFIX_SIZE + 1] == 0) { *partitionId = partitionName[VICE_PREFIX_SIZE] - 'a'; } else { *partitionId = (partitionName[VICE_PREFIX_SIZE] - 'a') * 26 + (partitionName[VICE_PREFIX_SIZE + 1] - 'a') + 26; } if (*partitionId > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_PartitionNameToId; } rc = 1; fail_vos_PartitionNameToId: if (st != NULL) { *st = tst; } return rc; } /* * vos_PartitionIdToName - translate a number representing a partition * to a character string. * * PARAMETERS * * IN partitionId - an integer representing the partition. * * OUT partitionName - a string containing the converted partition ID * upon successful completion. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_PartitionIdToName(unsigned int partitionId, char *partitionName, afs_status_p st) { int rc = 0; afs_status_t tst = 0; if (partitionId > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_PartitionIdToName; } if (partitionName == NULL) { tst = ADMVOSPARTITIONNAMENULL; goto fail_vos_PartitionIdToName; } if (partitionId < 26) { strcpy(partitionName, VICE_PARTITION_PREFIX); partitionName[6] = partitionId + 'a'; partitionName[7] = '\0'; } else { strcpy(partitionName, VICE_PARTITION_PREFIX); partitionId -= 26; partitionName[6] = 'a' + (partitionId / 26); partitionName[7] = 'a' + (partitionId % 26); partitionName[8] = '\0'; } rc = 1; fail_vos_PartitionIdToName: if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeQuotaChange - change the quota of a volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be modified. * * IN volumeQuota - the new volume quota. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeQuotaChange(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, unsigned int volumeQuota, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; int ttid = 0; int rcode = 0; struct volintInfo tstatus; int active_trans = 0; /* * Verify that the cellHandle is capable of making vos rpc's */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_VolumeQuotaChange; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeQuotaChange; } memset((void *)&tstatus, 0, sizeof(tstatus)); tstatus.dayUse = -1; tstatus.spare2 = -1; tstatus.maxquota = volumeQuota; tst = AFSVolTransCreate(f_server->serv, volumeId, partition, ITBusy, &ttid); if (tst) { goto fail_vos_VolumeQuotaChange; } active_trans = 1; tst = AFSVolSetInfo(f_server->serv, ttid, &tstatus); if (tst) { goto fail_vos_VolumeQuotaChange; } rc = 1; fail_vos_VolumeQuotaChange: if (active_trans) { afs_status_t tst2 = 0; tst2 = AFSVolEndTrans(f_server->serv, ttid, &rcode); if (tst2) { if (tst == 0) { tst = tst2; rc = 0; } } if (rcode) { if (tst == 0) { tst = rcode; rc = 0; } } } if (st != NULL) { *st = tst; } return rc; } /* * vos_VolumeGet2 - get information about a particular volume. * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN callBack - a call back function pointer that may be called to report * status information. Can be null. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be retrieved. * * OUT pinfo - upon successful completion, contains the information about the * specified volume. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_VolumeGet2(const void *cellHandle, const void *serverHandle, vos_MessageCallBack_t callBack, unsigned int partition, unsigned int volumeId, volintInfo* pinfo, afs_status_p st) { int rc = 0; afs_status_t tst = 0; file_server_p f_server = (file_server_p) serverHandle; volintInfo *pinfo_=0; /* * Validate arguments */ if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_VolumeGet2; } if (partition > VOLMAXPARTS) { tst = ADMVOSPARTITIONIDTOOLARGE; goto fail_vos_VolumeGet2; } if (pinfo == NULL) { tst = ADMVOSVOLUMEPNULL; goto fail_vos_VolumeGet2; } /* * Retrieve the information for the volume */ if (!UV_ListOneVolume(f_server->serv, partition, volumeId, &pinfo_,&tst)) { goto fail_vos_VolumeGet2; } rc = 1; fail_vos_VolumeGet2: if (pinfo_ != NULL) { memcpy(pinfo,pinfo_,sizeof(volintInfo)); free(pinfo_); } if (st != NULL) { *st = tst; } return rc; } /* * vos_ClearVolUpdateCounter - reset volUpdateCounter of a volume to zero * * PARAMETERS * * IN cellHandle - a previously opened cellHandle that corresponds * to the cell where the volume exists. * * IN serverHandle - a previously opened serverHandle that corresponds * to the server where the volume exists. * * IN partition - the partition where the volume exists. * * IN volumeId - the volume id of the volume to be retrieved. * * LOCKS * * No locks are obtained or released by this function * * RETURN CODES * * Returns != 0 upon successful completion. */ int ADMINAPI vos_ClearVolUpdateCounter(const void *cellHandle, const void *serverHandle, unsigned int partition, unsigned int volumeId, afs_status_p st) { int rc = 0; afs_status_t tst = 0; afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle; file_server_p f_server = (file_server_p) serverHandle; int ttid = 0; int rcode = 0; struct volintInfo tstatus; int active_trans = 0; /* * Verify that the cellHandle is capable of making vos rpc's */ if (!IsValidCellHandle(c_handle, &tst)) { goto fail_vos_ClearVolUpdateCounter; } if (!IsValidServerHandle(f_server, &tst)) { goto fail_vos_ClearVolUpdateCounter; } memset((void *)&tstatus, 0, sizeof(tstatus)); tstatus.maxquota = -1; tstatus.dayUse = -1; tstatus.creationDate = -1; tstatus.updateDate = -1; tstatus.flags = -1; tstatus.spare0 = -1; tstatus.spare1 = -1; tstatus.spare2 = 0; tstatus.spare3 = -1; tst = AFSVolTransCreate(f_server->serv, volumeId, partition, ITBusy, &ttid); if (tst) { goto fail_vos_ClearVolUpdateCounter; } active_trans = 1; tst = AFSVolSetInfo(f_server->serv, ttid, &tstatus); if (tst) { goto fail_vos_ClearVolUpdateCounter; } rc = 1; fail_vos_ClearVolUpdateCounter: if (active_trans) { afs_status_t tst2 = 0; tst2 = AFSVolEndTrans(f_server->serv, ttid, &rcode); if (tst2) { if (tst == 0) { tst = tst2; rc = 0; } } if (rcode) { if (tst == 0) { tst = rcode; rc = 0; } } } if (st != NULL) { *st = tst; } return rc; }