patch-2.3.27 linux/drivers/scsi/scsi_proc.c
Next file: linux/drivers/scsi/scsi_syms.c
Previous file: linux/drivers/scsi/scsi_ioctl.c
Back to the patch index
Back to the overall index
- Lines: 214
- Date:
Thu Nov 11 16:57:30 1999
- Orig file:
v2.3.26/linux/drivers/scsi/scsi_proc.c
- Orig date:
Tue Sep 7 12:14:06 1999
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
@@ -27,6 +27,9 @@
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/blk.h>
+
+#include <asm/uaccess.h>
+
#include "scsi.h"
#include "hosts.h"
@@ -36,27 +39,16 @@
#endif
#ifdef CONFIG_PROC_FS
-extern int scsi_proc_info(char *, char **, off_t, int, int, int);
-
-struct scsi_dir {
- struct proc_dir_entry entry;
- char name[4];
-};
-
/* generic_proc_info
* Used if the driver currently has no own support for /proc/scsi
*/
-int generic_proc_info(char *buffer, char **start, off_t offset,
- int length, int inode, int inout,
+int generic_proc_info(char *buffer, char **start, off_t offset, int length,
const char *(*info) (struct Scsi_Host *),
struct Scsi_Host *sh)
{
int len, pos, begin;
- if (inout == TRUE)
- return (-ENOSYS); /* This is a no-op */
-
begin = 0;
if (info && sh) {
pos = len = sprintf(buffer, "%s\n", info(sh));
@@ -79,70 +71,70 @@
/* dispatch_scsi_info is the central dispatcher
* It is the interface between the proc-fs and the SCSI subsystem code
*/
-extern int dispatch_scsi_info(int ino, char *buffer, char **start,
- off_t offset, int length, int func)
+static int proc_scsi_read(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
{
- struct Scsi_Host *hpnt = scsi_hostlist;
+ struct Scsi_Host *hpnt = data;
+ int n;
- if (ino == PROC_SCSI_SCSI) {
- /*
- * This is for the scsi core, rather than any specific
- * lowlevel driver.
- */
- return (scsi_proc_info(buffer, start, offset, length, 0, func));
- }
- while (hpnt) {
- if (ino == (hpnt->host_no + PROC_SCSI_FILE)) {
- if (hpnt->hostt->proc_info == NULL)
- return generic_proc_info(buffer, start, offset, length,
- hpnt->host_no, func,
- hpnt->hostt->info,
- hpnt);
- else
- return (hpnt->hostt->proc_info(buffer, start, offset,
- length, hpnt->host_no, func));
- }
- hpnt = hpnt->next;
- }
- return (-EBADF);
+ if (hpnt->hostt->proc_info == NULL)
+ n = generic_proc_info(buffer, start, offset, length,
+ hpnt->hostt->info, hpnt);
+ else
+ n = (hpnt->hostt->proc_info(buffer, start, offset,
+ length, hpnt->host_no, 0));
+ *eof = (n<length);
+ return n;
}
-static void scsi_proc_fill_inode(struct inode *inode, int fill)
+#define PROC_BLOCK_SIZE (3*1024) /* 4K page size, but our output routines
+ * use some slack for overruns
+ */
+
+static ssize_t proc_scsi_write(struct file * file, const char * buf,
+ unsigned long count, void *data)
{
- Scsi_Host_Template *shpnt;
+ struct Scsi_Host *hpnt = data;
+ ssize_t ret = 0;
+ char * page;
+ char *start;
+
+ if (count > PROC_BLOCK_SIZE)
+ return -EOVERFLOW;
+
+ if (!(page = (char *) __get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ copy_from_user(page, buf, count);
- shpnt = scsi_hosts;
- while (shpnt && shpnt->proc_dir->low_ino != inode->i_ino)
- shpnt = shpnt->next;
- if (!shpnt || !shpnt->module)
- return;
- if (fill)
- __MOD_INC_USE_COUNT(shpnt->module);
+ if (hpnt->hostt->proc_info == NULL)
+ ret = -ENOSYS;
else
- __MOD_DEC_USE_COUNT(shpnt->module);
+ ret = hpnt->hostt->proc_info(page, &start, 0, count,
+ hpnt->host_no, 1);
+ free_page((ulong) page);
+ return(ret);
}
void build_proc_dir_entries(Scsi_Host_Template * tpnt)
{
struct Scsi_Host *hpnt;
- struct scsi_dir *scsi_hba_dir;
- proc_scsi_register(0, tpnt->proc_dir);
- tpnt->proc_dir->fill_inode = &scsi_proc_fill_inode;
+ tpnt->proc_dir = create_proc_entry(tpnt->proc_name, S_IFDIR, proc_scsi);
+ tpnt->proc_dir->owner = tpnt->module;
hpnt = scsi_hostlist;
while (hpnt) {
if (tpnt == hpnt->hostt) {
- scsi_hba_dir = scsi_init_malloc(sizeof(struct scsi_dir), GFP_KERNEL);
- if (scsi_hba_dir == NULL)
+ struct proc_dir_entry *p;
+ p = create_proc_read_entry(hpnt->proc_name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ tpnt->proc_dir,
+ proc_scsi_read,
+ (void *)hpnt);
+ if (!p)
panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
- memset(scsi_hba_dir, 0, sizeof(struct scsi_dir));
- scsi_hba_dir->entry.low_ino = PROC_SCSI_FILE + hpnt->host_no;
- scsi_hba_dir->entry.namelen = sprintf(scsi_hba_dir->name, "%d",
- hpnt->host_no);
- scsi_hba_dir->entry.name = scsi_hba_dir->name;
- scsi_hba_dir->entry.mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_scsi_register(tpnt->proc_dir, &scsi_hba_dir->entry);
+ p->write_proc=proc_scsi_write;
+ p->owner = tpnt->module;
}
hpnt = hpnt->next;
}
@@ -178,28 +170,28 @@
cmdNum; /* cmd number */
} parseHandle;
-
inline int parseFree(parseHandle * handle)
{ /* free memory */
kfree(handle->cmdPos);
kfree(handle);
- return (-1);
+ return -1;
}
-
parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
{
char *ptr; /* temp pointer */
parseHandle *handle; /* new handle */
if (!buf || !cmdList) /* bad input ? */
- return (NULL);
- if ((handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL)) == 0)
- return (NULL); /* out of memory */
- if ((handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL)) == 0) {
+ return NULL;
+ handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL);
+ if (!handle)
+ return NULL; /* out of memory */
+ handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL);
+ if (!handle->cmdPos) {
kfree(handle);
- return (NULL); /* out of memory */
+ return NULL; /* out of memory */
}
handle->buf = handle->bufPos = buf; /* init handle */
handle->cmdList = cmdList;
@@ -212,10 +204,9 @@
handle->cmdPos[++cmdNum] = ptr++;
}
}
- return (handle);
+ return handle;
}
-
int parseOpt(parseHandle * handle, char **param)
{
int cmdIndex = 0, cmdLen = 0;
@@ -299,7 +290,7 @@
return;
}
-#else
+#else /* if !CONFIG_PROC_FS */
void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
{
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)