u64 id;
int count;
ssize_t size;
- char data[];
+ char *buf;
};
struct pstore_ftrace_seq_data {
#define REC_SIZE sizeof(struct pstore_ftrace_record)
+static void free_pstore_private(struct pstore_private *private)
+{
+ if (!private)
+ return;
+ kfree(private->buf);
+ kfree(private);
+}
+
static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
{
struct pstore_private *ps = s->private;
{
struct pstore_private *ps = s->private;
struct pstore_ftrace_seq_data *data = v;
- struct pstore_ftrace_record *rec = (void *)(ps->data + data->off);
+ struct pstore_ftrace_record *rec = (void *)(ps->buf + data->off);
seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %pf <- %pF\n",
pstore_ftrace_decode_cpu(rec),
if (ps->type == PSTORE_TYPE_FTRACE)
return seq_read(file, userbuf, count, ppos);
- return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size);
+ return simple_read_from_buffer(userbuf, count, ppos, ps->buf, ps->size);
}
static int pstore_file_open(struct inode *inode, struct file *file)
spin_lock_irqsave(&allpstore_lock, flags);
list_del(&p->list);
spin_unlock_irqrestore(&allpstore_lock, flags);
- kfree(p);
+ free_pstore_private(p);
}
}
goto fail;
inode->i_mode = S_IFREG | 0444;
inode->i_fop = &pstore_file_operations;
- private = kmalloc(sizeof *private + size, GFP_KERNEL);
+ private = kzalloc(sizeof(*private), GFP_KERNEL);
if (!private)
goto fail_alloc;
private->type = record->type;
if (!dentry)
goto fail_lockedalloc;
- memcpy(private->data, record->buf, size);
+ private->buf = record->buf;
inode->i_size = private->size = size;
inode->i_private = private;
fail_lockedalloc:
inode_unlock(d_inode(root));
- kfree(private);
+ free_pstore_private(private);
fail_alloc:
iput(inode);
if (psi->open && psi->open(psi))
goto out;
+ /*
+ * Backend callback read() allocates record.buf. decompress_record()
+ * may reallocate record.buf. On success, pstore_mkfile() will keep
+ * the record.buf, so free it only on failure.
+ */
while ((record.size = psi->read(&record)) > 0) {
decompress_record(&record);
rc = pstore_mkfile(&record);
+ if (rc) {
+ /* pstore_mkfile() did not take buf, so free it. */
+ kfree(record.buf);
+ if (rc != -EEXIST || !quiet)
+ failed++;
+ }
- if (rc && (rc != -EEXIST || !quiet))
- failed++;
-
- kfree(record.buf);
+ /* Reset for next record. */
memset(&record, 0, sizeof(record));
record.psi = psi;
}