예제 #1
0
/* No lock needed. Only the volserver will call this, and only one transaction
 * can have a given volume (volid/partition pair) in use at a time 
 */
void
VPurgeVolume(Error * ec, Volume * vp)
{
    struct DiskPartition64 *tpartp = vp->partition;
    char purgePath[MAXPATHLEN];

    /* so VCheckDetach doesn't try to update the volume header and
     * dump spurious errors into the logs */
    V_inUse(vp) = 0;

    /* N.B.  it's important here to use the partition pointed to by the
     * volume header. This routine can, under some circumstances, be called
     * when two volumes with the same id exist on different partitions.
     */
    (void)afs_snprintf(purgePath, sizeof purgePath, "%s/%s",
		       VPartitionPath(vp->partition),
		       VolumeExternalName(V_id(vp)));
    PurgeIndex_r(vp, vLarge);
    PurgeIndex_r(vp, vSmall);
    PurgeHeader_r(vp);
    unlink(purgePath);
    /*
     * Call the fileserver to break all call backs for that volume
     */
    FSYNC_VolOp(V_id(vp), tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
}
예제 #2
0
파일: vutil.c 프로젝트: jblaine/openafs
/**
 * read an existing volume disk header.
 *
 * @param[in]  volid  volume id
 * @param[in]  dp     disk partition object
 * @param[out] hdr    volume disk header or NULL
 *
 * @note if hdr is NULL, this is essentially an existence test for the vol
 *       header
 *
 * @return operation status
 *    @retval 0 success
 *    @retval -1 volume header doesn't exist
 *    @retval EIO failed to read volume header
 *
 * @internal
 */
afs_int32
VReadVolumeDiskHeader(VolumeId volid,
		      struct DiskPartition64 * dp,
		      VolumeDiskHeader_t * hdr)
{
    afs_int32 code = 0;
    int fd;
    char path[MAXPATHLEN];

    snprintf(path, sizeof(path), "%s" OS_DIRSEP VFORMAT,
	     VPartitionPath(dp), afs_printable_VolumeId_lu(volid));
    fd = open(path, O_RDONLY);
    if (fd < 0) {
	Log("VReadVolumeDiskHeader: Couldn't open header for volume %" AFS_VOLID_FMT " (errno %d).\n",
	    afs_printable_VolumeId_lu(volid), errno);
	code = -1;

    } else if (hdr && read(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) {
	Log("VReadVolumeDiskHeader: Couldn't read header for volume %" AFS_VOLID_FMT ".\n",
	    afs_printable_VolumeId_lu(volid));
	code = EIO;
    }

    if (fd >= 0) {
	close(fd);
    }
    return code;
}
예제 #3
0
파일: partition.c 프로젝트: openafs/openafs
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 */
}
예제 #4
0
void
HandlePart(struct DiskPartition64 *partP)
{
    int nvols = 0;
    DIR *dirp;
    struct dirent *dp;
#ifdef AFS_NT40_ENV
    char pname[64];
    char *p = pname;
    (void)sprintf(pname, "%s\\", VPartitionPath(partP));
#else
    char *p = VPartitionPath(partP);
#endif

    if ((dirp = opendir(p)) == NULL) {
	printf("Can't read directory %s; giving up\n", p);
	exit(1);
    }
    if (dsizeOnly && !saveinodes)
	printf
	    ("Volume-Id\t  Volsize  Auxsize Inodesize  AVolsize SizeDiff                (VolName)\n");
    while ((dp = readdir(dirp))) {
	p = (char *)strrchr(dp->d_name, '.');
	if (p != NULL && strcmp(p, VHDREXT) == 0) {
	    HandleVolume(partP, dp->d_name);
	    Totvolsize += totvolsize;
	    TVauxsize += Vauxsize;
	    TVvnodesize += Vvnodesize;
	    TVdiskused += Vdiskused;
	    nvols++;
	}
    }
    closedir(dirp);
    if (dsizeOnly) {
	printf("\nPart Totals  %12d%9d%10d%10d%9d (%d volumes)\n\n",
	       TVdiskused, TVauxsize, TVvnodesize, Totvolsize,
	       Totvolsize - TVdiskused, nvols);
    }
}
예제 #5
0
/**
 * destroy a volume disk header.
 *
 * @param[in] dp      disk partition object
 * @param[in] volid   volume id
 * @param[in] parent  parent's volume id, 0 if unknown
 *
 * @return operation status
 *    @retval 0 success
 *
 * @note if parent is 0, the parent volume ID will be looked up from the
 * fileserver
 *
 * @note for non-DAFS, parent is currently ignored
 */
afs_int32
VDestroyVolumeDiskHeader(struct DiskPartition64 * dp,
			 VolumeId volid,
			 VolumeId parent)
{
    afs_int32 code = 0;
    char path[MAXPATHLEN];
#ifdef AFS_DEMAND_ATTACH_FS
    SYNC_response res;
#endif /* AFS_DEMAND_ATTACH_FS */

    (void)afs_snprintf(path, sizeof(path),
                       "%s/" VFORMAT,
                       VPartitionPath(dp), afs_printable_uint32_lu(volid));
    code = unlink(path);
    if (code) {
	Log("VDestroyVolumeDiskHeader: Couldn't unlink disk header, error = %d\n", errno);
	goto done;
    }

#ifdef AFS_DEMAND_ATTACH_FS
    memset(&res, 0, sizeof(res));
    if (!parent) {
	FSSYNC_VGQry_response_t q_res;

	code = FSYNC_VGCQuery(dp->name, volid, &q_res, &res);
	if (code) {
	    Log("VDestroyVolumeDiskHeader: FSYNC_VGCQuery(%s, %lu) failed "
	        "with code %ld, reason %ld\n", dp->name,
	        afs_printable_uint32_lu(volid), afs_printable_int32_ld(code),
		afs_printable_int32_ld(res.hdr.reason));
	    goto done;
	}

	parent = q_res.rw;

    }
    code = FSYNC_VGCDel(dp->name, parent, volid, FSYNC_WHATEVER, &res);
    if (code) {
	Log("VDestroyVolumeDiskHeader: FSYNC_VGCDel(%s, %lu, %lu) failed "
	    "with code %ld reason %ld\n", dp->name,
	    afs_printable_uint32_lu(parent),
	    afs_printable_uint32_lu(volid),
	    afs_printable_int32_ld(code),
	    afs_printable_int32_ld(res.hdr.reason));
    }
#endif /* AFS_DEMAND_ATTACH_FS */

 done:
    return code;
}
예제 #6
0
파일: vg_scan.c 프로젝트: adeason/openafs
/**
 * scanner thread.
 */
static void *
_VVGC_scanner_thread(void * args)
{
    struct DiskPartition64 *part = args;
    int code;

    code = _VVGC_scan_partition(part);
    if (code) {
	ViceLog(0, ("Error: _VVGC_scan_partition failed with code %d for partition %s\n",
	    code, VPartitionPath(part)));
    }

    return NULL;
}
예제 #7
0
/**
 * lock a partition's vol headers.
 *
 * @param[in] dp       the partition to lock
 * @param[in] locktype READ_LOCK or WRITE_LOCK
 *
 * @return operation status
 *  @retval 0 success
 */
int
VPartHeaderLock(struct DiskPartition64 *dp, int locktype)
{
    int code;

    /* block on acquiring the lock */
    int nonblock = 0;

    code = VGetDiskLock(&dp->headerLock, locktype, nonblock);
    if (code) {
	Log("VPartHeaderLock: error %d locking partititon %s\n", code,
	    VPartitionPath(dp));
    }
    return code;
}
예제 #8
0
/**
 * write an existing volume disk header.
 *
 * @param[in] hdr   volume disk header
 * @param[in] dp    disk partition object
 * @param[in] cr    assert if O_CREAT | O_EXCL should be passed to open()
 *
 * @return operation status
 *    @retval 0 success
 *    @retval -1 volume header doesn't exist
 *    @retval EIO failed to write volume header
 *
 * @internal
 */
static afs_int32
_VWriteVolumeDiskHeader(VolumeDiskHeader_t * hdr,
			struct DiskPartition64 * dp,
			int flags)
{
    afs_int32 code = 0;
    int fd;
    char path[MAXPATHLEN];

#ifdef AFS_DEMAND_ATTACH_FS
    /* prevent racing with VGC scanners reading the vol header while we are
     * writing it */
    code = VPartHeaderLock(dp, READ_LOCK);
    if (code) {
	return EIO;
    }
#endif /* AFS_DEMAND_ATTACH_FS */

    flags |= O_RDWR;

    (void)afs_snprintf(path, sizeof(path),
		       "%s/" VFORMAT,
		       VPartitionPath(dp), afs_printable_uint32_lu(hdr->id));
    fd = open(path, flags, 0644);
    if (fd < 0) {
	code = errno;
	Log("_VWriteVolumeDiskHeader: Couldn't open header for volume %lu, "
	    "error = %d\n", afs_printable_uint32_lu(hdr->id), errno);
    } else if (write(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) {
	Log("_VWriteVolumeDiskHeader: Couldn't write header for volume %lu, "
	    "error = %d\n", afs_printable_uint32_lu(hdr->id), errno);
	code = EIO;
    }

    if (fd >= 0) {
	if (close(fd) != 0) {
	    Log("_VWriteVolumeDiskHeader: Error closing header for volume "
	        "%lu, errno %d\n", afs_printable_uint32_lu(hdr->id), errno);
	}
    }

#ifdef AFS_DEMAND_ATTACH_FS
    VPartHeaderUnlock(dp, READ_LOCK);
#endif /* AFS_DEMAND_ATTACH_FS */

    return code;
}
예제 #9
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);
}
예제 #10
0
void
VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
{
    ULARGE_INTEGER free_user, total, free_total;
    int ufree, tot, tfree;

    if (!GetDiskFreeSpaceEx
	(VPartitionPath(dp), &free_user, &total, &free_total)) {
	printf("Failed to get disk space info for %s, error = %d\n", dp->name,
	       GetLastError());
	return;
    }

    /* Convert to 1K units. */
    ufree = (int)Int64ShraMod32(free_user.QuadPart, 10);
    tot = (int)Int64ShraMod32(total.QuadPart, 10);
    tfree = (int)Int64ShraMod32(free_total.QuadPart, 10);

    dp->minFree = tfree - ufree;	/* only used in VPrintDiskStats_r */
    dp->totalUsable = tot;
    dp->free = tfree;
}
예제 #11
0
void
VLockPartition_r(char *name)
{
    struct DiskPartition64 *dp = VGetPartition_r(name, 0);
    OVERLAPPED lap;

    if (!dp)
	return;
    if (dp->lock_fd == INVALID_FD) {
	char path[64];
	int rc;
	(void)sprintf(path, "%s\\%s", VPartitionPath(dp), LOCKFILE);
	dp->lock_fd =
	    (FD_t)CreateFile(path, GENERIC_WRITE,
			    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
			    CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
	assert(dp->lock_fd != INVALID_FD);

	memset(&lap, 0, sizeof(lap));
	rc = LockFileEx((HANDLE) dp->lock_fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1,
			0, &lap);
	assert(rc);
    }
}
예제 #12
0
/**
 * add an entry to the volume group cache.
 *
 * @param[in] dp       disk partition object
 * @param[in] parent   parent volume id
 * @param[in] child    child volume id
 * @param[out] newvg   if non-NULL, *newvg is 1 if adding this added a
 *                     new VG, 0 if we added to an existing VG
 *
 * @pre VOL_LOCK held
 *
 * @return operation status
 *    @retval 0 success
 *    @retval -1 parent and child are already registered in
 *               different VGs
 */
int
VVGCache_entry_add_r(struct DiskPartition64 * dp,
		     VolumeId parent,
		     VolumeId child,
		     afs_int32 *newvg)
{
    int code = 0, res;
    VVGCache_entry_t * child_ent, * parent_ent;

    if (newvg) {
	*newvg = 0;
    }

    /* check for existing entries */
    res = _VVGC_lookup(dp, child, &child_ent, NULL);
    if (res && res != ENOENT) {
	code = res;
	goto done;
    }

    res = _VVGC_lookup(dp, parent, &parent_ent, NULL);
    if (res && res != ENOENT) {
	code = res;
	goto done;
    }

    /*
     * branch based upon existence of parent and child nodes
     */
    if (parent_ent && child_ent) {
	/* both exist.  we're done.
	 * if they point different places, then report the error. */
	if (child_ent != parent_ent) {
	    code = -1;
	}
	if (parent == child) {
	    /* if we're adding the RW entry as a child, the RW id may
	     * not be in the child array yet, so make sure not to skip
	     * over that */
	    goto cladd;
	}
	goto done;
    } else if (!parent_ent && child_ent) {
	/* child exists.
	 * update vg root volid, and add hash entry. */
	parent_ent = child_ent;
	parent_ent->rw = parent;

	code = _VVGC_hash_entry_add(dp,
				    parent,
				    parent_ent,
				    NULL);
	goto done;
    } else if (!child_ent && !parent_ent) {
	code = _VVGC_entry_add(dp,
			       parent,
			       &parent_ent,
			       NULL);
	if (code) {
	    goto done;
	}
	if (newvg) {
	    *newvg = 1;
	}
	if (child == parent) {
	    /* if we're the RW, skip over adding the child hash entry;
	     * we already added the hash entry when creating the entry */
	    child_ent = parent_ent;
	    goto cladd;
	}
    }

    osi_Assert(!child_ent);
    child_ent = parent_ent;
    code = _VVGC_hash_entry_add(dp,
				child,
				child_ent,
				NULL);
    if (code) {
	goto done;
    }

 cladd:
    code = _VVGC_entry_cl_add(child_ent, child);

 done:
    if (code && code != EINVAL) {
	ViceLog(0, ("VVGCache_entry_add: error %d trying to add vol %lu to VG"
	    " %lu on partition %s", code, afs_printable_uint32_lu(child),
	    afs_printable_uint32_lu(parent), VPartitionPath(dp)));
    }

    if (code == 0 && VVGCache.part[dp->index].state == VVGC_PART_STATE_UPDATING) {
	/* we successfully added the entry; make sure it's not on the
	 * to-delete list, so it doesn't get deleted later */
	code = _VVGC_dlist_del_r(dp, parent, child);
	if (code && code != ENOENT) {
	    ViceLog(0, ("VVGCache_entry_add: error %d trying to remove vol "
	                "%lu (parent %lu) from the to-delete list for part "
	                "%s.\n", code, afs_printable_uint32_lu(child),
	                afs_printable_uint32_lu(parent),
	                VPartitionPath(dp)));
	} else {
	    code = 0;
	}
    }

    return code;
}
예제 #13
0
파일: vg_scan.c 프로젝트: adeason/openafs
/**
 * start a background scan.
 *
 * @param[in] dp  disk partition object
 *
 * @return operation status
 *    @retval 0 success
 *    @retval -1 internal error
 *    @retval -3 racing against another thread
 *
 * @internal
 */
int
_VVGC_scan_start(struct DiskPartition64 * dp)
{
    int code = 0;
    pthread_t tid;
    pthread_attr_t attrs;
    int i;

    if (_VVGC_state_change(dp,
			   VVGC_PART_STATE_UPDATING)
	== VVGC_PART_STATE_UPDATING) {
	/* race */
	ViceLog(0, ("VVGC_scan_partition: race detected; aborting scanning partition %s\n",
	            VPartitionPath(dp)));
	code = -3;
	goto error;
    }

    /* initialize partition's to-delete list */
    VVGCache.part[dp->index].dlist_hash_buckets =
	malloc(VolumeHashTable.Size * sizeof(struct rx_queue));
    if (!VVGCache.part[dp->index].dlist_hash_buckets) {
	code = -1;
	goto error;
    }
    for (i = 0; i < VolumeHashTable.Size; i++) {
	queue_Init(&VVGCache.part[dp->index].dlist_hash_buckets[i]);
    }

    code = pthread_attr_init(&attrs);
    if (code) {
	goto error;
    }

    code = pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
    if (code) {
	goto error;
    }

    code = pthread_create(&tid, &attrs, &_VVGC_scanner_thread, dp);

    if (code) {
	VVGCache_part_state_t old_state;

	ViceLog(0, ("_VVGC_scan_start: pthread_create failed with %d\n", code));

	old_state = _VVGC_state_change(dp, VVGC_PART_STATE_INVALID);
	osi_Assert(old_state == VVGC_PART_STATE_UPDATING);
    }

 error:
    if (code) {
	ViceLog(0, ("_VVGC_scan_start failed with code %d for partition %s\n",
	        code, VPartitionPath(dp)));
	if (VVGCache.part[dp->index].dlist_hash_buckets) {
	    free(VVGCache.part[dp->index].dlist_hash_buckets);
	    VVGCache.part[dp->index].dlist_hash_buckets = NULL;
	}
    }

    return code;
}
예제 #14
0
파일: vg_scan.c 프로젝트: adeason/openafs
/**
 * scan a disk partition for .vol files
 *
 * @param[in] part   disk partition object
 *
 * @pre VOL_LOCK is NOT held
 *
 * @return operation status
 *    @retval 0 success
 *    @retval -1 invalid disk partition object
 *    @retval -2 failed to flush stale entries for this partition
 *
 * @internal
 */
static int
_VVGC_scan_partition(struct DiskPartition64 * part)
{
    int code, res;
    DIR *dirp = NULL;
    VVGCache_scan_table_t tbl;
    char *part_path = NULL;

    code = _VVGC_scan_table_init(&tbl);
    if (code) {
	ViceLog(0, ("VVGC_scan_partition: could not init scan table; error = %d\n",
	    code));
	goto done;
    }
    part_path = VPartitionPath(part);
    if (part_path == NULL) {
	ViceLog(0, ("VVGC_scan_partition: invalid partition object given; aborting scan\n"));
	code = -1;
	goto done;
    }

    VOL_LOCK;
    res = _VVGC_flush_part_r(part);
    if (res) {
	ViceLog(0, ("VVGC_scan_partition: error flushing partition %s; error = %d\n",
	    VPartitionPath(part), res));
	code = -2;
    }
    VOL_UNLOCK;
    if (code) {
	goto done;
    }

    dirp = opendir(part_path);
    if (dirp == NULL) {
	ViceLog(0, ("VVGC_scan_partition: could not open %s, aborting scan; error = %d\n",
	    part_path, errno));
	code = -1;
	goto done;
    }

    ViceLog(5, ("VVGC_scan_partition: scanning partition %s for VG cache\n",
                 part_path));

    code = VWalkVolumeHeaders(part, part_path, _VVGC_RecordHeader,
                              _VVGC_UnlinkHeader, &tbl);
    if (code < 0) {
	goto done;
    }

    _VVGC_scan_table_flush(&tbl, part);

 done:
    if (dirp) {
	closedir(dirp);
	dirp = NULL;
    }
    if (code) {
	ViceLog(0, ("VVGC_scan_partition: error %d while scanning %s\n",
	            code, part_path));
    } else {
	ViceLog(0, ("VVGC_scan_partition: finished scanning %s: %lu volumes in %lu groups\n",
	             part_path, tbl.newvols, tbl.newvgs));
    }

    VOL_LOCK;

    _VVGC_flush_dlist(part);
    free(VVGCache.part[part->index].dlist_hash_buckets);
    VVGCache.part[part->index].dlist_hash_buckets = NULL;

    if (code) {
	_VVGC_state_change(part, VVGC_PART_STATE_INVALID);
    } else {
	_VVGC_state_change(part, VVGC_PART_STATE_VALID);
    }

    VOL_UNLOCK;

    return code;
}
예제 #15
0
파일: vg_scan.c 프로젝트: adeason/openafs
/**
 * flush thread-local scan table to the global VG cache.
 *
 * @param[in] tbl     scan table
 * @param[in] dp      disk partition object
 *
 * @pre VOL_LOCK is NOT held
 *
 * @return operation status
 *    @retval 0 success
 *    @retval nonzero a VVGCache_entry_add_r operation failed during a
 *                    flush of the thread-local table
 *
 * @internal
 */
static int
_VVGC_scan_table_flush(VVGCache_scan_table_t * tbl,
		       struct DiskPartition64 * dp)
{
    int code = 0, res, i;
    afs_int32 newvg = 0;
    unsigned long newvols, newvgs;

    newvols = tbl->newvols;
    newvgs = tbl->newvgs;

    VOL_LOCK;

    for (i = 0; i < tbl->idx; i++) {
	/*
	 * We need to check the 'to-delete' list and prevent adding any entries
	 * that are on it. The volser could potentially create a volume in one
	 * VG, then delete it and put it on another VG. If we are doing a scan
	 * when that happens, tbl->entries could have the entries for trying to
	 * put the vol on both VGs, though at least one of them will also be on
	 * the dlist.  If we put everything in tbl->entries on the VGC then try
	 * to delete afterwards, putting one entry on the VGC cause an error,
	 * and we'll fail to add it. So instead, avoid adding any new VGC
	 * entries if it is on the dlist.
	 */
	if (_VVGC_dlist_lookup_r(dp, tbl->entries[i].parent,
			         tbl->entries[i].volid)) {
	    continue;
	}
	res = VVGCache_entry_add_r(dp,
				   tbl->entries[i].parent,
				   tbl->entries[i].volid,
				   &newvg);
	if (res) {
	    code = res;
	} else {
	    newvols++;
	    newvgs += newvg;
	}
    }

    /* flush the to-delete list while we're here. We don't need to preserve
     * the list across the entire scan, and flushing it each time we flush
     * a scan table will keep the size of the dlist down */
    _VVGC_flush_dlist(dp);

    VOL_UNLOCK;

    ViceLog(125, ("VVGC_scan_table_flush: flushed %d entries from "
                  "scan table to global VG cache\n", tbl->idx));
    ViceLog(125, ("VVGC_scan_table_flush: %s total: %lu vols, %lu groups\n",
                  VPartitionPath(dp), newvols, newvgs));

    res = _VVGC_scan_table_init(tbl);
    if (res) {
	code = res;
    }

    tbl->newvols = newvols;
    tbl->newvgs = newvgs;

    return code;
}
예제 #16
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);
}
예제 #17
0
파일: vutil.c 프로젝트: jblaine/openafs
Volume *
VCreateVolume_r(Error * ec, char *partname, VolumeId volumeId, VolumeId parentId)
{				/* Should be the same as volumeId if there is
				 * no parent */
    VolumeDiskData vol;
    int i, rc;
    char headerName[VMAXPATHLEN], volumePath[VMAXPATHLEN];
    Device device;
    struct DiskPartition64 *partition;
    struct VolumeDiskHeader diskHeader;
    IHandle_t *handle;
    FdHandle_t *fdP;
    Inode nearInode AFS_UNUSED = 0;
    char *part, *name;
    struct stat st;
    struct VolumeHeader tempHeader;
    struct afs_inode_info stuff[MAXINODETYPE];
    afs_ino_str_t stmp;
# ifdef AFS_DEMAND_ATTACH_FS
    int locktype = 0;
# endif /* AFS_DEMAND_ATTACH_FS */

    init_inode_info(&tempHeader, stuff);

    *ec = 0;
    memset(&vol, 0, sizeof(vol));
    vol.id = volumeId;
    vol.parentId = parentId;
    vol.copyDate = time(0);	/* The only date which really means when this
				 * @i(instance) of this volume was created.
				 * Creation date does not mean this */

    /* Initialize handle for error case below. */
    handle = NULL;

    /* Verify that the parition is valid before writing to it. */
    if (!(partition = VGetPartition_r(partname, 0))) {
	Log("VCreateVolume: partition %s is not in service.\n", partname);
	*ec = VNOVOL;
	return NULL;
    }
#if	defined(NEARINODE_HINT)
    nearInodeHash(volumeId, nearInode);
    nearInode %= partition->f_files;
#endif
    VGetVolumePath(ec, vol.id, &part, &name);
    if (*ec == VNOVOL || !strcmp(partition->name, part)) {
	/* this case is ok */
    } else {
	/* return EXDEV if it's a clone to an alternate partition
	 * otherwise assume it's a move */
	if (vol.parentId != vol.id) {
	    *ec = EXDEV;
	    return NULL;
	}
    }
    *ec = 0;

# ifdef AFS_DEMAND_ATTACH_FS
    /* volume doesn't exist yet, but we must lock it to try to prevent something
     * else from reading it when we're e.g. half way through creating it (or
     * something tries to create the same volume at the same time) */
    locktype = VVolLockType(V_VOLUPD, 1);
    rc = VLockVolumeByIdNB(volumeId, partition, locktype);
    if (rc) {
	Log("VCreateVolume: vol %lu already locked by someone else\n",
	    afs_printable_uint32_lu(volumeId));
	*ec = VNOVOL;
	return NULL;
    }
# else /* AFS_DEMAND_ATTACH_FS */
    VLockPartition_r(partname);
# endif /* !AFS_DEMAND_ATTACH_FS */

    memset(&tempHeader, 0, sizeof(tempHeader));
    tempHeader.stamp.magic = VOLUMEHEADERMAGIC;
    tempHeader.stamp.version = VOLUMEHEADERVERSION;
    tempHeader.id = vol.id;
    tempHeader.parent = vol.parentId;
    vol.stamp.magic = VOLUMEINFOMAGIC;
    vol.stamp.version = VOLUMEINFOVERSION;
    vol.destroyMe = DESTROY_ME;
    snprintf(headerName, sizeof headerName, VFORMAT,
	     afs_printable_VolumeId_lu(vol.id));
    snprintf(volumePath, sizeof volumePath, "%s" OS_DIRSEP "%s",
	     VPartitionPath(partition), headerName);
    rc = stat(volumePath, &st);
    if (rc == 0 || errno != ENOENT) {
	if (rc == 0) {
	    Log("VCreateVolume: Header file %s already exists!\n",
		volumePath);
	    *ec = VVOLEXISTS;
	} else {
	    Log("VCreateVolume: Error %d trying to stat header file %s\n",
	        errno, volumePath);
	    *ec = VNOVOL;
	}
	goto bad_noheader;
    }
    device = partition->device;

    for (i = 0; i < MAXINODETYPE; i++) {
	struct afs_inode_info *p = &stuff[i];
	if (p->obsolete)
	    continue;
#ifdef AFS_NAMEI_ENV
	*(p->inode) =
	    IH_CREATE(NULL, device, VPartitionPath(partition), nearInode,
		      (p->inodeType == VI_LINKTABLE) ? vol.parentId : vol.id,
		      INODESPECIAL, p->inodeType, vol.parentId);
	if (!(VALID_INO(*(p->inode)))) {
	    if (errno == EEXIST && (p->inodeType == VI_LINKTABLE)) {
		/* Increment the reference count instead. */
		IHandle_t *lh;
		int code;

		*(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
		IH_INIT(lh, device, parentId, *(p->inode));
		fdP = IH_OPEN(lh);
		if (fdP == NULL) {
		    IH_RELEASE(lh);
		    goto bad;
		}
		code = IH_INC(lh, *(p->inode), parentId);
		FDH_REALLYCLOSE(fdP);
		IH_RELEASE(lh);
		if (code < 0)
		    goto bad;
		continue;
	    }
	}
#else
	*(p->inode) =
	    IH_CREATE(NULL, device, VPartitionPath(partition), nearInode,
		      vol.id, INODESPECIAL, p->inodeType, vol.parentId);
#endif

	if (!VALID_INO(*(p->inode))) {
	    Log("VCreateVolume:  Problem creating %s file associated with volume header %s\n", p->description, volumePath);
	  bad:
	    if (handle)
		IH_RELEASE(handle);
	    RemoveInodes(stuff, device, vol.parentId, vol.id);
	    if (!*ec) {
		*ec = VNOVOL;
	    }
	    VDestroyVolumeDiskHeader(partition, volumeId, parentId);
	  bad_noheader:
# ifdef AFS_DEMAND_ATTACH_FS
	    if (locktype) {
		VUnlockVolumeById(volumeId, partition);
	    }
# endif /* AFS_DEMAND_ATTACH_FS */
	    return NULL;
	}
	IH_INIT(handle, device, vol.parentId, *(p->inode));
	fdP = IH_OPEN(handle);
	if (fdP == NULL) {
	    Log("VCreateVolume:  Problem iopen inode %s (err=%d)\n",
		PrintInode(stmp, *(p->inode)), errno);
	    goto bad;
	}
	if (FDH_PWRITE(fdP, (char *)&p->stamp, sizeof(p->stamp), 0) !=
	    sizeof(p->stamp)) {
	    Log("VCreateVolume:  Problem writing to inode %s (err=%d)\n",
		PrintInode(stmp, *(p->inode)), errno);
	    FDH_REALLYCLOSE(fdP);
	    goto bad;
	}
	FDH_REALLYCLOSE(fdP);
	IH_RELEASE(handle);
	nearInode = *(p->inode);
    }

    IH_INIT(handle, device, vol.parentId, tempHeader.volumeInfo);
    fdP = IH_OPEN(handle);
    if (fdP == NULL) {
	Log("VCreateVolume:  Problem iopen inode %s (err=%d)\n",
	    PrintInode(stmp, tempHeader.volumeInfo), errno);
	goto bad;
    }
    if (FDH_PWRITE(fdP, (char *)&vol, sizeof(vol), 0) != sizeof(vol)) {
	Log("VCreateVolume:  Problem writing to  inode %s (err=%d)\n",
	    PrintInode(stmp, tempHeader.volumeInfo), errno);
	FDH_REALLYCLOSE(fdP);
	goto bad;
    }
    FDH_CLOSE(fdP);
    IH_RELEASE(handle);

    VolumeHeaderToDisk(&diskHeader, &tempHeader);
    rc = VCreateVolumeDiskHeader(&diskHeader, partition);
    if (rc) {
	Log("VCreateVolume: Error %d trying to write volume header for "
	    "volume %" AFS_VOLID_FMT " on partition %s; volume not created\n", rc,
	    afs_printable_VolumeId_lu(vol.id), VPartitionPath(partition));
	if (rc == EEXIST) {
	    *ec = VVOLEXISTS;
	}
	goto bad;
    }

# ifdef AFS_DEMAND_ATTACH_FS
    if (locktype) {
	VUnlockVolumeById(volumeId, partition);
    }
# endif /* AFS_DEMAND_ATTACH_FS */
    return (VAttachVolumeByName_r(ec, partname, headerName, V_SECRETLY));
}