Пример #1
0
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 */
}
Пример #2
0
static int
fs_stateLoadDump(struct fs_dump_state * state)
{
    afs_uint64 z;
    int fd, ret = 0;
    struct afs_stat status;
    afs_int32 now = FT_ApproxTime();

    ZeroInt64(z);

    if ((fd = afs_open(state->fn, O_RDWR)) == -1 ||
	(afs_fstat(fd, &status) == -1)) {
	ViceLog(0, ("fs_stateLoadDump: failed to load state dump file '%s'\n",
		    state->fn));
	ret = 1;
	goto done;
    }
    state->fd = fd;
    state->mode = FS_STATE_LOAD_MODE;
    state->file_len = status.st_size;

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

    if (fs_stateReadHeader(state, &z, state->hdr, sizeof(struct fs_state_header))) {
	ViceLog(0, ("fs_stateLoadDump: failed to read header from dump file '%s'\n",
		    state->fn));
	ret = 1;
	goto done;
    }

    /* check the validity of the header */
    if (fs_stateCheckHeader(state->hdr)) {
	ViceLog(1, ("fs_stateLoadDump: header failed validity checks; not restoring '%s'\n",
		    state->fn));
	ret = 1;
	goto done;
    }

    if ((state->hdr->timestamp + HOST_STATE_VALID_WINDOW) >= now) {
	state->flags.do_host_restore = 1;
    } else {
	ViceLog(0, ("fs_stateLoadDump: warning: dump is too old for host and callback restore; skipping those steps\n"));
    }

 done:
    return ret;
}
Пример #3
0
/*
 * open an AFS directory file
 */
