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: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
d8f51227f3
commit
0d9bfe9123
|
@ -139,11 +139,11 @@ static ssize_t chp_measurement_chars_read(struct file *filp,
|
||||||
|
|
||||||
device = container_of(kobj, struct device, kobj);
|
device = container_of(kobj, struct device, kobj);
|
||||||
chp = to_channelpath(device);
|
chp = to_channelpath(device);
|
||||||
if (!chp->cmg_chars)
|
if (chp->cmg == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return memory_read_from_buffer(buf, count, &off,
|
return memory_read_from_buffer(buf, count, &off, &chp->cmg_chars,
|
||||||
chp->cmg_chars, sizeof(struct cmg_chars));
|
sizeof(chp->cmg_chars));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bin_attribute chp_measurement_chars_attr = {
|
static struct bin_attribute chp_measurement_chars_attr = {
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct channel_path {
|
||||||
/* Channel-measurement related stuff: */
|
/* Channel-measurement related stuff: */
|
||||||
int cmg;
|
int cmg;
|
||||||
int shared;
|
int shared;
|
||||||
void *cmg_chars;
|
struct cmg_chars cmg_chars;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return channel_path struct for given chpid. */
|
/* Return channel_path struct for given chpid. */
|
||||||
|
|
|
@ -967,22 +967,19 @@ static void
|
||||||
chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
|
chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
|
||||||
struct cmg_chars *chars)
|
struct cmg_chars *chars)
|
||||||
{
|
{
|
||||||
struct cmg_chars *cmg_chars;
|
|
||||||
int i, mask;
|
int i, mask;
|
||||||
|
|
||||||
cmg_chars = chp->cmg_chars;
|
|
||||||
for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
|
for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
|
||||||
mask = 0x80 >> (i + 3);
|
mask = 0x80 >> (i + 3);
|
||||||
if (cmcv & mask)
|
if (cmcv & mask)
|
||||||
cmg_chars->values[i] = chars->values[i];
|
chp->cmg_chars.values[i] = chars->values[i];
|
||||||
else
|
else
|
||||||
cmg_chars->values[i] = 0;
|
chp->cmg_chars.values[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int chsc_get_channel_measurement_chars(struct channel_path *chp)
|
int chsc_get_channel_measurement_chars(struct channel_path *chp)
|
||||||
{
|
{
|
||||||
struct cmg_chars *cmg_chars;
|
|
||||||
int ccode, ret;
|
int ccode, ret;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -1006,11 +1003,6 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
|
||||||
u32 data[NR_MEASUREMENT_CHARS];
|
u32 data[NR_MEASUREMENT_CHARS];
|
||||||
} __attribute__ ((packed)) *scmc_area;
|
} __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);
|
spin_lock_irq(&chsc_page_lock);
|
||||||
memset(chsc_page, 0, PAGE_SIZE);
|
memset(chsc_page, 0, PAGE_SIZE);
|
||||||
scmc_area = chsc_page;
|
scmc_area = chsc_page;
|
||||||
|
@ -1042,14 +1034,10 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
|
||||||
/* No cmg-dependent data. */
|
/* No cmg-dependent data. */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
chp->cmg_chars = cmg_chars;
|
|
||||||
chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
|
chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
|
||||||
(struct cmg_chars *) &scmc_area->data);
|
(struct cmg_chars *) &scmc_area->data);
|
||||||
out:
|
out:
|
||||||
spin_unlock_irq(&chsc_page_lock);
|
spin_unlock_irq(&chsc_page_lock);
|
||||||
if (!chp->cmg_chars)
|
|
||||||
kfree(cmg_chars);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue