-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[S390] hypfs: Move buffer allocation from open to read
Currently the buffer for diagnose data is allocated in the open function of the debugfs file and is released in the close function. This has the drawback that a user (root) can pin that memory by not closing the file. This patch moves the buffer allocation to the read function. The buffer is automatically released after the buffer is copied to userspace. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
- Loading branch information
Michael Holzheu
authored and
Martin Schwidefsky
committed
Jan 5, 2011
1 parent
6432c01
commit 2fcb368
Showing
6 changed files
with
195 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
* Hypervisor filesystem for Linux on s390 - debugfs interface | ||
* | ||
* Copyright (C) IBM Corp. 2010 | ||
* Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> | ||
*/ | ||
|
||
#include <linux/slab.h> | ||
#include "hypfs.h" | ||
|
||
static struct dentry *dbfs_dir; | ||
|
||
static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f) | ||
{ | ||
struct hypfs_dbfs_data *data; | ||
|
||
data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
if (!data) | ||
return NULL; | ||
kref_init(&data->kref); | ||
data->dbfs_file = f; | ||
return data; | ||
} | ||
|
||
static void hypfs_dbfs_data_free(struct kref *kref) | ||
{ | ||
struct hypfs_dbfs_data *data; | ||
|
||
data = container_of(kref, struct hypfs_dbfs_data, kref); | ||
data->dbfs_file->data_free(data->buf_free_ptr); | ||
kfree(data); | ||
} | ||
|
||
static void data_free_delayed(struct work_struct *work) | ||
{ | ||
struct hypfs_dbfs_data *data; | ||
struct hypfs_dbfs_file *df; | ||
|
||
df = container_of(work, struct hypfs_dbfs_file, data_free_work.work); | ||
mutex_lock(&df->lock); | ||
data = df->data; | ||
df->data = NULL; | ||
mutex_unlock(&df->lock); | ||
kref_put(&data->kref, hypfs_dbfs_data_free); | ||
} | ||
|
||
static ssize_t dbfs_read(struct file *file, char __user *buf, | ||
size_t size, loff_t *ppos) | ||
{ | ||
struct hypfs_dbfs_data *data; | ||
struct hypfs_dbfs_file *df; | ||
ssize_t rc; | ||
|
||
if (*ppos != 0) | ||
return 0; | ||
|
||
df = file->f_path.dentry->d_inode->i_private; | ||
mutex_lock(&df->lock); | ||
if (!df->data) { | ||
data = hypfs_dbfs_data_alloc(df); | ||
if (!data) { | ||
mutex_unlock(&df->lock); | ||
return -ENOMEM; | ||
} | ||
rc = df->data_create(&data->buf, &data->buf_free_ptr, | ||
&data->size); | ||
if (rc) { | ||
mutex_unlock(&df->lock); | ||
kfree(data); | ||
return rc; | ||
} | ||
df->data = data; | ||
schedule_delayed_work(&df->data_free_work, HZ); | ||
} | ||
data = df->data; | ||
kref_get(&data->kref); | ||
mutex_unlock(&df->lock); | ||
|
||
rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); | ||
kref_put(&data->kref, hypfs_dbfs_data_free); | ||
return rc; | ||
} | ||
|
||
static const struct file_operations dbfs_ops = { | ||
.read = dbfs_read, | ||
.llseek = no_llseek, | ||
}; | ||
|
||
int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) | ||
{ | ||
df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, | ||
&dbfs_ops); | ||
if (IS_ERR(df->dentry)) | ||
return PTR_ERR(df->dentry); | ||
mutex_init(&df->lock); | ||
INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed); | ||
return 0; | ||
} | ||
|
||
void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) | ||
{ | ||
debugfs_remove(df->dentry); | ||
} | ||
|
||
int hypfs_dbfs_init(void) | ||
{ | ||
dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); | ||
if (IS_ERR(dbfs_dir)) | ||
return PTR_ERR(dbfs_dir); | ||
return 0; | ||
} | ||
|
||
void hypfs_dbfs_exit(void) | ||
{ | ||
debugfs_remove(dbfs_dir); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.