static int afs_dir_open(struct inode *inode, struct file *file)
{
	_enter("{%lu}", inode->i_ino);

	BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
	BUILD_BUG_ON(sizeof(union afs_dirent) != 32);

	if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
		return -ENOENT;

	return afs_open(inode, file);
}
Пример #4
0
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;
}
Пример #5
0
void
HandleVolume(struct DiskPartition64 *dp, char *name, char *filename, int fromtime)
{
    struct VolumeHeader header;
    struct VolumeDiskHeader diskHeader;
    struct afs_stat status, stat;
    register int fd;
    Volume *vp;
    IHandle_t *ih;
    char headerName[1024];

    afs_int32 n;

    (void)afs_snprintf(headerName, sizeof headerName, "%s/%s",
		       VPartitionPath(dp), name);
    if ((fd = afs_open(headerName, O_RDONLY)) == -1
	|| afs_fstat(fd, &status) == -1) {
	fprintf(stderr, "Cannot read volume header %s\n", name);
	close(fd);
	exit(1);
    }
    n = read(fd, &diskHeader, sizeof(diskHeader));

    if (n != sizeof(diskHeader)
	|| diskHeader.stamp.magic != VOLUMEHEADERMAGIC) {
	fprintf(stderr, "Error reading volume header %s\n", name);
	exit(1);
    }
    if (diskHeader.stamp.version != VOLUMEHEADERVERSION) {
	fprintf(stderr,
		"Volume %s, version number is incorrect; volume needs salvage\n",
		name);
	exit(1);
    }
    DiskToVolumeHeader(&header, &diskHeader);

    close(fd);
    vp = AttachVolume(dp, name, &header);
    if (!vp) {
	fprintf(stderr, "Error attaching volume header %s\n", name);
	exit(1);
    }

    DoMyVolDump(vp, dp, filename, fromtime);
}
Пример #6
0
static int
openFile(char * path)
{
    int ret = 0;
    struct afs_stat status;

    dump_fd = afs_open(path, O_RDWR);
    if (dump_fd == -1) {
	fprintf(stderr, "dump file '%s' failed to open\n", path);
	ret = 1;
	goto done;
    }

    printf("opened dump file '%s'\n", path);

    if (afs_fstat(dump_fd, &status) == -1) {
	fprintf(stderr, "failed to stat file\n");
	ret = 1;
	goto done;
    }

    map_len = status.st_size;

    map = afs_mmap(NULL, map_len, PROT_READ, MAP_SHARED, dump_fd, 0);
    if (map == MAP_FAILED) {
	fprintf(stderr, "failed to mmap file\n");
	ret = 1;
	goto done;
    }

    printf("mapped %lu bytes at %"AFS_PTR_FMT"\n", (unsigned long)map_len, map);

 done:
    if (ret) {
	if (map) {
	    munmap(map, map_len);
	    map = NULL;
	}
	if (dump_fd != -1) {
	    close(dump_fd);
	    dump_fd = -1;
	}
    }
    return ret;
}
Пример #7
0
void
HandleVolume(struct DiskPartition64 *dp, char *name)
{
    struct VolumeHeader header;
    struct VolumeDiskHeader diskHeader;
    struct afs_stat status, stat;
    int fd;
    Volume *vp;
    IHandle_t *ih;
    char headerName[1024];

    if (online) {
	printf("volinfo: -online not supported\n");
	exit(1);
    } else {
	afs_int32 n;

	(void)afs_snprintf(headerName, sizeof headerName, "%s/%s",
			   VPartitionPath(dp), name);
	if ((fd = afs_open(headerName, O_RDONLY)) == -1
	    || afs_fstat(fd, &status) == -1) {
	    printf("Volinfo: Cannot read volume header %s\n", name);
	    close(fd);
	    exit(1);
	}
	n = read(fd, &diskHeader, sizeof(diskHeader));

	if (n != sizeof(diskHeader)
	    || diskHeader.stamp.magic != VOLUMEHEADERMAGIC) {
	    printf("Volinfo: Error reading volume header %s\n", name);
	    exit(1);
	}
	if (diskHeader.stamp.version != VOLUMEHEADERVERSION) {
	    printf
		("Volinfo: Volume %s, version number is incorrect; volume needs salvage\n",
		 name);
	    exit(1);
	}
	DiskToVolumeHeader(&header, &diskHeader);

	if (dheader) {
	    FdHandle_t *fdP;
	    afs_sfsize_t size = 0;
	    afs_sfsize_t code;

	    if (afs_fstat(fd, &stat) == -1) {
		perror("stat");
		exit(1);
	    }
	    if (!dsizeOnly && !saveinodes) {
		size = stat.st_size;
		printf("Volume header (size = %d):\n", (int)size);
		printf("\tstamp\t= 0x%x\n", header.stamp.version);
		printf("\tVolId\t= %u\n", header.id);
	    }

	    IH_INIT(ih, dp->device, header.parent, header.volumeInfo);
	    fdP = IH_OPEN(ih);
	    if (fdP == NULL) {
		perror("opening volume info");
		exit(1);
	    }
	    code = FDH_SIZE(fdP);
	    if (code == -1) {
		perror("fstat");
		exit(1);
	    }
	    FDH_REALLYCLOSE(fdP);
	    IH_RELEASE(ih);
	    size += code;
	    if (!dsizeOnly && !saveinodes) {
		printf("\tparent\t= %u\n", header.parent);
		printf("\tInfo inode\t= %s (size = %d)\n",
		       PrintInode(NULL, header.volumeInfo), (int)code);
	    }

	    IH_INIT(ih, dp->device, header.parent, header.smallVnodeIndex);
	    fdP = IH_OPEN(ih);
	    if (fdP == NULL) {
		perror("opening small vnode index");
		exit(1);
	    }
	    code = FDH_SIZE(fdP);
	    if (code == -1) {
		perror("fstat");
		exit(1);
	    }
	    FDH_REALLYCLOSE(fdP);
	    IH_RELEASE(ih);
	    size += code;
	    if (!dsizeOnly && !saveinodes) {
		printf("\tSmall inode\t= %s (size = %d)\n",
		       PrintInode(NULL, header.smallVnodeIndex), (int)code);
	    }

	    IH_INIT(ih, dp->device, header.parent, header.largeVnodeIndex);
	    fdP = IH_OPEN(ih);
	    if (fdP == NULL) {
		perror("opening large vnode index");
		exit(1);
	    }
	    code = FDH_SIZE(fdP);
	    if (code == -1) {
		perror("fstat");
		exit(1);
	    }
	    FDH_REALLYCLOSE(fdP);
	    IH_RELEASE(ih);
	    size += code;
	    if (!dsizeOnly && !saveinodes) {
		printf("\tLarge inode\t= %s (size = %d)\n",
		       PrintInode(NULL, header.largeVnodeIndex), (int)code);
#ifndef AFS_NT40_ENV
		printf("Total aux volume size = %d\n\n", (int)size);
#endif
	    }
#ifdef AFS_NAMEI_ENV
	    IH_INIT(ih, dp->device, header.parent, header.linkTable);
	    fdP = IH_OPEN(ih);
	    if (fdP == NULL) {
		perror("opening link table index");
		exit(1);
	    }
	    code = FDH_SIZE(fdP);
	    if (code == -1) {
		perror("fstat");
		exit(1);
	    }
	    FDH_REALLYCLOSE(fdP);
	    IH_RELEASE(ih);
	    size += code;
	    if (!dsizeOnly && !saveinodes) {
		printf("\tLink inode\t= %s (size = %d)\n",
		       PrintInode(NULL, header.linkTable), (int)code);
		printf("Total aux volume size = %d\n\n", (int)size);
	    }
#endif
	    Vauxsize = size;
	    Vauxsize_k = size / 1024;
	}
	close(fd);
	vp = AttachVolume(dp, name, &header);
	if (!vp) {
	    printf("Volinfo: Error attaching volume header %s\n", name);
	    return;
	}
    }
    PrintHeader(vp);
    if (DumpVnodes) {
	if (!dsizeOnly && !saveinodes)
	    printf("\nLarge vnodes (directories)\n");
	PrintVnodes(vp, vLarge);
	if (!dsizeOnly && !saveinodes) {
	    printf("\nSmall vnodes(files, symbolic links)\n");
	    fflush(stdout);
	}
	if (saveinodes)
	    printf("Saving all volume files to current directory ...\n");
	PrintVnodes(vp, vSmall);
    }
    if (dsizeOnly) {
	totvolsize = Vauxsize_k + Vvnodesize_k;
	if (saveinodes)
	    printf
		("Volume-Id\t  Volsize  Auxsize Inodesize  AVolsize SizeDiff                (VolName)\n");
	printf("%u\t%9d%9d%10d%10d%9d\t%24s\n", V_id(vp), Vdiskused,
	       Vauxsize_k, Vvnodesize_k, totvolsize, totvolsize - Vdiskused,
	       V_name(vp));
    }
    free(vp->header);
    free(vp);
}
Пример #8
0
void
VLockPartition_r(char *name)
{
    register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
    char *partitionName;
    int retries, code;
    struct timeval pausing;
#if defined(AFS_HPUX_ENV)
    int lockfRtn;
    struct privgrp_map privGrpList[PRIV_MAXGRPS];
    unsigned int *globalMask;
    int globalMaskIndex;
#endif /* defined(AFS_HPUX_ENV) */
#if defined(AFS_DARWIN_ENV)
    char lockfile[MAXPATHLEN];
#endif /* defined(AFS_DARWIN_ENV) */
#ifdef AFS_NAMEI_ENV
#ifdef AFS_AIX42_ENV
    char LockFileName[MAXPATHLEN + 1];

    sprintf((char *)&LockFileName, "%s/AFSINODE_FSLock", name);
    partitionName = (char *)&LockFileName;
#endif
#endif

    if (!dp)
	return;			/* no partition, will fail later */
    if (dp->lock_fd != -1)
	return;

#if    defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV)
#if !defined(AFS_AIX42_ENV) || !defined(AFS_NAMEI_ENV)
    partitionName = dp->devName;
#endif
    code = O_RDWR;
#elif defined(AFS_DARWIN_ENV)
    strlcpy((partitionName = lockfile), dp->name, sizeof(lockfile));
    strlcat(lockfile, "/.lock.afs", sizeof(lockfile));
    code = O_RDONLY | O_CREAT;
#else
    partitionName = dp->name;
    code = O_RDONLY;
#endif

    for (retries = 25; retries; retries--) {
	dp->lock_fd = afs_open(partitionName, code);
	if (dp->lock_fd != -1)
	    break;
	if (errno == ENOENT)
	    code |= O_CREAT;
	pausing.tv_sec = 0;
	pausing.tv_usec = 500000;
	select(0, NULL, NULL, NULL, &pausing);
    }
    assert(retries != 0);

#if defined (AFS_HPUX_ENV)

    assert(getprivgrp(privGrpList) == 0);

    /*
     * In general, it will difficult and time-consuming ,if not impossible,
     * to try to find the privgroup to which this process belongs that has the
     * smallest membership, to minimise the security hole.  So, we use the privgrp
     * to which everybody belongs.
     */
    /* first, we have to find the global mask */
    for (globalMaskIndex = 0; globalMaskIndex < PRIV_MAXGRPS;
	 globalMaskIndex++) {
	if (privGrpList[globalMaskIndex].priv_groupno == PRIV_GLOBAL) {
	    globalMask =
		&(privGrpList[globalMaskIndex].priv_mask[LOCKRDONLY_OFFSET]);
	    break;
	}
    }

    if (((*globalMask) & privmask(PRIV_LOCKRDONLY)) == 0) {
	/* allow everybody to set a lock on a read-only file descriptor */
	(*globalMask) |= privmask(PRIV_LOCKRDONLY);
	assert(setprivgrp(PRIV_GLOBAL, privGrpList[globalMaskIndex].priv_mask)
	       == 0);

	lockfRtn = lockf(dp->lock_fd, F_LOCK, 0);

	/* remove the privilege granted to everybody to lock a read-only fd */
	(*globalMask) &= ~(privmask(PRIV_LOCKRDONLY));
	assert(setprivgrp(PRIV_GLOBAL, privGrpList[globalMaskIndex].priv_mask)
	       == 0);
    } else {
	/* in this case, we should be able to do this with impunity, anyway */
	lockfRtn = lockf(dp->lock_fd, F_LOCK, 0);
    }

    assert(lockfRtn != -1);
#else
#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
    assert(lockf(dp->lock_fd, F_LOCK, 0) != -1);
#else
    assert(flock(dp->lock_fd, LOCK_EX) == 0);
#endif /* defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) */
#endif
}
Пример #9
0
/**
 * handle a single vol header as part of VWalkVolumeHeaders.
 *
 * @param[in] dp      disk partition
 * @param[in] volfunc function to call when a vol header is successfully read
 * @param[in] name    full path name to the .vol header
 * @param[out] hdr    header data read in from the .vol header
 * @param[in] locked  1 if the partition headers are locked, 0 otherwise
 * @param[in] rock    the rock to pass to volfunc
 *
 * @return operation status
 *  @retval 0  success
 *  @retval -1 fatal error, stop scanning
 *  @retval 1  failed to read header
 *  @retval 2  volfunc callback indicated error after header read
 */
