static void VInitPartition_r(char *path, char *devname, Device dev) { struct DiskPartition64 *dp, *op; dp = malloc(sizeof(struct DiskPartition64)); /* Add it to the end, to preserve order when we print statistics */ for (op = DiskPartitionList; op; op = op->next) { if (!op->next) break; } if (op) op->next = dp; else DiskPartitionList = dp; dp->next = 0; dp->name = strdup(path); dp->index = volutil_GetPartitionID(path); #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV) /* Create a lockfile for the partition, of the form /vicepa/Lock/vicepa */ dp->devName = malloc(2 * strlen(path) + 6); strcpy(dp->devName, path); strcat(dp->devName, OS_DIRSEP); strcat(dp->devName, "Lock"); mkdir(dp->devName, 0700); strcat(dp->devName, path); close(afs_open(dp->devName, O_RDWR | O_CREAT, 0600)); dp->device = dp->index; #else dp->devName = strdup(devname); dp->device = dev; #endif dp->lock_fd = INVALID_FD; dp->flags = 0; dp->f_files = 1; /* just a default value */ #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV) if (programType == fileServer) (void)namei_ViceREADME(VPartitionPath(dp)); #endif VSetPartitionDiskUsage_r(dp); #ifdef AFS_DEMAND_ATTACH_FS AddPartitionToTable_r(dp); queue_Init(&dp->vol_list.head); CV_INIT(&dp->vol_list.cv, "vol list", CV_DEFAULT, 0); dp->vol_list.len = 0; dp->vol_list.busy = 0; { char lockpath[MAXPATHLEN+1]; snprintf(lockpath, MAXPATHLEN, "%s/" AFS_PARTLOCK_FILE, dp->name); lockpath[MAXPATHLEN] = '\0'; VLockFileInit(&dp->headerLockFile, lockpath); snprintf(lockpath, MAXPATHLEN, "%s/" AFS_VOLUMELOCK_FILE, dp->name); lockpath[MAXPATHLEN] = '\0'; VLockFileInit(&dp->volLockFile, lockpath); } VDiskLockInit(&dp->headerLock, &dp->headerLockFile, 1); #endif /* AFS_DEMAND_ATTACH_FS */ }
static struct DiskPartition64 * VLookupPartition_r(char * path) { afs_int32 id = volutil_GetPartitionID(path); if (id < 0 || id > VOLMAXPARTS) return NULL; return DiskPartitionTable[id]; }
IHandle_t * GetLinkHandle(char *part, int volid) { int dev; Inode ino; IHandle_t *lh; dev = volutil_GetPartitionID(part); ino = namei_MakeSpecIno(volid, VI_LINKTABLE); IH_INIT(lh, dev, volid, ino); return lh; }
afs_uint32 xfon_voldump(XFILE * X, int flag, char *name) { struct hostent *he; struct rx_securityClass *class; struct rx_connection *conn; struct ktc_principal sname; struct ktc_token token; struct afsconf_dir *confdir; afs_uint32 code, server_addr = 0; afs_int32 volid, date, partid = 0; int isnum, index; char *x, *y; /* Parse out the optional date and server location */ if ((code = rx_Init(0))) return code; if (!(name = strdup(name))) return ENOMEM; if ((x = strrchr(name, ','))) { *x++ = 0; date = atoi(x); } else { date = 0; } if ((x = strrchr(name, '@'))) { int a, b, c, d; *x++ = 0; if (!(y = strchr(x, '/'))) { free(name); return VL_BADPARTITION; } *y++ = 0; if (sscanf(x, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && a >= 0 && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0 && d <= 255) { server_addr = (a << 24) | (b << 16) | (c << 8) | d; server_addr = htonl(server_addr); } else { he = gethostbyname(x); if (!he) { free(name); return VL_BADSERVER; } memcpy(&server_addr, he->h_addr, sizeof(server_addr)); } partid = volutil_GetPartitionID(y); if (partid < 0) { free(name); return VL_BADPARTITION; } } /* Get tokens and set up a security object */ confdir = afsconf_Open(AFSCONF_CLIENTNAME); if (!confdir) { free(name); return AFSCONF_NODB; } if ((code = afsconf_GetLocalCell(confdir, sname.cell, MAXKTCNAMELEN))) { free(name); return code; } afsconf_Close(confdir); strcpy(sname.name, "afs"); sname.instance[0] = 0; code = ktc_GetToken(&sname, &token, sizeof(token), 0); if (code) { class = rxnull_NewClientSecurityObject(); index = 0; } else {
/* function called with partition name and volid ID, and which removes all * inodes marked with the specified volume ID. If the volume is a read-only * clone, we'll only remove the header inodes, since they're the only inodes * marked with that volume ID. If you want to reclaim all the data, you should * nuke the read-write volume ID. * * Note also that nuking a read-write volume effectively nukes all RO volumes * cloned from that RW volume ID, too, since everything except for their * indices will be gone. */ int nuke(char *aname, afs_int32 avolid) { /* first process the partition containing this junk */ struct afs_stat_st tstat; struct ilist *ti, *ni, *li=NULL; afs_int32 code; int i, forceSal; char wpath[100]; char *lastDevComp; struct DiskPartition64 *dp; #ifdef AFS_NAMEI_ENV char *path; namei_t ufs_name; #endif /* AFS_NAMEI_ENV */ #ifndef AFS_NAMEI_ENV char devName[64]; #endif /* !AFS_NAMEI_ENV */ IHandle_t *fileH; struct ilist *allInodes = 0; if (avolid == 0) return EINVAL; code = afs_stat(aname, &tstat); if (code || (dp = VGetPartition(aname, 0)) == NULL) { printf("volnuke: partition %s does not exist.\n", aname); if (!code) { code = EINVAL; } return code; } /* get the device name for the partition */ #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV) lastDevComp = aname; #else #ifdef AFS_NT40_ENV lastDevComp = &aname[strlen(aname) - 1]; *lastDevComp = toupper(*lastDevComp); #else { char *tfile = vol_DevName(tstat.st_dev, wpath); if (!tfile) { printf("volnuke: can't find %s's device.\n", aname); return 1; } strcpy(devName, tfile); /* save this from the static buffer */ } /* aim lastDevComp at the 'foo' of '/dev/foo' */ lastDevComp = strrchr(devName, OS_DIRSEPC); /* either points at slash, or there is no slash; adjust appropriately */ if (lastDevComp) lastDevComp++; else lastDevComp = devName; #endif /* AFS_NT40_ENV */ #endif /* AFS_NAMEI_ENV && !AFS_NT40_ENV */ ObtainWriteLock(&localLock); /* OK, we have the mounted on place, aname, the device name (in devName). * all we need to do to call ListViceInodes is find the inodes for the * volume we're nuking. */ code = ListViceInodes(lastDevComp, aname, INVALID_FD, NukeProc, avolid, &forceSal, 0, wpath, &allInodes); if (code == 0) { /* actually do the idecs now */ for (ti = allInodes; ti; ti = ti->next) { for (i = 0; i < ti->freePtr; i++) { #ifndef AFS_PTHREAD_ENV IOMGR_Poll(); /* keep RPC running */ #endif /* !AFS_PTHREAD_ENV */ /* idec this inode into oblivion */ #ifdef AFS_NAMEI_ENV #ifdef AFS_NT40_ENV IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid, ti->inode[i]); #else IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid, ti->inode[i]); #endif /* AFS_NT40_ENV */ namei_HandleToName(&ufs_name, fileH); path = ufs_name.n_path; IH_RELEASE(fileH); if (OS_UNLINK(path) < 0) { Log("Nuke: Failed to remove %s\n", path); } #else /* AFS_NAMEI_ENV */ IH_INIT(fileH, (int)tstat.st_dev, avolid, ti->inode[i]); { int j; for (j = 0; j < ti->count[i]; j++) { code = IH_DEC(fileH, ti->inode[i], avolid); } } IH_RELEASE(fileH); #endif /* AFS_NAMEI_ENV */ } ni = ti->next; if (li) free(li); li = ti; } if (li) free(li); code = 0; /* we really don't care about it except for debugging */ allInodes = NULL; /* at this point, we should try to remove the volume header file itself. * the volume header file is the file named VNNNNN.vol in the UFS file * system, and is a normal file. As such, it is not stamped with the * volume's ID in its inode, and has to be removed explicitly. */ code = VDestroyVolumeDiskHeader(dp, avolid, 0); } else { /* just free things */ for (ti = allInodes; ti; ti = ni) { ni = ti->next; if (li) free(li); li = ti; } if (li) free(li); allInodes = NULL; } ReleaseWriteLock(&localLock); return code; }
/* VAttachPartitions() finds the vice partitions on this server. Calls * VCheckPartition() to do some basic checks on the partition. If the partition * is a valid vice partition, VCheckPartition will add it to the DiskPartition * list. * Returns the number of errors returned by VCheckPartition. An error in * VCheckPartition means that partition is a valid vice partition but the * fileserver should not start because of the error found on that partition. * * AFS_NAMEI_ENV * No specific user space file system checks, since we don't know what * is being used for vice partitions. * * Use partition name as devname. */ static int VCheckPartition(char *part, char *devname, int logging) { struct afs_stat_st status; #if !defined(AFS_LINUX20_ENV) && !defined(AFS_NT40_ENV) char AFSIDatPath[MAXPATHLEN]; #endif /* Only keep track of "/vicepx" partitions since it can get hairy * when NFS mounts are involved.. */ if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) { return 0; } if (volutil_GetPartitionID(part) == -1) { Log("Warning: %s is a bad partition name; ignored.\n", part); return 0; } if (afs_stat(part, &status) < 0) { Log("VInitVnodes: Couldn't find file system %s; ignored\n", part); return 0; } if (logging) { Log("This program is compiled without AFS_NAMEI_ENV, and " "partition %s is mounted with the 'logging' option. " "Using the inode fileserver backend with 'logging' UFS " "partitions causes volume corruption, so please either " "mount the partition without logging, or use the namei " "fileserver backend. Aborting...\n", part); return -1; } #ifndef AFS_AIX32_ENV if (programType == fileServer) { char salvpath[MAXPATHLEN]; strcpy(salvpath, part); strcat(salvpath, "/FORCESALVAGE"); if (afs_stat(salvpath, &status) == 0) { Log("VInitVnodes: Found %s; aborting\n", salvpath); return -1; } } #endif #if !defined(AFS_LINUX20_ENV) && !defined(AFS_NT40_ENV) strcpy(AFSIDatPath, part); strcat(AFSIDatPath, "/AFSIDat"); #ifdef AFS_NAMEI_ENV if (afs_stat(AFSIDatPath, &status) < 0) { DIR *dirp; struct dirent *dp; dirp = opendir(part); opr_Assert(dirp); while ((dp = readdir(dirp))) { if (dp->d_name[0] == 'V') { Log("This program is compiled with AFS_NAMEI_ENV, but partition %s seems to contain volumes which don't use the namei-interface; aborting\n", part); closedir(dirp); return -1; } } closedir(dirp); } #else /* AFS_NAMEI_ENV */ if (afs_stat(AFSIDatPath, &status) == 0) { Log("This program is compiled without AFS_NAMEI_ENV, but partition %s seems to contain volumes which use the namei-interface; aborting\n", part); return -1; } #ifdef AFS_SGI_XFS_IOPS_ENV if (VerifyXFSInodeSize(part, status.st_fstype) < 0) return -1; #endif #endif /* AFS_NAMEI_ENV */ #endif /* !AFS_LINUX20_ENV && !AFS_NT40_ENV */ VInitPartition(part, devname, status.st_dev); return 0; }