Beispiel #1
0
/* VIsAlwaysAttach() checks whether a /vicepX directory should always be
 * attached (return value 1), or only attached when it is a separately
 * mounted partition (return value 0).  For non-NAMEI environments, it
 * always returns 0.
 *
 * *awouldattach will be set to 1 if the given path at least looks like a vice
 * partition (that is, if we return 0, the only thing preventing this partition
 * from being attached is the existence of the AlwaysAttach file), or to 0
 * otherwise. *awouldattach is set regardless of whether or not the partition
 * should always be attached or not.
 */
static int
VIsAlwaysAttach(char *part, int *awouldattach)
{
#ifdef AFS_NAMEI_ENV
    struct afs_stat_st st;
    char checkfile[256];
    int ret;
#endif /* AFS_NAMEI_ENV */

    if (awouldattach) {
	*awouldattach = 0;
    }

#ifdef AFS_NAMEI_ENV
    if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE))
	return 0;

    if (awouldattach) {
	*awouldattach = 1;
    }

    strncpy(checkfile, part, 100);
    strcat(checkfile, OS_DIRSEP);
    strcat(checkfile, VICE_ALWAYSATTACH_FILE);

    ret = afs_stat(checkfile, &st);
    return (ret < 0) ? 0 : 1;
#else /* AFS_NAMEI_ENV */
    return 0;
#endif /* AFS_NAMEI_ENV */
}
static int
fs_stateCreateDump(struct fs_dump_state * state)
{
    int fd, ret = 0;
    char savedump[MAXPATHLEN];
    struct afs_stat status;

    afs_snprintf(savedump, sizeof(savedump), "%s.old", state->fn);

    if (afs_stat(state->fn, &status) == 0) {
	renamefile(state->fn, savedump);
    }

    if (((fd = afs_open(state->fn,
			O_RDWR | O_CREAT | O_TRUNC,
			S_IRUSR | S_IWUSR)) == -1) ||
	(afs_fstat(fd, &status) == -1)) {
	ViceLog(0, ("fs_stateCreateDump: failed to create state dump file '%s'\n",
		    state->fn));
	ret = 1;
	goto done;
    }

    state->fd = fd;
    state->mode = FS_STATE_DUMP_MODE;
    memset(state->hdr, 0, sizeof(struct fs_state_header));
    fs_stateIncEOF(state, sizeof(struct fs_state_header));

#ifdef FS_STATE_USE_MMAP
    if (fs_stateSizeFile(state)) {
	ViceLog(0, ("fs_stateCreateDump: failed to resize state dump file '%s'\n",
		    state->fn));
	ret = 1;
	goto done;
    }

    if (fs_stateMapFile(state)) {
	ViceLog(0, ("fs_stateCreateDump: failed to memory map state dump file '%s'\n",
		    state->fn));
	ret = 1;
	goto done;
    }
#endif

    ret = fs_stateInvalidateDump(state);

 done:
    return ret;
}
Beispiel #3
0
/* VAttachPartitions2() looks for and attaches /vicepX partitions
 * where a special file (VICE_ALWAYSATTACH_FILE) exists.  This is
 * used to attach /vicepX directories which aren't on dedicated
 * partitions, in the NAMEI fileserver.
 */
static void
VAttachPartitions2(void)
{
#ifdef AFS_NAMEI_ENV
    DIR *dirp;
    struct dirent *de;
    char pname[32];
    int wouldattach;

    dirp = opendir(OS_DIRSEP);
    while ((de = readdir(dirp))) {
	strcpy(pname, OS_DIRSEP);
	strncat(pname, de->d_name, 20);
	pname[sizeof(pname) - 1] = '\0';

	/* Only keep track of "/vicepx" partitions since automounter
	 * may hose us */
	if (VIsAlwaysAttach(pname, &wouldattach)) {
	    VCheckPartition(pname, "", 0);
	} else {
	    struct afs_stat_st st;
	    if (wouldattach && VGetPartition(pname, 0) == NULL &&
	        afs_stat(pname, &st) == 0 && S_ISDIR(st.st_mode)) {

		/* This is a /vicep* dir, and it has not been attached as a
		 * partition. This probably means that this is a /vicep* dir
		 * that is not a separate partition, so just give a notice so
		 * admins are not confused as to why their /vicep* dirs are not
		 * being attached.
		 *
		 * It is possible that the dir _is_ a separate partition and we
		 * failed to attach it earlier, making this message a bit
		 * confusing. But that should be rare, and an error message
		 * about the failure will already be logged right before this,
		 * so it should be clear enough. */

		Log("VAttachPartitions: not attaching %s; either it is not a "
		    "separate partition, or it failed to attach (create the "
		    "file %s/" VICE_ALWAYSATTACH_FILE " to force attachment)\n",
		    pname, pname);
	    }
	}
    }
    closedir(dirp);
#endif /* AFS_NAMEI_ENV */
}
Beispiel #4
0
/* VIsNeverAttach() checks whether a /vicepX directory should never be
 * attached (return value 1), or follow the normal mounting logic. The
 * Always Attach flag may override the NeverAttach flag.
 */