static int
_VHandleVolumeHeader(struct DiskPartition64 *dp, VWalkVolFunc volfunc,
                     const char *name, struct VolumeDiskHeader *hdr,
                     int locked, void *rock)
{
    int error = 0;
    int fd;

    if ((fd = afs_open(name, O_RDONLY)) == -1
        || read(fd, hdr, sizeof(*hdr))
        != sizeof(*hdr)
        || hdr->stamp.magic != VOLUMEHEADERMAGIC) {
        error = 1;
    }

    if (fd >= 0) {
	close(fd);
    }

#ifdef AFSFS_DEMAND_ATTACH_FS
    if (locked) {
	VPartHeaderUnlock(dp);
    }
#endif /* AFS_DEMAND_ATTACH_FS */

    if (!error && volfunc) {
	/* the volume header seems fine; call the caller-supplied
	 * 'we-found-a-volume-header' function */
	int last = 1;

#ifdef AFS_DEMAND_ATTACH_FS
	if (!locked) {
	    last = 0;
	}
#endif /* AFS_DEMAND_ATTACH_FS */

	error = (*volfunc) (dp, name, hdr, last, rock);
	if (error < 0) {
	    return -1;
	}
	if (error) {
	    error = 2;
	}
    }

#ifdef AFS_DEMAND_ATTACH_FS
    if (error && !locked) {
	int code;
	/* retry reading the volume header under the partition
	 * header lock, just to be safe and ensure we're not
	 * racing something rewriting the vol header */
	code = VPartHeaderLock(dp, WRITE_LOCK);
	if (code) {
	    Log("Error acquiring partition write lock when "
		"looking at header %s\n", name);
	    return -1;
	}

	return _VHandleVolumeHeader(dp, volfunc, name, hdr, 1, rock);
    }
#endif /* AFS_DEMAND_ATTACH_FS */

    return error;
}