Exemplo n.º 1
0
/**
 * lookup a vg cache entry given any member volume id.
 *
 * @param[in]  dp           disk partition object
 * @param[in]  volid        vg member volume id
 * @param[out] entry_out    address in which to store volume group entry structure pointer
 * @param[out] hash_out     address in which to store hash entry pointer
 *
 * @pre VOL_LOCK held
 *
 * @warning - it is up to the caller to get a ref to entry_out, if needed
 *          - hash_out must not be referenced after dropping VOL_LOCK
 *
 * @return operation status
 *    @retval 0 success
 *    @retval ENOENT volume id not found
 *    @retval EINVAL partition's VGC is invalid
 *
 * @internal
 */
static int
_VVGC_lookup(struct DiskPartition64 * dp,
               VolumeId volid,
               VVGCache_entry_t ** entry_out,
               VVGCache_hash_entry_t ** hash_out)
{
    int code = ENOENT;
    int bucket = VVGC_HASH(volid);
    struct VVGCache_hash_entry * ent, * nent;

    if (VVGCache.part[dp->index].state == VVGC_PART_STATE_INVALID) {
	return EINVAL;
    }

    *entry_out = NULL;

    for (queue_Scan(&VVGCache_hash_table.hash_buckets[bucket],
		    ent,
		    nent,
		    VVGCache_hash_entry)) {
	if (ent->volid == volid && ent->dp == dp) {
	    code = 0;
	    *entry_out = ent->entry;
	    if (hash_out) {
		*hash_out = ent;
	    }
	    break;
	}
    }

    return code;
}
Exemplo n.º 2
0
/**
 * add an entry to the hash table.
 *
 * @param[in]  dp        disk partition object
 * @param[in]  volid     volume id
 * @param[in]  ent       volume group object
 * @param[out] hash_out  address in which to store pointer to hash entry
 *
 * @pre VOL_LOCK held
 *
 * @return operation status
 *    @retval 0 success
 *    @retval EEXIST hash entry for volid already exists, and it points to
 *                   a different VG entry
 *
 * @internal
 */
static int
_VVGC_hash_entry_add(struct DiskPartition64 * dp,
		     VolumeId volid,
		     VVGCache_entry_t * ent,
		     VVGCache_hash_entry_t ** hash_out)
{
    int code = 0;
    VVGCache_hash_entry_t * hent;
    int hash = VVGC_HASH(volid);
    VVGCache_entry_t *nent;

    code = _VVGC_lookup(dp, volid, &nent, hash_out);
    if (!code) {
	if (ent != nent) {
	    ViceLog(0, ("_VVGC_hash_entry_add: tried to add a duplicate "
	                " nonmatching entry for vol %lu: original "
	                "(%"AFS_PTR_FMT",%lu) new (%"AFS_PTR_FMT",%lu)\n",
	                afs_printable_uint32_lu(volid),
	                nent, afs_printable_uint32_lu(nent->rw),
	                ent, afs_printable_uint32_lu(ent->rw)));
	    return EEXIST;
	}
	ViceLog(1, ("_VVGC_hash_entry_add: tried to add duplicate "
	              "hash entry for vol %lu, VG %lu",
	              afs_printable_uint32_lu(volid),
	              afs_printable_uint32_lu(ent->rw)));
	/* accept attempts to add matching duplicate entries; just
	 * pretend we added it */
	return 0;
    }

    code = _VVGC_hash_entry_alloc(&hent);
    if (code) {
	goto done;
    }

    hent->entry = ent;
    hent->dp    = dp;
    hent->volid = volid;
    queue_Append(&VVGCache_hash_table.hash_buckets[hash],
		 hent);

 done:
    if (hash_out) {
	*hash_out = hent;
    }
    return code;
}
Exemplo n.º 3
0
/**
 * looks up an entry on the to-delete list, if it exists.
 *
 * @param[in] dp     the partition whose dlist we are looking at
 * @param[in] parent the parent volume ID we're looking for
 * @param[in] child  the child volume ID we're looking for
 *
 * @return a pointer to the entry in the dlist for that entry
 *  @retval NULL the requested entry does not exist in the dlist
 */
static VVGCache_dlist_entry_t *
_VVGC_dlist_lookup_r(struct DiskPartition64 *dp, VolumeId parent,
                     VolumeId child)
{
    int bucket = VVGC_HASH(child);
    VVGCache_dlist_entry_t *ent, *nent;

    for (queue_Scan(&VVGCache.part[dp->index].dlist_hash_buckets[bucket],
                    ent, nent,
		    VVGCache_dlist_entry)) {

	if (ent->child == child && ent->parent == parent) {
	    return ent;
	}
    }

    return NULL;
}
Exemplo n.º 4
0
/**
 * add a VGC entry to the partition's to-delete list.
 *
 * This adds a VGC entry (a parent/child pair) to a list of VGC entries to
 * be deleted from the VGC at the end of a VGC scan. This is necessary,
 * while a VGC scan is ocurring, volumes may be deleted. Since a VGC scan
 * scans a partition in VVGC_SCAN_TBL_LEN chunks, a VGC delete operation
 * may delete a volume, only for it to be added again when the VGC scan's
 * table adds it to the VGC. So when a VGC entry is deleted and a VGC scan
 * is running, this function must be called to ensure it does not come
 * back onto the VGC.
 *
 * @param[in] dp      the partition to whose dlist we are adding
 * @param[in] parent  the parent volumeID of the VGC entry
 * @param[in] child   the child volumeID of the VGC entry
 *
 * @return operation status
 *  @retval 0 success
 *  @retval ENOMEM memory allocation error
 *
 * @pre VVGCache.part[dp->index].state == VVGC_PART_STATE_UPDATING
 *
 * @internal VGC use only
 */
int
_VVGC_dlist_add_r(struct DiskPartition64 *dp, VolumeId parent,
                  VolumeId child)
{
    int bucket = VVGC_HASH(child);
    VVGCache_dlist_entry_t *entry;

    entry = malloc(sizeof(*entry));
    if (!entry) {
	return ENOMEM;
    }

    entry->child = child;
    entry->parent = parent;

    queue_Append(&VVGCache.part[dp->index].dlist_hash_buckets[bucket],
                 entry);
    return 0;
}