mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 04:36:22 +00:00
/proc implementation moved to seq_*() library. Mostly done by Ming Zhang.
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@57 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+1
-1
@@ -287,7 +287,7 @@ static struct scst_tgt_template tgt_template = {
|
||||
.rdy_to_xfer = mpt_rdy_to_xfer,
|
||||
.on_free_cmd = mpt_on_free_cmd,
|
||||
.task_mgmt_fn_done = mpt_task_mgmt_fn_done,
|
||||
.proc_info = mpt_proc_info,
|
||||
//ToDo: .proc_info = mpt_proc_info,
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <scsi_tgt.h>
|
||||
@@ -2054,36 +2054,40 @@ out:
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
static int qla2x00t_proc_log_entry_read(char *buffer, char **start,
|
||||
off_t offset, int length, int *eof,
|
||||
void *data)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
res = scst_proc_log_entry_read(buffer, start, offset, length, eof,
|
||||
data, trace_flag, NULL);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int qla2x00t_proc_log_entry_write(struct file *file, const char *buf,
|
||||
unsigned long length, void *data)
|
||||
static int q2t_log_info_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
res = scst_proc_log_entry_write(file, buf, length, data,
|
||||
&trace_flag, SCST_DEFAULT_QLA_LOG_FLAGS, NULL);
|
||||
res = scst_proc_log_entry_read(seq, trace_flag, NULL);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int q2t_proc_log_entry_write(struct file *file, const char __user *buf,
|
||||
size_t length, loff_t *off)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
res = scst_proc_log_entry_write(file, buf, length, &trace_flag,
|
||||
SCST_DEFAULT_QLA_LOG_FLAGS, NULL);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static struct scst_proc_data q2t_log_proc_data = {
|
||||
SCST_DEF_RW_SEQ_OP(q2t_proc_log_entry_write)
|
||||
.show = q2t_log_info_show,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int qla2x00t_proc_log_entry_build(struct scst_tgt_template *templ)
|
||||
static int q2t_proc_log_entry_build(struct scst_tgt_template *templ)
|
||||
{
|
||||
int res = 0;
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
@@ -2094,10 +2098,9 @@ static int qla2x00t_proc_log_entry_build(struct scst_tgt_template *templ)
|
||||
|
||||
if (root) {
|
||||
/* create the proc file entry for the device */
|
||||
p = create_proc_read_entry(Q2T_PROC_LOG_ENTRY_NAME,
|
||||
S_IFREG | S_IRUGO | S_IWUSR, root,
|
||||
qla2x00t_proc_log_entry_read,
|
||||
(void *)templ->name);
|
||||
q2t_log_proc_data.data = (void *)templ->name;
|
||||
p = scst_create_proc_entry(root, Q2T_PROC_LOG_ENTRY_NAME,
|
||||
&q2t_log_proc_data);
|
||||
if (p == NULL) {
|
||||
PRINT_ERROR("Not enough memory to register "
|
||||
"target driver %s entry %s in /proc",
|
||||
@@ -2105,7 +2108,6 @@ static int qla2x00t_proc_log_entry_build(struct scst_tgt_template *templ)
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
p->write_proc = qla2x00t_proc_log_entry_write;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -2115,7 +2117,7 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void qla2x00t_proc_log_entry_clean(struct scst_tgt_template *templ)
|
||||
static void q2t_proc_log_entry_clean(struct scst_tgt_template *templ)
|
||||
{
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
struct proc_dir_entry *root;
|
||||
@@ -2131,7 +2133,7 @@ static void qla2x00t_proc_log_entry_clean(struct scst_tgt_template *templ)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __init qla2x00t_init(void)
|
||||
static int __init q2t_init(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
@@ -2154,7 +2156,7 @@ static int __init qla2x00t_init(void)
|
||||
* called via scst_register_target_template()
|
||||
*/
|
||||
|
||||
res = qla2x00t_proc_log_entry_build(&tgt_template);
|
||||
res = q2t_proc_log_entry_build(&tgt_template);
|
||||
if (res < 0) {
|
||||
goto out_unreg_target;
|
||||
}
|
||||
@@ -2169,11 +2171,11 @@ out_unreg_target:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void __exit qla2x00t_exit(void)
|
||||
static void __exit q2t_exit(void)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
qla2x00t_proc_log_entry_clean(&tgt_template);
|
||||
q2t_proc_log_entry_clean(&tgt_template);
|
||||
|
||||
scst_unregister_target_template(&tgt_template);
|
||||
|
||||
@@ -2185,8 +2187,8 @@ static void __exit qla2x00t_exit(void)
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(qla2x00t_init);
|
||||
module_exit(qla2x00t_exit);
|
||||
module_init(q2t_init);
|
||||
module_exit(q2t_exit);
|
||||
|
||||
MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar & Nathaniel Clark");
|
||||
MODULE_DESCRIPTION("Target mode logic for qla2xxx");
|
||||
|
||||
+45
-16
@@ -24,10 +24,15 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#ifdef SCST_HIGHMEM
|
||||
#include <asm/kmap_types.h>
|
||||
#endif
|
||||
#include <../drivers/scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
/* Version numbers, the same as for the kernel */
|
||||
#define SCST_VERSION_CODE 0x000906
|
||||
@@ -694,14 +699,15 @@ struct scst_tgt_template
|
||||
*/
|
||||
int (*report_aen) (int mgmt_fn, const uint8_t *lun, int lun_len);
|
||||
|
||||
/*
|
||||
* This function can be used to export the driver's statistics and
|
||||
* other infos to the world outside the kernel.
|
||||
/*
|
||||
* Those functions can be used to export the driver's statistics and
|
||||
* other infos to the world outside the kernel.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
int (*proc_info) (char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_tgt *tgt, int inout);
|
||||
int (*read_proc) (struct seq_file *seq, struct scst_tgt *tgt);
|
||||
int (*write_proc) (char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_tgt *tgt);
|
||||
|
||||
/*
|
||||
* Name of the template. Must be unique to identify
|
||||
@@ -836,15 +842,15 @@ struct scst_dev_type
|
||||
int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd,
|
||||
struct scst_tgt_dev *tgt_dev);
|
||||
|
||||
/*
|
||||
* This function can be used to export the handler's statistics and
|
||||
* other infos to the world outside the kernel.
|
||||
/*
|
||||
* Those functions can be used to export the handler's statistics and
|
||||
* other infos to the world outside the kernel.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
int (*proc_info) (char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type,
|
||||
int inout);
|
||||
int (*read_proc) (struct seq_file *seq, struct scst_dev_type *dev_type);
|
||||
int (*write_proc) (char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type);
|
||||
|
||||
struct module *module;
|
||||
|
||||
@@ -2149,14 +2155,37 @@ struct scst_proc_log {
|
||||
const char *token;
|
||||
};
|
||||
|
||||
int scst_proc_log_entry_read(char *buffer, char **start,
|
||||
off_t offset, int length, int *eof, void *data,
|
||||
unsigned long log_level, const struct scst_proc_log *tbl);
|
||||
int scst_proc_log_entry_read(struct seq_file *seq, unsigned long log_level,
|
||||
const struct scst_proc_log *tbl);
|
||||
|
||||
int scst_proc_log_entry_write(struct file *file, const char *buf,
|
||||
unsigned long length, void *data, unsigned long *log_level,
|
||||
unsigned long length, unsigned long *log_level,
|
||||
unsigned long default_level, const struct scst_proc_log *tbl);
|
||||
|
||||
/*
|
||||
* helper data structure and function to create proc entry.
|
||||
*/
|
||||
struct scst_proc_data {
|
||||
struct file_operations seq_op;
|
||||
int (*show)(struct seq_file *, void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
int scst_single_seq_open(struct inode *inode, struct file *file);
|
||||
|
||||
struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry * root,
|
||||
const char *name, struct scst_proc_data *pdata);
|
||||
|
||||
#define SCST_DEF_RW_SEQ_OP(x) \
|
||||
.seq_op = { \
|
||||
.owner = THIS_MODULE, \
|
||||
.open = scst_single_seq_open,\
|
||||
.read = seq_read, \
|
||||
.write = x, \
|
||||
.llseek = seq_lseek, \
|
||||
.release = single_release, \
|
||||
},
|
||||
|
||||
/*
|
||||
* Adds and deletes (stops) num SCST's threads. Returns 0 on success,
|
||||
* error code otherwise.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_PID | \
|
||||
@@ -17,28 +18,28 @@
|
||||
#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MINOR)
|
||||
#endif
|
||||
|
||||
static int scst_dev_handler_proc_log_entry_read(char *buffer, char **start,
|
||||
off_t offset, int length, int *eof, void *data)
|
||||
static struct scst_proc_data dev_handler_log_proc_data;
|
||||
|
||||
static int dev_handler_log_info_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
res = scst_proc_log_entry_read(buffer, start, offset, length, eof,
|
||||
data, trace_flag, NULL);
|
||||
res = scst_proc_log_entry_read(seq, trace_flag, NULL);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int scst_dev_handler_proc_log_entry_write(struct file *file,
|
||||
const char *buf, unsigned long length, void *data)
|
||||
static int scst_dev_handler_proc_log_entry_write(struct file *file, const char __user *buf,
|
||||
size_t length, loff_t *off)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
res = scst_proc_log_entry_write(file, buf, length, data,
|
||||
&trace_flag, SCST_DEFAULT_DEV_LOG_FLAGS, NULL);
|
||||
res = scst_proc_log_entry_write(file, buf, length, &trace_flag,
|
||||
SCST_DEFAULT_DEV_LOG_FLAGS, NULL);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -57,10 +58,9 @@ static int scst_dev_handler_build_std_proc(struct scst_dev_type *dev_type)
|
||||
|
||||
if (root) {
|
||||
/* create the proc file entry for the device */
|
||||
p = create_proc_read_entry(DEV_HANDLER_LOG_ENTRY_NAME,
|
||||
S_IFREG | S_IRUGO | S_IWUSR, root,
|
||||
scst_dev_handler_proc_log_entry_read,
|
||||
(void *)dev_type->name);
|
||||
dev_handler_log_proc_data.data = (void *)dev_type->name;
|
||||
p = scst_create_proc_entry(root, DEV_HANDLER_LOG_ENTRY_NAME,
|
||||
&dev_handler_log_proc_data);
|
||||
if (p == NULL) {
|
||||
PRINT_ERROR_PR("Not enough memory to register dev "
|
||||
"handler %s entry %s in /proc",
|
||||
@@ -68,7 +68,6 @@ static int scst_dev_handler_build_std_proc(struct scst_dev_type *dev_type)
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
p->write_proc = scst_dev_handler_proc_log_entry_write;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -93,3 +92,9 @@ static void scst_dev_handler_destroy_std_proc(struct scst_dev_type *dev_type)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
static struct scst_proc_data dev_handler_log_proc_data = {
|
||||
SCST_DEF_RW_SEQ_OP(scst_dev_handler_proc_log_entry_write)
|
||||
.show = dev_handler_log_info_show,
|
||||
};
|
||||
#endif
|
||||
|
||||
+359
-437
@@ -141,12 +141,12 @@ static void fileio_exec_read_toc(struct scst_cmd *cmd);
|
||||
static void fileio_exec_prevent_allow_medium_removal(struct scst_cmd *cmd);
|
||||
static int fileio_fsync(struct scst_fileio_tgt_dev *ftgt_dev,
|
||||
loff_t loff, loff_t len, struct scst_cmd *cmd);
|
||||
static int disk_fileio_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type, int inout);
|
||||
static int cdrom_fileio_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type, int inout);
|
||||
static int fileio_proc_help_read(char *buffer, char **start,off_t offset,
|
||||
int length, int *eof, void *data);
|
||||
static int disk_fileio_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type);
|
||||
static int disk_fileio_write_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type);
|
||||
static int cdrom_fileio_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type);
|
||||
static int cdrom_fileio_write_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type);
|
||||
|
||||
#define DISK_TYPE_FILEIO { \
|
||||
name: DISK_FILEIO_NAME, \
|
||||
@@ -161,7 +161,8 @@ static int fileio_proc_help_read(char *buffer, char **start,off_t offset,
|
||||
parse: disk_fileio_parse, \
|
||||
exec: disk_fileio_exec, \
|
||||
task_mgmt_fn: fileio_task_mgmt_fn, \
|
||||
proc_info: disk_fileio_proc, \
|
||||
read_proc: disk_fileio_read_proc, \
|
||||
write_proc: disk_fileio_write_proc, \
|
||||
}
|
||||
|
||||
#define CDROM_TYPE_FILEIO { \
|
||||
@@ -177,7 +178,8 @@ static int fileio_proc_help_read(char *buffer, char **start,off_t offset,
|
||||
parse: cdrom_fileio_parse, \
|
||||
exec: cdrom_fileio_exec, \
|
||||
task_mgmt_fn: fileio_task_mgmt_fn, \
|
||||
proc_info: cdrom_fileio_proc, \
|
||||
read_proc: cdrom_fileio_read_proc, \
|
||||
write_proc: cdrom_fileio_write_proc,\
|
||||
}
|
||||
|
||||
DECLARE_MUTEX(scst_fileio_mutex);
|
||||
@@ -2262,349 +2264,285 @@ out:
|
||||
return dev;
|
||||
}
|
||||
|
||||
struct fileio_proc_update_struct {
|
||||
int len, plen, pplen;
|
||||
off_t begin, pbegin, ppbegin;
|
||||
off_t pos;
|
||||
};
|
||||
|
||||
static int fileio_proc_update_size(int size, off_t offset, int length,
|
||||
struct fileio_proc_update_struct *p, int is_start)
|
||||
{
|
||||
int res = 0;
|
||||
if (size > 0) {
|
||||
p->len += size;
|
||||
p->pos = p->begin + p->len;
|
||||
if (p->pos <= offset) {
|
||||
p->len = 0;
|
||||
p->begin = p->pos;
|
||||
} else if (p->pos >= offset + length) {
|
||||
res = 1;
|
||||
goto out;
|
||||
} else
|
||||
res = 0;
|
||||
} else {
|
||||
p->begin = p->ppbegin;
|
||||
p->len = p->pplen;
|
||||
res = 1;
|
||||
goto out;
|
||||
}
|
||||
if (is_start) {
|
||||
p->ppbegin = p->pbegin;
|
||||
p->pplen = p->plen;
|
||||
p->pbegin = p->begin;
|
||||
p->plen = p->len;
|
||||
}
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a file in the /proc/DISK_FILEIO_NAME/DISK_FILEIO_NAME is read
|
||||
* or written
|
||||
*/
|
||||
static int disk_fileio_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type, int inout)
|
||||
static int disk_fileio_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type)
|
||||
{
|
||||
int res = 0, action;
|
||||
char *p, *name, *file_name;
|
||||
struct scst_fileio_dev *virt_dev, *vv;
|
||||
int size;
|
||||
struct fileio_proc_update_struct pu;
|
||||
int res = 0;
|
||||
struct scst_fileio_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
memset(&pu, 0, sizeof(pu));
|
||||
|
||||
/* VERY UGLY code. You can rewrite it if you want */
|
||||
|
||||
if (down_interruptible(&scst_fileio_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (inout == 0) { /* read */
|
||||
size = scnprintf(buffer, length, "%-17s %-11s %-11s %-15s %s\n",
|
||||
"Name", "Size(MB)", "Block size", "Options", "File name");
|
||||
if (fileio_proc_update_size(size, offset, length, &pu, 1))
|
||||
goto stop_output;
|
||||
seq_printf(seq, "%-17s %-11s %-11s %-15s %s\n",
|
||||
"Name", "Size(MB)", "Block size", "Options", "File name");
|
||||
|
||||
list_for_each_entry(virt_dev, &disk_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
list_for_each_entry(virt_dev, &disk_fileio_dev_list, fileio_dev_list_entry) {
|
||||
int c;
|
||||
seq_printf(seq, "%-17s %-11d %-12d", virt_dev->name,
|
||||
(uint32_t)(virt_dev->file_size >> 20),
|
||||
virt_dev->block_size);
|
||||
c = 0;
|
||||
if (virt_dev->wt_flag) {
|
||||
seq_printf(seq, "WT ");
|
||||
c += 3;
|
||||
}
|
||||
if (virt_dev->nv_cache) {
|
||||
seq_printf(seq, "NV ");
|
||||
c += 3;
|
||||
}
|
||||
if (virt_dev->rd_only_flag) {
|
||||
seq_printf(seq, "RO ");
|
||||
c += 3;
|
||||
}
|
||||
if (virt_dev->o_direct_flag) {
|
||||
seq_printf(seq, "DR ");
|
||||
c += 3;
|
||||
}
|
||||
if (virt_dev->nullio) {
|
||||
seq_printf(seq, "NIO ");
|
||||
c += 4;
|
||||
}
|
||||
while (c < 16) {
|
||||
seq_printf(seq, " ");
|
||||
c++;
|
||||
}
|
||||
seq_printf(seq, "%s\n", virt_dev->file_name);
|
||||
}
|
||||
up(&scst_fileio_mutex);
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a file in the /proc/DISK_FILEIO_NAME/DISK_FILEIO_NAME is written
|
||||
*/
|
||||
static int disk_fileio_write_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type)
|
||||
{
|
||||
int res = 0, action;
|
||||
char *p, *name, *file_name;
|
||||
struct scst_fileio_dev *virt_dev, *vv;
|
||||
uint32_t block_size = DEF_DISK_BLOCKSIZE;
|
||||
int block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
|
||||
size_t len;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
/* VERY UGLY code. You can rewrite it if you want */
|
||||
|
||||
if (buffer[0] == '\0')
|
||||
goto out;
|
||||
|
||||
if (down_interruptible(&scst_fileio_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = buffer;
|
||||
if (p[strlen(p) - 1] == '\n') {
|
||||
p[strlen(p) - 1] = '\0';
|
||||
}
|
||||
if (!strncmp("close ", p, 6)) {
|
||||
p += 6;
|
||||
action = 0;
|
||||
} else if (!strncmp("open ", p, 5)) {
|
||||
p += 5;
|
||||
action = 2;
|
||||
} else {
|
||||
PRINT_ERROR_PR("Unknown action \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
name = p;
|
||||
while (!isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
if (*name == '\0') {
|
||||
PRINT_ERROR_PR("%s", "Name required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
} else if (strlen(name) >= sizeof(virt_dev->name)) {
|
||||
PRINT_ERROR_PR("Name is too long (max %zd "
|
||||
"characters)", sizeof(virt_dev->name)-1);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
if (action) { /* open */
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &disk_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
{
|
||||
int c;
|
||||
size = scnprintf(buffer + pu.len, length - pu.len,
|
||||
"%-17s %-11d %-12d", virt_dev->name,
|
||||
(uint32_t)(virt_dev->file_size >> 20),
|
||||
virt_dev->block_size);
|
||||
if (fileio_proc_update_size(size, offset, length, &pu,
|
||||
1)) {
|
||||
goto stop_output;
|
||||
}
|
||||
c = 0;
|
||||
if (virt_dev->wt_flag) {
|
||||
size = scnprintf(buffer + pu.len, length - pu.len, "WT");
|
||||
c += size;
|
||||
if (fileio_proc_update_size(size, offset,
|
||||
length, &pu, 0)) {
|
||||
goto stop_output;
|
||||
}
|
||||
}
|
||||
if (virt_dev->nv_cache) {
|
||||
size = scnprintf(buffer + pu.len, length - pu.len,
|
||||
c ? ",NV" : "NV");
|
||||
c += size;
|
||||
if (fileio_proc_update_size(size, offset,
|
||||
length, &pu, 0)) {
|
||||
goto stop_output;
|
||||
}
|
||||
}
|
||||
if (virt_dev->rd_only_flag) {
|
||||
size = scnprintf(buffer + pu.len, length - pu.len,
|
||||
c ? ",RO" : "RO");
|
||||
c += size;
|
||||
if (fileio_proc_update_size(size, offset,
|
||||
length, &pu, 0)) {
|
||||
goto stop_output;
|
||||
}
|
||||
}
|
||||
if (virt_dev->o_direct_flag) {
|
||||
size = scnprintf(buffer + pu.len, length - pu.len,
|
||||
c ? ",DR" : "DR");
|
||||
c += size;
|
||||
if (fileio_proc_update_size(size, offset,
|
||||
length, &pu, 0)) {
|
||||
goto stop_output;
|
||||
}
|
||||
}
|
||||
if (virt_dev->nullio) {
|
||||
size = scnprintf(buffer + pu.len, length - pu.len,
|
||||
c ? ",NIO" : "NIO");
|
||||
c += size;
|
||||
if (fileio_proc_update_size(size, offset,
|
||||
length, &pu, 0)) {
|
||||
goto stop_output;
|
||||
}
|
||||
}
|
||||
while (c < 16) {
|
||||
size = scnprintf(buffer + pu.len, length - pu.len, " ");
|
||||
if (fileio_proc_update_size(size, offset,
|
||||
length, &pu, 0)) {
|
||||
goto stop_output;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
size = scnprintf(buffer + pu.len, length - pu.len, "%s\n",
|
||||
virt_dev->file_name);
|
||||
if (fileio_proc_update_size(size, offset, length, &pu,
|
||||
0)) {
|
||||
goto stop_output;
|
||||
if (strcmp(vv->name, name) == 0) {
|
||||
virt_dev = vv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*eof = 1;
|
||||
goto stop_output;
|
||||
} else { /* write */
|
||||
uint32_t block_size = DEF_DISK_BLOCKSIZE;
|
||||
int block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
|
||||
p = buffer;
|
||||
if (p[strlen(p) - 1] == '\n') {
|
||||
p[strlen(p) - 1] = '\0';
|
||||
}
|
||||
if (!strncmp("close ", p, 6)) {
|
||||
p += 6;
|
||||
action = 0;
|
||||
} else if (!strncmp("open ", p, 5)) {
|
||||
p += 5;
|
||||
action = 2;
|
||||
} else {
|
||||
PRINT_ERROR_PR("Unknown action \"%s\"", p);
|
||||
if (virt_dev) {
|
||||
PRINT_ERROR_PR("Virtual device with name "
|
||||
"%s already exist", name);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
name = p;
|
||||
file_name = p;
|
||||
while (!isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
if (*name == '\0') {
|
||||
PRINT_ERROR_PR("%s", "Name required");
|
||||
if (*file_name == '\0') {
|
||||
PRINT_ERROR_PR("%s", "File name required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
} else if (strlen(name) >= sizeof(virt_dev->name)) {
|
||||
PRINT_ERROR_PR("Name is too long (max %zd "
|
||||
"characters)", sizeof(virt_dev->name)-1);
|
||||
} else if (*file_name != '/') {
|
||||
PRINT_ERROR_PR("File path \"%s\" is not "
|
||||
"absolute", file_name);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
if (action) { /* open */
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &disk_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
{
|
||||
if (strcmp(vv->name, name) == 0) {
|
||||
virt_dev = vv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (virt_dev) {
|
||||
PRINT_ERROR_PR("Virtual device with name "
|
||||
"%s already exist", name);
|
||||
virt_dev = fileio_alloc_dev();
|
||||
if (virt_dev == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s",
|
||||
"Allocation of virt_dev failed");
|
||||
res = -ENOMEM;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
|
||||
if (isdigit(*p)) {
|
||||
char *pp;
|
||||
uint32_t t;
|
||||
block_size = simple_strtoul(p, &pp, 0);
|
||||
p = pp;
|
||||
if ((*p != '\0') && !isspace(*p)) {
|
||||
PRINT_ERROR_PR("Parse error: \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
file_name = p;
|
||||
while (!isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
if (*file_name == '\0') {
|
||||
PRINT_ERROR_PR("%s", "File name required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
} else if (*file_name != '/') {
|
||||
PRINT_ERROR_PR("File path \"%s\" is not "
|
||||
"absolute", file_name);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
virt_dev = fileio_alloc_dev();
|
||||
if (virt_dev == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s",
|
||||
"Allocation of virt_dev failed");
|
||||
res = -ENOMEM;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
|
||||
if (isdigit(*p)) {
|
||||
char *pp;
|
||||
uint32_t t;
|
||||
block_size = simple_strtoul(p, &pp, 0);
|
||||
p = pp;
|
||||
if ((*p != '\0') && !isspace(*p)) {
|
||||
PRINT_ERROR_PR("Parse error: \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
|
||||
t = block_size;
|
||||
block_shift = 0;
|
||||
while(1) {
|
||||
if ((t & 1) != 0)
|
||||
break;
|
||||
t >>= 1;
|
||||
block_shift++;
|
||||
}
|
||||
if (block_shift < 9) {
|
||||
PRINT_ERROR_PR("Wrong block size %d",
|
||||
block_size);
|
||||
res = -EINVAL;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
}
|
||||
virt_dev->block_size = block_size;
|
||||
virt_dev->block_shift = block_shift;
|
||||
|
||||
while (*p != '\0') {
|
||||
if (!strncmp("WRITE_THROUGH", p, 13)) {
|
||||
p += 13;
|
||||
virt_dev->wt_flag = 1;
|
||||
TRACE_DBG("%s", "WRITE_THROUGH");
|
||||
} else if (!strncmp("NV_CACHE", p, 8)) {
|
||||
p += 8;
|
||||
virt_dev->nv_cache = 1;
|
||||
TRACE_DBG("%s", "NON-VOLATILE CACHE");
|
||||
} else if (!strncmp("READ_ONLY", p, 9)) {
|
||||
p += 9;
|
||||
virt_dev->rd_only_flag = 1;
|
||||
TRACE_DBG("%s", "READ_ONLY");
|
||||
} else if (!strncmp("O_DIRECT", p, 8)) {
|
||||
p += 8;
|
||||
#if 0
|
||||
|
||||
virt_dev->o_direct_flag = 1;
|
||||
TRACE_DBG("%s", "O_DIRECT");
|
||||
#else
|
||||
PRINT_INFO_PR("%s flag doesn't currently"
|
||||
" work, ignoring it", "O_DIRECT");
|
||||
#endif
|
||||
} else if (!strncmp("NULLIO", p, 6)) {
|
||||
p += 6;
|
||||
virt_dev->nullio = 1;
|
||||
TRACE_DBG("%s", "NULLIO");
|
||||
} else {
|
||||
PRINT_ERROR_PR("Unknown flag \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
}
|
||||
|
||||
strcpy(virt_dev->name, name);
|
||||
|
||||
pu.len = strlen(file_name) + 1;
|
||||
virt_dev->file_name = kmalloc(pu.len, GFP_KERNEL);
|
||||
if (virt_dev->file_name == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s",
|
||||
"Allocation of file_name failed");
|
||||
res = -ENOMEM;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
strncpy(virt_dev->file_name, file_name, pu.len);
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
|
||||
list_add_tail(&virt_dev->fileio_dev_list_entry,
|
||||
&disk_fileio_dev_list);
|
||||
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&disk_devtype_fileio,
|
||||
virt_dev->name);
|
||||
if (virt_dev->virt_id < 0) {
|
||||
res = virt_dev->virt_id;
|
||||
goto out_free_vpath;
|
||||
}
|
||||
TRACE_DBG("Added virt_dev (name %s, file name %s, "
|
||||
"id %d, block size %d) to "
|
||||
"disk_fileio_dev_list", virt_dev->name,
|
||||
virt_dev->file_name, virt_dev->virt_id,
|
||||
virt_dev->block_size);
|
||||
} else { /* close */
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &disk_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
{
|
||||
if (strcmp(vv->name, name) == 0) {
|
||||
virt_dev = vv;
|
||||
t = block_size;
|
||||
block_shift = 0;
|
||||
while(1) {
|
||||
if ((t & 1) != 0)
|
||||
break;
|
||||
}
|
||||
t >>= 1;
|
||||
block_shift++;
|
||||
}
|
||||
if (virt_dev == NULL) {
|
||||
PRINT_ERROR_PR("Device %s not found", name);
|
||||
if (block_shift < 9) {
|
||||
PRINT_ERROR_PR("Wrong block size %d",
|
||||
block_size);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
scst_unregister_virtual_device(virt_dev->virt_id);
|
||||
PRINT_INFO_PR("Virtual device %s unregistered",
|
||||
virt_dev->name);
|
||||
TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
|
||||
|
||||
list_del(&virt_dev->fileio_dev_list_entry);
|
||||
|
||||
kfree(virt_dev->file_name);
|
||||
kfree(virt_dev);
|
||||
}
|
||||
res = length;
|
||||
virt_dev->block_size = block_size;
|
||||
virt_dev->block_shift = block_shift;
|
||||
|
||||
while (*p != '\0') {
|
||||
if (!strncmp("WRITE_THROUGH", p, 13)) {
|
||||
p += 13;
|
||||
virt_dev->wt_flag = 1;
|
||||
TRACE_DBG("%s", "WRITE_THROUGH");
|
||||
} else if (!strncmp("NV_CACHE", p, 8)) {
|
||||
p += 8;
|
||||
virt_dev->nv_cache = 1;
|
||||
TRACE_DBG("%s", "NON-VOLATILE CACHE");
|
||||
} else if (!strncmp("READ_ONLY", p, 9)) {
|
||||
p += 9;
|
||||
virt_dev->rd_only_flag = 1;
|
||||
TRACE_DBG("%s", "READ_ONLY");
|
||||
} else if (!strncmp("O_DIRECT", p, 8)) {
|
||||
p += 8;
|
||||
#if 0
|
||||
|
||||
virt_dev->o_direct_flag = 1;
|
||||
TRACE_DBG("%s", "O_DIRECT");
|
||||
#else
|
||||
PRINT_INFO_PR("%s flag doesn't currently"
|
||||
" work, ignoring it", "O_DIRECT");
|
||||
#endif
|
||||
} else if (!strncmp("NULLIO", p, 6)) {
|
||||
p += 6;
|
||||
virt_dev->nullio = 1;
|
||||
TRACE_DBG("%s", "NULLIO");
|
||||
} else {
|
||||
PRINT_ERROR_PR("Unknown flag \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
}
|
||||
|
||||
strcpy(virt_dev->name, name);
|
||||
|
||||
len = strlen(file_name) + 1;
|
||||
virt_dev->file_name = kmalloc(len, GFP_KERNEL);
|
||||
if (virt_dev->file_name == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s",
|
||||
"Allocation of file_name failed");
|
||||
res = -ENOMEM;
|
||||
goto out_free_vdev;
|
||||
}
|
||||
strncpy(virt_dev->file_name, file_name, len);
|
||||
|
||||
list_add_tail(&virt_dev->fileio_dev_list_entry,
|
||||
&disk_fileio_dev_list);
|
||||
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&disk_devtype_fileio,
|
||||
virt_dev->name);
|
||||
if (virt_dev->virt_id < 0) {
|
||||
res = virt_dev->virt_id;
|
||||
goto out_free_vpath;
|
||||
}
|
||||
TRACE_DBG("Added virt_dev (name %s, file name %s, "
|
||||
"id %d, block size %d) to "
|
||||
"disk_fileio_dev_list", virt_dev->name,
|
||||
virt_dev->file_name, virt_dev->virt_id,
|
||||
virt_dev->block_size);
|
||||
} else { /* close */
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &disk_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
{
|
||||
if (strcmp(vv->name, name) == 0) {
|
||||
virt_dev = vv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (virt_dev == NULL) {
|
||||
PRINT_ERROR_PR("Device %s not found", name);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
scst_unregister_virtual_device(virt_dev->virt_id);
|
||||
PRINT_INFO_PR("Virtual device %s unregistered",
|
||||
virt_dev->name);
|
||||
TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
|
||||
|
||||
list_del(&virt_dev->fileio_dev_list_entry);
|
||||
|
||||
kfree(virt_dev->file_name);
|
||||
kfree(virt_dev);
|
||||
}
|
||||
res = length;
|
||||
|
||||
out_up:
|
||||
up(&scst_fileio_mutex);
|
||||
@@ -2613,14 +2551,6 @@ out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
stop_output:
|
||||
*start = buffer + (offset - pu.begin);
|
||||
pu.len -= (offset - pu.begin);
|
||||
if (pu.len > length)
|
||||
pu.len = length;
|
||||
res = max(0, pu.len);
|
||||
goto out_up;
|
||||
|
||||
out_free_vpath:
|
||||
list_del(&virt_dev->fileio_dev_list_entry);
|
||||
kfree(virt_dev->file_name);
|
||||
@@ -2630,6 +2560,7 @@ out_free_vdev:
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
|
||||
/* scst_fileio_mutex supposed to be held */
|
||||
static int cdrom_fileio_open(char *p, char *name)
|
||||
{
|
||||
@@ -2640,8 +2571,7 @@ static int cdrom_fileio_open(char *p, char *name)
|
||||
int cdrom_empty;
|
||||
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &cdrom_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
list_for_each_entry(vv, &cdrom_fileio_dev_list, fileio_dev_list_entry)
|
||||
{
|
||||
if (strcmp(vv->name, name) == 0) {
|
||||
virt_dev = vv;
|
||||
@@ -2932,115 +2862,128 @@ out_err_resume:
|
||||
|
||||
/*
|
||||
* Called when a file in the /proc/CDROM_FILEIO_NAME/CDROM_FILEIO_NAME is read
|
||||
* or written
|
||||
*/
|
||||
static int cdrom_fileio_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type, int inout)
|
||||
static int cdrom_fileio_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type)
|
||||
{
|
||||
int res = 0, action;
|
||||
char *p, *name;
|
||||
int res = 0;
|
||||
struct scst_fileio_dev *virt_dev;
|
||||
int size;
|
||||
struct fileio_proc_update_struct pu;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
memset(&pu, 0, sizeof(pu));
|
||||
|
||||
if (down_interruptible(&scst_fileio_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (inout == 0) { /* read */
|
||||
size = scnprintf(buffer, length, "%-17s %-9s %s\n",
|
||||
"Name", "Size(MB)", "File name");
|
||||
if (fileio_proc_update_size(size, offset, length, &pu, 1))
|
||||
goto stop_output;
|
||||
seq_printf(seq, "%-17s %-9s %s\n", "Name", "Size(MB)", "File name");
|
||||
|
||||
list_for_each_entry(virt_dev, &cdrom_fileio_dev_list,
|
||||
fileio_dev_list_entry)
|
||||
{
|
||||
size = scnprintf(buffer + pu.len, length - pu.len,
|
||||
"%-17s %-9d %s\n", virt_dev->name,
|
||||
(uint32_t)(virt_dev->file_size >> 20),
|
||||
virt_dev->file_name);
|
||||
if (fileio_proc_update_size(size, offset, length, &pu,
|
||||
1)) {
|
||||
goto stop_output;
|
||||
}
|
||||
}
|
||||
*eof = 1;
|
||||
goto stop_output;
|
||||
} else { /* write */
|
||||
p = buffer;
|
||||
if (p[strlen(p) - 1] == '\n') {
|
||||
p[strlen(p) - 1] = '\0';
|
||||
}
|
||||
if (!strncmp("close ", p, 6)) {
|
||||
p += 6;
|
||||
action = 0;
|
||||
} else if (!strncmp("change ", p, 5)) {
|
||||
p += 7;
|
||||
action = 1;
|
||||
} else if (!strncmp("open ", p, 5)) {
|
||||
p += 5;
|
||||
action = 2;
|
||||
} else {
|
||||
PRINT_ERROR_PR("Unknown action \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
name = p;
|
||||
while (!isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
if (*name == '\0') {
|
||||
PRINT_ERROR_PR("%s", "Name required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
} else if (strlen(name) >= sizeof(virt_dev->name)) {
|
||||
PRINT_ERROR_PR("Name is too long (max %zd "
|
||||
"characters)", sizeof(virt_dev->name)-1);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
if (action == 2) { /* open */
|
||||
res = cdrom_fileio_open(p, name);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
} else if (action == 1) { /* change */
|
||||
res = cdrom_fileio_change(p, name);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
} else { /* close */
|
||||
res = cdrom_fileio_close(name);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
}
|
||||
res = length;
|
||||
list_for_each_entry(virt_dev, &cdrom_fileio_dev_list,
|
||||
fileio_dev_list_entry) {
|
||||
seq_printf(seq, "%-17s %-9d %s\n", virt_dev->name,
|
||||
(uint32_t)(virt_dev->file_size >> 20),
|
||||
virt_dev->file_name);
|
||||
}
|
||||
|
||||
up(&scst_fileio_mutex);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a file in the /proc/CDROM_FILEIO_NAME/CDROM_FILEIO_NAME is written
|
||||
*/
|
||||
static int cdrom_fileio_write_proc(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, struct scst_dev_type *dev_type)
|
||||
{
|
||||
int res = 0, action;
|
||||
char *p, *name;
|
||||
struct scst_fileio_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (down_interruptible(&scst_fileio_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = buffer;
|
||||
if (p[strlen(p) - 1] == '\n') {
|
||||
p[strlen(p) - 1] = '\0';
|
||||
}
|
||||
if (!strncmp("close ", p, 6)) {
|
||||
p += 6;
|
||||
action = 0;
|
||||
} else if (!strncmp("change ", p, 5)) {
|
||||
p += 7;
|
||||
action = 1;
|
||||
} else if (!strncmp("open ", p, 5)) {
|
||||
p += 5;
|
||||
action = 2;
|
||||
} else {
|
||||
PRINT_ERROR_PR("Unknown action \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
name = p;
|
||||
while (!isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
if (*name == '\0') {
|
||||
PRINT_ERROR_PR("%s", "Name required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
} else if (strlen(name) >= sizeof(virt_dev->name)) {
|
||||
PRINT_ERROR_PR("Name is too long (max %zd "
|
||||
"characters)", sizeof(virt_dev->name)-1);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
if (action == 2) { /* open */
|
||||
res = cdrom_fileio_open(p, name);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
} else if (action == 1) { /* change */
|
||||
res = cdrom_fileio_change(p, name);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
} else { /* close */
|
||||
res = cdrom_fileio_close(name);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
}
|
||||
res = length;
|
||||
|
||||
out_up:
|
||||
up(&scst_fileio_mutex);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
stop_output:
|
||||
*start = buffer + (offset - pu.begin);
|
||||
pu.len -= (offset - pu.begin);
|
||||
if (pu.len > length)
|
||||
pu.len = length;
|
||||
res = pu.len;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
static int fileio_help_info_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
char *s = (char*)seq->private;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
seq_printf(seq, "%s", s);
|
||||
|
||||
TRACE_EXIT();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scst_proc_data fileio_help_proc_data = {
|
||||
SCST_DEF_RW_SEQ_OP(NULL)
|
||||
.show = fileio_help_info_show,
|
||||
};
|
||||
|
||||
static int fileio_proc_help_build(struct scst_dev_type *dev_type)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -3049,23 +2992,17 @@ static int fileio_proc_help_build(struct scst_dev_type *dev_type)
|
||||
TRACE_ENTRY();
|
||||
|
||||
root = scst_proc_get_dev_type_root(dev_type);
|
||||
if (root) {
|
||||
p = create_proc_read_entry(FILEIO_PROC_HELP,
|
||||
S_IFREG | S_IRUGO, root,
|
||||
fileio_proc_help_read,
|
||||
(dev_type->type == TYPE_DISK) ?
|
||||
disk_fileio_proc_help_string :
|
||||
cdrom_fileio_proc_help_string);
|
||||
if (p == NULL) {
|
||||
PRINT_ERROR_PR("Not enough memory to register dev "
|
||||
"handler %s entry %s in /proc",
|
||||
dev_type->name, FILEIO_PROC_HELP);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
fileio_help_proc_data.data = (dev_type->type == TYPE_DISK) ?
|
||||
disk_fileio_proc_help_string :
|
||||
cdrom_fileio_proc_help_string;
|
||||
p = scst_create_proc_entry(root, FILEIO_PROC_HELP, &fileio_help_proc_data);
|
||||
if (p == NULL) {
|
||||
PRINT_ERROR_PR("Not enough memory to register dev "
|
||||
"handler %s entry %s in /proc",
|
||||
dev_type->name, FILEIO_PROC_HELP);
|
||||
res = -ENOMEM;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -3083,21 +3020,6 @@ static void fileio_proc_help_destroy(struct scst_dev_type *dev_type)
|
||||
TRACE_EXIT();
|
||||
}
|
||||
|
||||
static int fileio_proc_help_read(char *buffer, char **start, off_t offset,
|
||||
int length, int *eof, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char *s = (char*)data;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (offset < strlen(s))
|
||||
res = scnprintf(buffer, length, "%s", &s[offset]);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init init_scst_fileio(struct scst_dev_type *devtype)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
@@ -1254,6 +1254,9 @@ EXPORT_SYMBOL(scst_proc_log_entry_read);
|
||||
EXPORT_SYMBOL(scst_proc_log_entry_write);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(scst_create_proc_entry);
|
||||
EXPORT_SYMBOL(scst_single_seq_open);
|
||||
|
||||
EXPORT_SYMBOL(__scst_get_buf);
|
||||
EXPORT_SYMBOL(scst_check_mem);
|
||||
EXPORT_SYMBOL(scst_get);
|
||||
|
||||
+532
-835
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user