예제 #1
0
int pt_section_map_share(struct pt_section *section)
{
	uint16_t mcount;
	int errcode;

	if (!section)
		return -pte_internal;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	mcount = section->mcount;
	if (!mcount) {
		(void) pt_section_unlock(section);
		return -pte_internal;
	}

	mcount += 1;
	if (!mcount) {
		(void) pt_section_unlock(section);
		return -pte_overflow;
	}

	section->mcount = mcount;

	return pt_section_unlock(section);
}
예제 #2
0
int pt_section_put(struct pt_section *section)
{
	uint16_t ucount, mcount;
	int errcode;

	if (!section)
		return -pte_internal;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	mcount = section->mcount;
	ucount = section->ucount;
	if (ucount > 1) {
		section->ucount = ucount - 1;
		return pt_section_unlock(section);
	}

	errcode = pt_section_unlock(section);
	if (errcode < 0)
		return errcode;

	if (!ucount || mcount)
		return -pte_internal;

	pt_section_free(section);
	return 0;
}
예제 #3
0
static int pt_sec_posix_map_success(struct pt_section *section)
{
	uint16_t mcount;
	int errcode, status;

	if (!section)
		return -pte_internal;

	mcount = section->mcount + 1;
	if (!mcount) {
		(void) pt_section_unlock(section);
		return -pte_overflow;
	}

	section->mcount = mcount;

	errcode = pt_section_unlock(section);
	if (errcode < 0)
		return errcode;

	status = pt_section_on_map(section);
	if (status < 0) {
		/* We had to release the section lock for pt_section_on_map() so
		 * @section may have meanwhile been mapped by other threads.
		 *
		 * We still want to return the error so we release our mapping.
		 * Our caller does not yet know whether pt_section_map()
		 * succeeded.
		 */
		(void) pt_section_unmap(section);
		return status;
	}

	return 0;
}
예제 #4
0
int pt_section_unmap(struct pt_section *section)
{
	uint16_t mcount;
	int errcode, status;

	if (!section)
		return -pte_internal;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	mcount = section->mcount;

	errcode = -pte_nomap;
	if (!mcount)
		goto out_unlock;

	section->mcount = mcount -= 1;
	if (mcount)
		return pt_section_unlock(section);

	errcode = -pte_internal;
	if (!section->unmap)
		goto out_unlock;

	status = section->unmap(section);

	pt_bcache_free(section->bcache);
	section->bcache = NULL;

	errcode = pt_section_unlock(section);
	if (errcode < 0)
		return errcode;

	return status;

out_unlock:
	(void) pt_section_unlock(section);
	return errcode;
}
예제 #5
0
int pt_section_get(struct pt_section *section)
{
	uint16_t ucount;
	int errcode;

	if (!section)
		return -pte_internal;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	ucount = section->ucount + 1;
	if (!ucount) {
		(void) pt_section_unlock(section);
		return -pte_internal;
	}

	section->ucount = ucount;

	return pt_section_unlock(section);
}
예제 #6
0
int pt_section_memsize(struct pt_section *section, uint64_t *size)
{
	int errcode, status;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	status = pt_section_memsize_locked(section, size);

	errcode = pt_section_unlock(section);
	if (errcode < 0)
		return errcode;

	return status;
}
예제 #7
0
int pt_section_map(struct pt_section *section)
{
	const char *filename;
	uint16_t mcount;
	FILE *file;
	int fd, errcode;

	if (!section)
		return -pte_internal;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	mcount = section->mcount + 1;
	if (mcount > 1) {
		section->mcount = mcount;
		return pt_section_unlock(section);
	}

	errcode = -pte_internal;
	if (!mcount)
		goto out_unlock;

	if (section->mapping)
		goto out_unlock;

	filename = section->filename;
	if (!filename)
		goto out_unlock;

	errcode = -pte_bad_image;
	fd = open(filename, O_RDONLY);
	if (fd == -1)
		goto out_unlock;

	errcode = check_file_status(section, fd);
	if (errcode < 0)
		goto out_fd;

	/* We close the file on success.  This does not unmap the section. */
	errcode = pt_sec_posix_map(section, fd);
	if (!errcode) {
		section->mcount = 1;
		close(fd);
		return pt_section_unlock(section);
	}

	/* Fall back to file based sections - report the original error
	 * if we fail to convert the file descriptor.
	 */
	file = fdopen(fd, "rb");
	if (!file)
		goto out_fd;

	/* We need to keep the file open on success.  It will be closed when
	 * the section is unmapped.
	 */
	errcode = pt_sec_file_map(section, file);
	if (!errcode) {
		section->mcount = 1;
		return pt_section_unlock(section);
	}

	fclose(file);
	goto out_unlock;

out_fd:
	close(fd);

out_unlock:
	(void) pt_section_unlock(section);
	return errcode;
}
예제 #8
0
int pt_section_alloc_bcache(struct pt_section *section)
{
	struct pt_image_section_cache *iscache;
	struct pt_block_cache *bcache;
	uint64_t ssize, memsize;
	uint32_t csize;
	int errcode;

	if (!section)
		return -pte_internal;

	if (!section->mcount)
		return -pte_internal;

	ssize = pt_section_size(section);
	csize = (uint32_t) ssize;

	if (csize != ssize)
		return -pte_not_supported;

	memsize = 0ull;

	/* We need to take both the attach and the section lock in order to pair
	 * the block cache allocation and the resize notification.
	 *
	 * This allows map notifications in between but they only change the
	 * order of sections in the cache.
	 *
	 * The attach lock needs to be taken first.
	 */
	errcode = pt_section_lock_attach(section);
	if (errcode < 0)
		return errcode;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		goto out_alock;

	bcache = pt_section_bcache(section);
	if (bcache) {
		errcode = 0;
		goto out_lock;
	}

	bcache = pt_bcache_alloc(csize);
	if (!bcache) {
		errcode = -pte_nomem;
		goto out_lock;
	}

	/* Install the block cache.  It will become visible and may be used
	 * immediately.
	 *
	 * If we fail later on, we leave the block cache and report the error to
	 * the allocating decoder thread.
	 */
	section->bcache = bcache;

	errcode = pt_section_memsize_locked(section, &memsize);
	if (errcode < 0)
		goto out_lock;

	errcode = pt_section_unlock(section);
	if (errcode < 0)
		goto out_alock;

	if (memsize) {
		iscache = section->iscache;
		if (iscache) {
			errcode = pt_iscache_notify_resize(iscache, section,
							  memsize);
			if (errcode < 0)
				goto out_alock;
		}
	}

	return pt_section_unlock_attach(section);


out_lock:
	(void) pt_section_unlock(section);

out_alock:
	(void) pt_section_unlock_attach(section);
	return errcode;
}