Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d9bfe91 authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

s390/cio: fix measurement characteristics memleak



Measurement characteristics are allocated during channel path
registration but not freed during deregistration. Fix this by
embedding these characteristics inside struct channel_path.

Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: default avatarPeter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent d8f51227
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -139,11 +139,11 @@ static ssize_t chp_measurement_chars_read(struct file *filp,

	device = container_of(kobj, struct device, kobj);
	chp = to_channelpath(device);
	if (!chp->cmg_chars)
	if (chp->cmg == -1)
		return 0;

	return memory_read_from_buffer(buf, count, &off,
				chp->cmg_chars, sizeof(struct cmg_chars));
	return memory_read_from_buffer(buf, count, &off, &chp->cmg_chars,
				       sizeof(chp->cmg_chars));
}

static struct bin_attribute chp_measurement_chars_attr = {
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ struct channel_path {
	/* Channel-measurement related stuff: */
	int cmg;
	int shared;
	void *cmg_chars;
	struct cmg_chars cmg_chars;
};

/* Return channel_path struct for given chpid. */
+2 −14
Original line number Diff line number Diff line
@@ -967,22 +967,19 @@ static void
chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
			  struct cmg_chars *chars)
{
	struct cmg_chars *cmg_chars;
	int i, mask;

	cmg_chars = chp->cmg_chars;
	for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
		mask = 0x80 >> (i + 3);
		if (cmcv & mask)
			cmg_chars->values[i] = chars->values[i];
			chp->cmg_chars.values[i] = chars->values[i];
		else
			cmg_chars->values[i] = 0;
			chp->cmg_chars.values[i] = 0;
	}
}

int chsc_get_channel_measurement_chars(struct channel_path *chp)
{
	struct cmg_chars *cmg_chars;
	int ccode, ret;

	struct {
@@ -1006,11 +1003,6 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
		u32 data[NR_MEASUREMENT_CHARS];
	} __attribute__ ((packed)) *scmc_area;

	chp->cmg_chars = NULL;
	cmg_chars = kmalloc(sizeof(*cmg_chars), GFP_KERNEL);
	if (!cmg_chars)
		return -ENOMEM;

	spin_lock_irq(&chsc_page_lock);
	memset(chsc_page, 0, PAGE_SIZE);
	scmc_area = chsc_page;
@@ -1042,14 +1034,10 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
		/* No cmg-dependent data. */
		goto out;
	}
	chp->cmg_chars = cmg_chars;
	chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
				  (struct cmg_chars *) &scmc_area->data);
out:
	spin_unlock_irq(&chsc_page_lock);
	if (!chp->cmg_chars)
		kfree(cmg_chars);

	return ret;
}