From: <vl...@us...> - 2006-12-14 17:08:54
|
Revision: 57 http://svn.sourceforge.net/scst/?rev=57&view=rev Author: vlnb Date: 2006-12-14 09:08:46 -0800 (Thu, 14 Dec 2006) Log Message: ----------- /proc implementation moved to seq_*() library. Mostly done by Ming Zhang. Modified Paths: -------------- trunk/mpt/mpt_scst.c trunk/qla2x00t/qla2x00-target/qla2x00t.c trunk/scst/include/scsi_tgt.h trunk/scst/src/dev_handlers/scst_dev_handler.h trunk/scst/src/dev_handlers/scst_fileio.c trunk/scst/src/scst.c trunk/scst/src/scst_proc.c Modified: trunk/mpt/mpt_scst.c =================================================================== --- trunk/mpt/mpt_scst.c 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/mpt/mpt_scst.c 2006-12-14 17:08:46 UTC (rev 57) @@ -287,7 +287,7 @@ .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 Modified: trunk/qla2x00t/qla2x00-target/qla2x00t.c =================================================================== --- trunk/qla2x00t/qla2x00-target/qla2x00t.c 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/qla2x00t/qla2x00-target/qla2x00t.c 2006-12-14 17:08:46 UTC (rev 57) @@ -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 @@ #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) +static int q2t_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 qla2x00t_proc_log_entry_write(struct file *file, const char *buf, - unsigned long length, void *data) +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, data, - &trace_flag, SCST_DEFAULT_QLA_LOG_FLAGS, NULL); + 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 @@ 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 @@ res = -ENOMEM; goto out; } - p->write_proc = qla2x00t_proc_log_entry_write; } out: @@ -2115,7 +2117,7 @@ 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 @@ #endif } -static int __init qla2x00t_init(void) +static int __init q2t_init(void) { int res = 0; @@ -2154,7 +2156,7 @@ * 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 @@ 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 @@ 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"); Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/scst/include/scsi_tgt.h 2006-12-14 17:08:46 UTC (rev 57) @@ -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 @@ */ 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 @@ 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,15 +2155,38 @@ 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. */ Modified: trunk/scst/src/dev_handlers/scst_dev_handler.h =================================================================== --- trunk/scst/src/dev_handlers/scst_dev_handler.h 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/scst/src/dev_handlers/scst_dev_handler.h 2006-12-14 17:08:46 UTC (rev 57) @@ -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 @@ 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 @@ res = -ENOMEM; goto out; } - p->write_proc = scst_dev_handler_proc_log_entry_write; } out: @@ -93,3 +92,9 @@ #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 Modified: trunk/scst/src/dev_handlers/scst_fileio.c =================================================================== --- trunk/scst/src/dev_handlers/scst_fileio.c 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/scst/src/dev_handlers/scst_fileio.c 2006-12-14 17:08:46 UTC (rev 57) @@ -141,12 +141,12 @@ 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 @@ 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 @@ 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 @@ 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) +/* + * Called when a file in the /proc/DISK_FILEIO_NAME/DISK_FILEIO_NAME is read + */ +static int disk_fileio_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type) { 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; + struct scst_fileio_dev *virt_dev; + + TRACE_ENTRY(); + + if (down_interruptible(&scst_fileio_mutex) != 0) { + res = -EINTR; goto out; } - if (is_start) { - p->ppbegin = p->pbegin; - p->pplen = p->plen; - p->pbegin = p->begin; - p->plen = p->len; + + 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) { + 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 read - * or written + * Called when a file in the /proc/DISK_FILEIO_NAME/DISK_FILEIO_NAME is 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_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; - int size; - struct fileio_proc_update_struct pu; + uint32_t block_size = DEF_DISK_BLOCKSIZE; + int block_shift = DEF_DISK_BLOCKSIZE_SHIFT; + size_t len; TRACE_ENTRY(); - - memset(&pu, 0, sizeof(pu)); /* 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; } - - 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; - list_for_each_entry(virt_dev, &disk_fileio_dev_list, - fileio_dev_list_entry) + 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; + if (strcmp(vv->name, name) == 0) { + virt_dev = vv; + break; } - 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; - } } - *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; + goto out_free_vdev; } - 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"); + + 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_up; - } else if (*file_name != '/') { - PRINT_ERROR_PR("File path \"%s\" is not " - "absolute", file_name); + 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_up; + goto out_free_vdev; } - - 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++; + } + + strcpy(virt_dev->name, name); - 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++; + 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); - 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); + list_add_tail(&virt_dev->fileio_dev_list_entry, + &disk_fileio_dev_list); - 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; + 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; } - strncpy(virt_dev->file_name, file_name, pu.len); + } + 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_add_tail(&virt_dev->fileio_dev_list_entry, - &disk_fileio_dev_list); + list_del(&virt_dev->fileio_dev_list_entry); - 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; + kfree(virt_dev->file_name); + kfree(virt_dev); } + res = length; out_up: up(&scst_fileio_mutex); @@ -2613,14 +2551,6 @@ 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 @@ goto out_up; } + /* scst_fileio_mutex supposed to be held */ static int cdrom_fileio_open(char *p, char *name) { @@ -2640,8 +2571,7 @@ 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,98 +2862,102 @@ /* * 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; + struct scst_fileio_dev *virt_dev; + + TRACE_ENTRY(); + + if (down_interruptible(&scst_fileio_mutex) != 0) { + res = -EINTR; + goto out; + } + + 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) { + 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; - 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; + 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; + } - 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; + } - 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; + if (action == 2) { /* open */ + res = cdrom_fileio_open(p, name); + if (res != 0) 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; + } else if (action == 1) { /* change */ + res = cdrom_fileio_change(p, name); + if (res != 0) 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; + } else { /* close */ + res = cdrom_fileio_close(name); + if (res != 0) + goto out_up; } + res = length; out_up: up(&scst_fileio_mutex); @@ -3031,16 +2965,25 @@ 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 @@ 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 @@ 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; Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/scst/src/scst.c 2006-12-14 17:08:46 UTC (rev 57) @@ -1254,6 +1254,9 @@ 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); Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2006-12-14 16:22:29 UTC (rev 56) +++ trunk/scst/src/scst_proc.c 2006-12-14 17:08:46 UTC (rev 57) @@ -28,56 +28,32 @@ #include <asm/string.h> #include <asm/uaccess.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include "scst_debug.h" #include "scsi_tgt.h" #include "scst_mem.h" #include "scst_priv.h" -static int scst_scsi_tgt_proc_info(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data); -static int scst_proc_scsi_tgt_gen_write(struct file *file, - const char *buf, - unsigned long length, void *data); -static int scst_proc_version_read(char *buffer, char **start,off_t offset, - int length, int *eof, void *data); -static int scst_proc_sessions_read(char *buffer, char **start, off_t offset, - int length, int *eof, void *data); -static int scst_proc_help_read(char *buffer, char **start,off_t offset, - int length, int *eof, void *data); -static int scst_proc_threads_read(char *buffer, char **start,off_t offset, - int length, int *eof, void *data); -static int scst_proc_threads_write(struct file *file, const char *buf, - unsigned long length, void *data); -static int scst_proc_scsi_tgt_read(char *buffer, char **start, off_t offset, - int length, int *eof, void *data); -static int scst_proc_scsi_tgt_write(struct file *file, const char *buf, - unsigned long count, void *data); -static int scst_proc_scsi_dev_handler_read(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data); -static int scst_proc_scsi_dev_handler_write(struct file *file, const char *buf, - unsigned long count, void *data); -static int scst_proc_scsi_dev_handler_type_read(char *buffer, char **start, - off_t offset, int length, - int *eof, void *data); static int scst_proc_init_groups(void); static void scst_proc_cleanup_groups(void); static int scst_proc_assign_handler(char *buf); static int scst_proc_group_add(const char *p); -static int scst_proc_groups_devices_read(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data); -static int scst_proc_groups_devices_write(struct file *file, const char *buf, - unsigned long length, void *data); -static int scst_proc_groups_names_read(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data); -static int scst_proc_groups_names_write(struct file *file, const char *buf, - unsigned long length, void *data); static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc); +static struct scst_proc_data scst_version_proc_data; +static struct scst_proc_data scst_help_proc_data; +static struct scst_proc_data scst_sgv_proc_data; +static struct scst_proc_data scst_groups_names_proc_data; +static struct scst_proc_data scst_groups_devices_proc_data; +static struct scst_proc_data scst_sessions_proc_data; +static struct scst_proc_data scst_dev_handler_type_proc_data; +static struct scst_proc_data scst_log_proc_data; +static struct scst_proc_data scst_tgt_proc_data; +static struct scst_proc_data scst_threads_proc_data; +static struct scst_proc_data scst_scsi_tgt_proc_data; +static struct scst_proc_data scst_dev_handler_proc_data; + /* * Must be less than 4K page size, since our output routines * use some slack for overruns @@ -217,90 +193,10 @@ #endif /* CONFIG_PPC */ -int scst_proc_read_tlb(const struct scst_proc_log *tbl, char *buffer, - int length, off_t offset, unsigned long log_level, int *first, - int *size, int *len, off_t *begin, off_t *pos) -{ - const struct scst_proc_log *t = tbl; - int res = 0; - - while (t->token) { - if (log_level & t->val) { - *size = scnprintf(buffer + *len, length - *len, - "%s%s", *first ? "" : " | ", t->token); - *first = 0; - if (*size > 0) { - *len += *size; - *pos = *begin + *len; - if (*pos <= offset) { - *len = 0; - *begin = *pos; - } else if (*pos >= offset + length) - goto out_end; - } else - goto out_end; - } - t++; - } -out: - return res; - -out_end: - res = 1; - goto out; -} - #if defined(DEBUG) || defined(TRACING) -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 res = 0, first = 1; - int size, len = 0; - off_t begin = 0, pos = 0; - - TRACE_ENTRY(); - - TRACE_DBG("offset: %d, length %d", (int) offset, length); - - if (scst_proc_read_tlb(scst_proc_trace_tbl, buffer, length, offset, - log_level, &first, &size, &len, &begin, &pos)) - goto stop_output; - - if (tbl) { - TRACE_DBG("Reading private tlb, offset: %d, length %d", - (int) offset, length); - if (scst_proc_read_tlb(tbl, buffer, length, offset, - log_level, &first, &size, &len, &begin, &pos)) - goto stop_output; - } - - size = scnprintf(buffer + len, length - len, "%s\n", first ? "none" : ""); - if (size > 0) { - len += size; - pos = begin + len; - if (pos <= offset) { - len = 0; - begin = pos; - } else if (pos >= offset + length) - goto stop_output; - } else - goto stop_output; - -stop_output: - *start = buffer + (offset - begin); - len -= (offset - begin); - if (len > length) - len = length; - res = max(0, len); - TRACE_EXIT_RES(res); - return res; -} - 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) { int res = length; @@ -308,6 +204,7 @@ unsigned long level = 0, oldlevel; char *buffer, *p, *e; const struct scst_proc_log *t; + char *data = (char *)PDE(file->f_dentry->d_inode)->data; TRACE_ENTRY(); @@ -452,44 +349,19 @@ return res; } -static int scst_scsi_tgt_proc_info_log(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data) +static int scst_proc_scsi_tgt_gen_write_log(struct file *file, const char __user *buf, + size_t length, loff_t *off) { int res; TRACE_ENTRY(); - if (down_interruptible(&scst_proc_mutex) != 0) { res = -EINTR; goto out; } - res = scst_proc_log_entry_read(buffer, start, offset, length, eof, - data, trace_flag, scst_proc_local_trace_tbl); - - up(&scst_proc_mutex); - -out: - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_scsi_tgt_gen_write_log(struct file *file, - const char *buf, - unsigned long length, void *data) -{ - int res; - - TRACE_ENTRY(); - - if (down_interruptible(&scst_proc_mutex) != 0) { - res = -EINTR; - goto out; - } - - res = scst_proc_log_entry_write(file, buf, length, data, + res = scst_proc_log_entry_write(file, buf, length, &trace_flag, SCST_DEFAULT_LOG_FLAGS, scst_proc_local_trace_tbl); up(&scst_proc_mutex); @@ -501,7 +373,7 @@ #endif /* defined(DEBUG) || defined(TRACING) */ -static int scst_proc_init_module_log(void) +static int __init scst_proc_init_module_log(void) { int res = 0; #if defined(DEBUG) || defined(TRACING) @@ -509,14 +381,10 @@ TRACE_ENTRY(); - generic = create_proc_read_entry(SCST_PROC_LOG_ENTRY_NAME, - S_IFREG | S_IRUGO | S_IWUSR, - scst_proc_scsi_tgt, - scst_scsi_tgt_proc_info_log, - (void *)"scsi_tgt"); - if (generic) { - generic->write_proc = scst_proc_scsi_tgt_gen_write_log; - } else { + generic = scst_create_proc_entry(scst_proc_scsi_tgt, + SCST_PROC_LOG_ENTRY_NAME, + &scst_log_proc_data); + if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_LOG_ENTRY_NAME); res = -ENOMEM; @@ -527,7 +395,7 @@ return res; } -static void scst_proc_cleanup_module_log(void) +static void __exit scst_proc_cleanup_module_log(void) { #if defined(DEBUG) || defined(TRACING) TRACE_ENTRY(); @@ -553,14 +421,11 @@ goto out; } - generic = create_proc_read_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME, - S_IFREG | S_IRUGO | S_IWUSR, - acg->acg_proc_root, - scst_proc_groups_devices_read, - (void *)acg); - if (generic) { - generic->write_proc = scst_proc_groups_devices_write; - } else { + scst_groups_devices_proc_data.data = acg; + generic = scst_create_proc_entry(acg->acg_proc_root, + SCST_PROC_GROUPS_DEVICES_ENTRY_NAME, + &scst_groups_devices_proc_data); + if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_GROUPS_ENTRY_NAME, @@ -569,14 +434,11 @@ goto out_remove; } - generic = create_proc_read_entry(SCST_PROC_GROUPS_USERS_ENTRY_NAME, - S_IFREG | S_IRUGO | S_IWUSR, - acg->acg_proc_root, - scst_proc_groups_names_read, - (void *)acg); - if (generic) { - generic->write_proc = scst_proc_groups_names_write; - } else { + scst_groups_names_proc_data.data = acg; + generic = scst_create_proc_entry(acg->acg_proc_root, + SCST_PROC_GROUPS_USERS_ENTRY_NAME, + &scst_groups_names_proc_data); + if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_GROUPS_ENTRY_NAME, @@ -674,7 +536,7 @@ return res; } -static int scst_proc_init_groups(void) +static int __init scst_proc_init_groups(void) { int res = 0; @@ -707,7 +569,7 @@ goto out; } -static void scst_proc_cleanup_groups(void) +static void __exit scst_proc_cleanup_groups(void) { struct scst_acg *acg_tmp, *acg; @@ -728,133 +590,14 @@ TRACE_EXIT(); } -struct scst_proc_update_struct { - int len, plen, pplen; - off_t begin, pbegin, ppbegin; - off_t pos; -}; - -static int scst_proc_update_size(int size, off_t offset, int length, - struct scst_proc_update_struct *p) +static int __init scst_proc_init_sgv(void) { 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; - } - p->ppbegin = p->pbegin; - p->pplen = p->plen; - p->pbegin = p->begin; - p->plen = p->len; -out: - return res; -} - -static int scst_proc_sgv_read_1(char *buffer, off_t offset, int length, - struct scst_proc_update_struct *p, - const struct sgv_pool *pool, const char *name) -{ - int i, size; - - size = scnprintf(buffer + p->len, length - p->len, "\n%-20s %-11d %-11d\n", - name, atomic_read(&pool->acc.hit_alloc), - atomic_read(&pool->acc.total_alloc)); - if (scst_proc_update_size(size, offset, length, p)) - return 1; - - for(i = 0; i < SGV_POOL_ELEMENTS; i++) { - size = scnprintf(buffer + p->len, length - p->len, - " %-18s %-11d %-11d\n", pool->cache_names[i], - atomic_read(&pool->cache_acc[i].hit_alloc), - atomic_read(&pool->cache_acc[i].total_alloc)); - if (scst_proc_update_size(size, offset, length, p)) - return 1; - } - return 0; -} - -static int scst_proc_sgv_read(char *buffer, char **start, - off_t offset, int length, int *eof, void *data) -{ - int res = 0; - int size; - struct scst_proc_update_struct st; - - TRACE_ENTRY(); - - TRACE_DBG("offset: %d, length %d", (int) offset, length); - - memset(&st, 0, sizeof(st)); - - size = scnprintf(buffer + st.len, length - st.len, "%-20s %-11s %-11s", - "Name", "Hit", "Total"); - if (scst_proc_update_size(size, offset, length, &st)) - goto stop_output; - - if (scst_proc_sgv_read_1(buffer, offset, length, &st, &scst_sgv.norm, - "sgv")) - goto stop_output; - - if (scst_proc_sgv_read_1(buffer, offset, length, &st, - &scst_sgv.norm_clust, "sgv-clust")) - goto stop_output; - - if (scst_proc_sgv_read_1(buffer, offset, length, &st, - &scst_sgv.dma, "sgv-dma")) - goto stop_output; - -#ifdef SCST_HIGHMEM - if (scst_proc_sgv_read_1(buffer, offset, length, &st, - &scst_sgv.highmem, "sgv-highmem")) - goto stop_output; - -#endif - - size = scnprintf(buffer + st.len, length - st.len, "\n%-32s %-11d\n", - "big", atomic_read(&sgv_big_total_alloc)); - if (scst_proc_update_size(size, offset, length, &st)) - goto stop_output; - - size = scnprintf(buffer + st.len, length - st.len, "\n%-32s %-11d\n", - "other", atomic_read(&sgv_other_total_alloc)); - if (scst_proc_update_size(size, offset, length, &st)) - goto stop_output; - - *eof = 1; - -stop_output: - *start = buffer + (offset - st.begin); - st.len -= (offset - st.begin); - if (st.len > length) - st.len = length; - res = max(0, st.len); - - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_init_sgv(void) -{ - int res = 0; struct proc_dir_entry *pr; TRACE_ENTRY(); - pr = create_proc_read_entry("sgv", S_IFREG | S_IRUGO, - scst_proc_scsi_tgt, scst_proc_sgv_read, NULL); + pr = scst_create_proc_entry(scst_proc_scsi_tgt, "sgv", &scst_sgv_proc_data); if (pr == NULL) { PRINT_ERROR_PR("%s", "cannot create sgv /proc entry"); res = -ENOMEM; @@ -864,14 +607,14 @@ return res; } -static void scst_proc_cleanup_sgv(void) +static void __exit scst_proc_cleanup_sgv(void) { TRACE_ENTRY(); remove_proc_entry("sgv", scst_proc_scsi_tgt); TRACE_EXIT(); } -int scst_proc_init_module(void) +int __init scst_proc_init_module(void) { int res = 0; struct proc_dir_entry *generic; @@ -884,57 +627,47 @@ goto out_nomem; } - generic = create_proc_read_entry(SCST_PROC_ENTRY_NAME, - S_IFREG | S_IRUGO | S_IWUSR, - scst_proc_scsi_tgt, - scst_scsi_tgt_proc_info, NULL); + generic = scst_create_proc_entry(scst_proc_scsi_tgt, + SCST_PROC_ENTRY_NAME, + &scst_tgt_proc_data); if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_ENTRY_NAME); goto out_remove; } - generic->write_proc = scst_proc_scsi_tgt_gen_write; - generic = create_proc_read_entry(SCST_PROC_VERSION_NAME, - S_IFREG | S_IRUGO, - scst_proc_scsi_tgt, - scst_proc_version_read, NULL); + generic = scst_create_proc_entry(scst_proc_scsi_tgt, SCST_PROC_VERSION_NAME, + &scst_version_proc_data); if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_VERSION_NAME); goto out_remove1; } - generic = create_proc_read_entry(SCST_PROC_SESSIONS_NAME, - S_IFREG | S_IRUGO, - scst_proc_scsi_tgt, - scst_proc_sessions_read, NULL); + generic = scst_create_proc_entry(scst_proc_scsi_tgt, SCST_PROC_SESSIONS_NAME, + &scst_sessions_proc_data); if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_SESSIONS_NAME); goto out_remove2; } - generic = create_proc_read_entry(SCST_PROC_HELP_NAME, - S_IFREG | S_IRUGO, - scst_proc_scsi_tgt, - scst_proc_help_read, NULL); + generic = scst_create_proc_entry(scst_proc_scsi_tgt, SCST_PROC_HELP_NAME, + &scst_help_proc_data); if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_HELP_NAME); goto out_remove3; } - generic = create_proc_read_entry(SCST_PROC_THREADS_NAME, - S_IFREG | S_IRUGO | S_IWUSR, - scst_proc_scsi_tgt, - scst_proc_threads_read, NULL); + generic = scst_create_proc_entry(scst_proc_scsi_tgt, + SCST_PROC_THREADS_NAME, + &scst_threads_proc_data); if (!generic) { PRINT_ERROR_PR("cannot init /proc/%s/%s", SCST_PROC_ENTRY_NAME, SCST_PROC_THREADS_NAME); goto out_remove4; } - generic->write_proc = scst_proc_threads_write; if (scst_proc_init_module_log() < 0) { goto out_remove5; @@ -981,7 +714,7 @@ goto out; } -void scst_proc_cleanup_module(void) +void __exit scst_proc_cleanup_module(void) { TRACE_ENTRY(); @@ -999,188 +732,12 @@ TRACE_EXIT(); } -static int scst_scsi_tgt_proc_info(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data) +static int scst_proc_threads_write(struct file *file, const char __user *buf, + size_t length, loff_t *off) { - int res = 0; - int size, len = 0, plen, pplen; - off_t begin = 0, pos = 0, pbegin, ppbegin; - struct scst_device *dev; - - TRACE_ENTRY(); - -//TRACE(TRACE_SPECIAL, "offset=%ld, length=%d", offset, length); - - if (down_interruptible(&scst_mutex) != 0) { - res = -EINTR; - goto out; - } - - size = scnprintf(buffer + len, length - len, "%-60s%s\n", - "Device (host:ch:id:lun or name)", - "Device handler"); - -//TRACE(TRACE_SPECIAL, "size=%d, pos=%ld, begin=%ld, len=%d, buf %s", -// size, pos, begin, len, buffer+len); - - if (size > 0) { - len += size; - pos = begin + len; - if (pos <= offset) { - len = 0; - begin = pos; - } else if (pos >= offset + length) - goto stop_output; - } else - goto stop_output; - - ppbegin = pbegin = begin; - pplen = plen = len; - list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { - if (dev->virt_id == 0) { - char conv[12]; - size = scnprintf(buffer + len, length - len, - "%d:%d:%d:", - dev->scsi_dev->host->host_no, - dev->scsi_dev->channel, - dev->scsi_dev->id); - sprintf(conv, "%%-%dd%%s\n", 60-size); - size += scnprintf(buffer + len + size, length - len - size, - conv, dev->scsi_dev->lun, - dev->handler ? dev->handler->name : "-"); - } else { - size = scnprintf(buffer + len, length - len, - "%-60s%s\n", - dev->virt_name, dev->handler->name); - } - -//printk("size=%d, pbegin=%ld, plen=%d, ppbegin=%ld, pplen=%d, buf %s", -// size, pbegin, plen, ppbegin, pplen, buffer+len); - - if (size > 0) { - len += size; - pos = begin + len; - if (pos <= offset) { - len = 0; - begin = pos; - } -//TRACE(TRACE_SPECIAL, "pos=%ld, begin=%ld, len=%d", pos, begin, len); - if (pos >= offset + length) - goto stop_output; - } else { - begin = ppbegin; - len = pplen; - goto stop_output; - } - ppbegin = pbegin; - pplen = plen; - pbegin = begin; - plen = len; - } - - *eof = 1; - -stop_output: - *start = buffer + (offset - begin); - len -= (offset - begin); - if (len > length) - len = length; - res = max(0, len); - -//TRACE(TRACE_SPECIAL, "res=%d, start=%ld, len=%d, begin=%ld, eof=%d", res, offset-begin, len, begin, *eof); - - up(&scst_mutex); - -out: - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_version_read(char *buffer, char **start,off_t offset, - int length, int *eof, void *data) -{ - int res; - - TRACE_ENTRY(); - - res = scnprintf(buffer, length, "%s\n", SCST_VERSION_STRING); - -#ifdef STRICT_SERIALIZING - if (res < length) - res += scnprintf(&buffer[res], length-res, "Strict " - "serializing enabled\n"); -#endif - -#ifdef EXTRACHECKS - if (res < length) - res += scnprintf(&buffer[res], length-res, "EXTRACHECKS\n"); -#endif - -#ifdef TRACING - if (res < length) - res += scnprintf(&buffer[res], length-res, "TRACING\n"); -#endif - -#ifdef DEBUG - if (res < length) - res += scnprintf(&buffer[res], length-res, "DEBUG\n"); -#endif - -#ifdef DEBUG_TM - if (res < length) - res += scnprintf(&buffer[res], length-res, "DEBUG_TM\n"); -#endif - -#ifdef DEBUG_RETRY - if (res < length) - res += scnprintf(&buffer[res], length-res, "DEBUG_RETRY\n"); -#endif - -#ifdef DEBUG_OOM - if (res < length) - res += scnprintf(&buffer[res], length-res, "DEBUG_OOM\n"); -#endif - - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_help_read(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) -{ - int res; - - TRACE_ENTRY(); - - res = scnprintf(buffer, length, "%s", scst_proc_help_string); - - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_threads_read(char *buffer, char **start,off_t offset, - int length, int *eof, void *data) -{ - int res; - - TRACE_ENTRY(); - - /* 2 mgmt threads */ - res = scnprintf(buffer, length, "%d\n", - atomic_read(&scst_threads_count) - 2); - - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_threads_write(struct file *file, const char *buf, - unsigned long length, void *data) -{ int res = length; int oldtn, newtn, delta; char *buffer; - TRACE_ENTRY(); @@ -1282,13 +839,13 @@ TRACE_ENTRY(); - if (vtt->tgtt->proc_info) { + if (vtt->tgtt->read_proc || vtt->tgtt->write_proc) { /* create the proc file entry for the device */ scnprintf(name, sizeof(name), "%d", vtt->tgtt->proc_dev_num); - p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, - vtt->tgtt->proc_tgt_root, - scst_proc_scsi_tgt_read, - (void *)vtt); + scst_scsi_tgt_proc_data.data = (void*)vtt; + p = scst_create_proc_entry(vtt->tgtt->proc_tgt_root, + name, + &scst_scsi_tgt_proc_data); if (p == NULL) { PRINT_ERROR_PR("Not enough memory to register SCSI " "target entry %s in /proc/%s/%s", name, @@ -1296,7 +853,6 @@ res = -ENOMEM; goto out; } - p->write_proc = scst_proc_scsi_tgt_write; vtt->proc_num = vtt->tgtt->proc_dev_num; vtt->tgtt->proc_dev_num++; } @@ -1312,7 +868,7 @@ TRACE_ENTRY(); - if (vtt->tgtt->proc_info) { + if (vtt->tgtt->read_proc || vtt->tgtt->write_proc) { scnprintf(name, sizeof(name), "%d", vtt->proc_num); remove_proc_entry(name, vtt->tgtt->proc_tgt_root); } @@ -1321,39 +877,10 @@ return; } -static int scst_proc_scsi_tgt_read(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data) +static int scst_proc_scsi_tgt_write(struct file *file, const char __user *buf, + size_t length, loff_t *off) { - struct scst_tgt *vtt = data; - int res = 0; - - TRACE_ENTRY(); - - TRACE_DBG("offset: %d, length %d, id: %d", - (int) offset, length, vtt->proc_num); - - if (down_interruptible(&scst_proc_mutex) != 0) { - res = -EINTR; - goto out; - } - - if (vtt->tgtt->proc_info) { - res = vtt->tgtt->proc_info(buffer, start, offset, length, eof, - vtt, 0); - } - - up(&scst_proc_mutex); - -out: - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_scsi_tgt_write(struct file *file, const char *buf, - unsigned long length, void *data) -{ - struct scst_tgt *vtt = data; + struct scst_tgt *vtt = (struct scst_tgt *)PDE(file->f_dentry->d_inode)->data; ssize_t res = 0; char *buffer; char *start; @@ -1361,7 +888,7 @@ TRACE_ENTRY(); - if (vtt->tgtt->proc_info == NULL) { + if (vtt->tgtt->write_proc == NULL) { res = -ENOSYS; goto out; } @@ -1397,7 +924,7 @@ goto out_free; } - res = vtt->tgtt->proc_info(buffer, &start, 0, length, &eof, vtt, 1); + res = vtt->tgtt->write_proc(buffer, &start, 0, length, &eof, vtt); up(&scst_proc_mutex); @@ -1427,11 +954,10 @@ goto out_nomem; } - p = create_proc_read_entry(SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME, - S_IFREG | S_IRUGO, - dev_type->proc_dev_type_root, - scst_proc_scsi_dev_handler_type_read, - (void *)dev_type); + scst_dev_handler_type_proc_data.data = dev_type; + p = scst_create_proc_entry(dev_type->proc_dev_type_root, + SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME, + &scst_dev_handler_type_proc_data); if (p == NULL) { PRINT_ERROR_PR("Not enough memory to register dev " "handler entry %s in /proc/%s/%s", @@ -1440,20 +966,18 @@ goto out_remove; } - if (dev_type->proc_info) { + if (dev_type->read_proc || dev_type->write_proc) { /* create the proc file entry for the dev type handler */ - p = create_proc_read_entry(dev_type->name, - S_IFREG | S_IRUGO | S_IWUSR, - dev_type->proc_dev_type_root, - scst_proc_scsi_dev_handler_read, - (void *)dev_type); + scst_dev_handler_proc_data.data = (void *)dev_type; + p = scst_create_proc_entry(dev_type->proc_dev_type_root, + dev_type->name, + &scst_dev_handler_proc_data); if (p == NULL) { PRINT_ERROR_PR("Not enough memory to register dev " "handler entry %s in /proc/%s/%s", dev_type->name, SCST_PROC_ENTRY_NAME, dev_type->name); goto out_remove1; } - p->write_proc = scst_proc_scsi_dev_handler_write; } out: @@ -1479,7 +1003,7 @@ if (dev_type->proc_dev_type_root) { remove_proc_entry(SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME, dev_type->proc_dev_type_root); - if (dev_type->proc_info) { + if (dev_type->read_proc || dev_type->write_proc) { remove_proc_entry(dev_type->name, dev_type->proc_dev_type_root); } @@ -1491,56 +1015,10 @@ return; } -static int scst_proc_scsi_dev_handler_type_read(char *buffer, char **start, - off_t offset, int length, - int *eof, void *data) +static int scst_proc_scsi_dev_handler_write(struct file *file, const char __user *buf, + size_t length, loff_t *off) { - struct scst_dev_type *dev_type = data; - int n = 0; - - TRACE_ENTRY(); - - n = scnprintf(buffer, length, "%d - %s\n", dev_type->type, - dev_type->type > 0x0f ? - "unknown" : scst_proc_dev_handler_type[dev_type->type]); - - TRACE_EXIT_RES(n); - return n; -} - -static int scst_proc_scsi_dev_handler_read(char *buffer, char **start, - off_t offset, int length, int *eof, - void *data) -{ - struct scst_dev_type *dev_type = data; - int res = 0; - - TRACE_ENTRY(); - - TRACE_DBG("offset: %d, length %d, name: %s", - (int) offset, length, dev_type->name); - - if (down_interruptible(&scst_proc_mutex) != 0) { - res = -EINTR; - goto out; - } - - if (dev_type->proc_info) { - res = dev_type->proc_info(buffer, start, offset, length, eof, - dev_type, 0); - } - - up(&scst_proc_mutex); - -out: - TRACE_EXIT_RES(res); - return res; -} - -static int scst_proc_scsi_dev_handler_write(struct file *file, const char *buf, - unsig... [truncated message content] |