static int
VIsNeverAttach(char *part)
{
    struct afs_stat_st st;
    char checkfile[256];
    int ret;

    if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE))
	return 0;

    strncpy(checkfile, part, 100);
    strcat(checkfile, OS_DIRSEP);
    strcat(checkfile, VICE_NEVERATTACH_FILE);

    ret = afs_stat(checkfile, &st);
    return (ret < 0) ? 0 : 1;
}
Beispiel #5
0
/* VIsAlwaysAttach() checks whether a /vicepX directory should always be
 * attached (return value 1), or only attached when it is a separately
 * mounted partition (return value 0).  For non-NAMEI environments, it
 * always returns 0.
 */
static int
VIsAlwaysAttach(char *part)
{
#ifdef AFS_NAMEI_ENV
    struct afs_stat st;
    char checkfile[256];
    int ret;

    if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE))
	return 0;

    strncpy(checkfile, part, 100);
    strcat(checkfile, "/");
    strcat(checkfile, VICE_ALWAYSATTACH_FILE);

    ret = afs_stat(checkfile, &st);
    return (ret < 0) ? 0 : 1;
#else /* AFS_NAMEI_ENV */
    return 0;
#endif /* AFS_NAMEI_ENV */
}
Beispiel #6
0
int
VAttachPartitions(void)
{
    struct DiskPartition64 *partP, *prevP, *nextP;
    struct vpt_iter iter;
    struct vptab entry;

    if (vpt_Start(&iter) < 0) {
	Log("No partitions to attach.\n");
	return 0;
    }

    while (0 == vpt_NextEntry(&iter, &entry)) {
	if (!VValidVPTEntry(&entry)) {
	    continue;
	}

	/* This test for duplicates relies on the fact that the method
	 * of storing the partition names in the NT registry means the same
	 * partition name will never appear twice in the list.
	 */
	for (partP = DiskPartitionList; partP; partP = partP->next) {
	    if (*partP->devName == *entry.vp_dev) {
		Log("Same drive (%s) used for both partition %s and partition %s, ignoring both.\n", entry.vp_dev, partP->name, entry.vp_name);
		partP->flags = PART_DUPLICATE;
		break;		/* Only one entry will ever be in this list. */
	    }
	}
	if (partP)
	    continue;		/* found a duplicate */

	if (VCheckPartition(entry.vp_dev) < 0)
	    continue;
	/* This test allows for manually inserting the FORCESALVAGE flag
	 * and thereby invoking the salvager. scandisk obviously won't be
	 * doing this for us.
	 */
	if (programType == fileServer) {
	    struct afs_stat status;
	    char salvpath[MAXPATHLEN];
	    strcpy(salvpath, entry.vp_dev);
	    strcat(salvpath, "\\FORCESALVAGE");
	    if (afs_stat(salvpath, &status) == 0) {
		Log("VAttachPartitions: Found %s; aborting\n", salvpath);
		exit(1);
	    }
	}
	VInitPartition(entry.vp_name, entry.vp_dev, *entry.vp_dev - 'A');
    }
    vpt_Finish(&iter);

    /* Run through partition list and clear out the dupes. */
    prevP = nextP = NULL;
    for (partP = DiskPartitionList; partP; partP = nextP) {
	nextP = partP->next;
	if (partP->flags == PART_DUPLICATE) {
	    if (prevP)
		prevP->next = partP->next;
	    else
		DiskPartitionList = partP->next;
	    free(partP);
	} else
	    prevP = partP;
    }

    return 0;
}
Beispiel #7
0
/* 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.
 */
int
VCheckPartition(char *part, char *devname)
{
    struct afs_stat 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 (afs_stat(part, &status) < 0) {
	Log("VInitVnodes: Couldn't find file system %s; ignored\n", part);
	return 0;
    }
#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);
	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 */

#if defined(AFS_DUX40_ENV) && !defined(AFS_NAMEI_ENV)
    if (status.st_ino != ROOTINO) {
	Log("%s is not a mounted file system; ignored.\n", part);
	return 0;
    }
#endif

    VInitPartition(part, devname, status.st_dev);

    return 0;
}
Beispiel #8
0
/* 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;
}
Beispiel #9
0
/* 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;
}