#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp ; mp = mp->next) {
if (!mp->ex_table_start)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr - mp->gp);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end-1, addr);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end-1, addr, g2);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
free_page((unsigned long)buf);
}
+/* caller must hold modlist_lock at least in read mode */
static __inline__ struct module *find_module(const char *name)
{
struct module *mod;
struct module *mod;
int err;
- lock_kernel();
+ read_lock(&modlist_lock);
if (name_user == 0) {
/* This finds "kernel_module" which is not exported. */
for(mod = module_list; mod->next != NULL; mod = mod->next)
break;
}
out:
- unlock_kernel();
+ read_unlock(&modlist_lock);
return err;
}
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+ read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end-1, addr, g2);
- if (ret) return ret;
+ if (ret) {
+ read_unlock(&modlist_lock);
+ return ret;
+ }
}
+ read_unlock(&modlist_lock);
#endif
return 0;
*
* This file contains the procfs interface for the
* QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
+
+ * Old code removed, switched to dynamic proc entry.
*/
#include <linux/config.h>
#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
-/* adding proc entries from inside a module is REALLY complicated
- * for pre-2.1.28 kernels. I don't want to care about it.
- */
-
#include <linux/proc_fs.h>
#include <linux/ftape.h>
-#if LINUX_VERSION_CODE <= KERNEL_VER(1,2,13) /* bail out */
-#error \
-Please disable CONFIG_FT_PROC_FS in "MCONFIG" or upgrade to a newer kernel!
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,16)
#include <linux/init.h>
-#else
-#define __initdata
-#define __initfunc(__arg) __arg
-#endif
#include <linux/qic117.h>
-
#include "../lowlevel/ftape-io.h"
#include "../lowlevel/ftape-ctl.h"
#include "../lowlevel/ftape-proc.h"
#include "../lowlevel/ftape-tracing.h"
-static int ftape_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data);
-
-#if LINUX_VERSION_CODE < KERNEL_VER(2,1,28)
-
-#include <asm/segment.h> /* for memcpy_tofs() */
-
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long ftape_proc_read(struct inode* inode, struct file* file,
- char* buf, unsigned long count);
-#else
-static int ftape_proc_read(struct inode* inode, struct file* file,
- char* buf, int count);
-#endif
-
-#define FT_PROC_REGISTER(parent, child) proc_register_dynamic(parent, child)
-
-/*
- * Structures for interfacing with the /proc filesystem.
- * Router creates its own directory /proc/net/router with the folowing
- * entries:
- * config device configuration
- * status global device statistics
- * <device> entry for each WAN device
- */
-
-/*
- * Generic /proc/net/ftape/<file> file and inode operations
- */
-
-
-static struct file_operations ftape_proc_fops =
-{
- NULL, /* lseek */
- ftape_proc_read, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL, /* can't fsync */
-};
-
-static struct inode_operations ftape_proc_inode_operations =
-{
- &ftape_proc_fops,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL, /* revalidate */
-};
-
-/*
- * Proc filesystem directory entries.
- */
-
-static int ftape_get_info(char *page, char **start, off_t off,
- int count, int dummy)
-{
- int dummy_eof;
-
- return ftape_read_proc(page, start, off, count, &dummy_eof, NULL);
-}
-
-static struct proc_dir_entry proc_ftape = {
- 0, /* low_ino */
- sizeof("ftape")-1, /* namelen */
- "ftape", /* name */
- S_IFREG | S_IRUGO, /* mode */
- 1, /* nlink */
- 0, /* uid */
- 0, /* gid */
- 0, /* size */
- &ftape_proc_inode_operations, /* ops */
- ftape_get_info, /* get_info */
- NULL, /* fill_inode */
- NULL, /* next */
- NULL, /* parent */
- NULL, /* subdir */
- NULL /* data */
-};
-
-/* Read ftape proc directory entry.
- */
-
-#define PROC_BLOCK_SIZE PAGE_SIZE
-
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long ftape_proc_read(struct inode * inode, struct file * file,
- char * buf, unsigned long nbytes)
-#else
-static int ftape_proc_read(struct inode * inode, struct file * file,
- char * buf, int nbytes)
-#endif
-{
- char *page;
- int retval=0;
- int eof=0;
- int n, count;
- char *start;
- struct proc_dir_entry * dp;
-
- if (nbytes < 0)
- return -EINVAL;
- dp = (struct proc_dir_entry *) inode->u.generic_ip;
- if (!(page = (char*) __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
-
- while ((nbytes > 0) && !eof)
- {
- count = PROC_BLOCK_SIZE <= nbytes ? PROC_BLOCK_SIZE : nbytes;
-
- start = NULL;
- if (dp->get_info) {
- /*
- * Handle backwards compatibility with the old net
- * routines.
- *
- * XXX What gives with the file->f_flags & O_ACCMODE
- * test? Seems stupid to me....
- */
- n = dp->get_info(page, &start, file->f_pos, count,
- (file->f_flags & O_ACCMODE) == O_RDWR);
- if (n < count)
- eof = 1;
- } else
- break;
-
- if (!start) {
- /*
- * For proc files that are less than 4k
- */
- start = page + file->f_pos;
- n -= file->f_pos;
- if (n <= 0)
- break;
- if (n > count)
- n = count;
- }
- if (n == 0)
- break; /* End of file */
- if (n < 0) {
- if (retval == 0)
- retval = n;
- break;
- }
-#if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
- copy_to_user(buf, start, n);
-#else
- memcpy_tofs(buf, start, n);
-#endif
- file->f_pos += n; /* Move down the file */
- nbytes -= n;
- buf += n;
- retval += n;
- }
- free_page((unsigned long) page);
- return retval;
-}
-
-#else /* LINUX_VERSION_CODE < KERNEL_VER(2,1,28) */
-
-#define FT_PROC_REGISTER(parent, child) proc_register(parent, child)
-
-/*
- * Proc filesystem directory entries.
- */
-
-static struct proc_dir_entry proc_ftape = {
- 0, /* low_ino */
- sizeof("ftape")-1, /* namelen */
- "ftape", /* name */
- S_IFREG | S_IRUGO, /* mode */
- 1, /* nlink */
- 0, /* uid */
- 0, /* gid */
- 0, /* size */
- NULL, /* ops */
- NULL, /* get_info */
- NULL, /* fill_inode */
- NULL, /* next */
- NULL, /* parent */
- NULL, /* subdir */
- NULL, /* data */
- ftape_read_proc, /* read_proc */
- NULL /* write_proc */
-};
-
-#endif
-
static size_t get_driver_info(char *buf)
{
const char *debug_level[] = { "bugs" ,
int __init ftape_proc_init(void)
{
- return FT_PROC_REGISTER(&proc_root, &proc_ftape);
+ return create_proc_read_entry("ftape", 0, &proc_root,
+ ftape_read_proc, NULL) != NULL;
}
#ifdef MODULE
void ftape_proc_destroy(void)
{
- proc_unregister(&proc_root, proc_ftape.low_ino);
+ remove_proc_entry("ftape", &proc_root);
}
#endif
int ip2_read_procmem(char *, char **, off_t, int, int );
int ip2_read_proc(char *, char **, off_t, int, int *, void * );
-struct proc_dir_entry ip2_proc_entry = {
- 0,
- 6,"ip2mem",
- S_IFREG | S_IRUGO,
- 1, 0, 0,
- 0,
- NULL,
- ip2_read_procmem
-};
-
/********************/
/* Type Definitions */
/********************/
if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) {
printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
}
- if ( ( err = proc_unregister( &proc_root, ip2_proc_entry.low_ino ) ) ) {
- printk(KERN_ERR "IP2: failed to unregister read_procmem (%d)\n", err);
- }
+ remove_proc_entry("ip2mem", &proc_root);
// free memory
for (i = 0; i < IP2_MAX_BOARDS; i++) {
printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
} else
/* Register the read_procmem thing */
- if ( ( err = proc_register( &proc_root, &ip2_proc_entry ) ) ) {
- printk(KERN_ERR "IP2: failed to register read_procmem (%d)\n", err );
+ if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) {
+ printk(KERN_ERR "IP2: failed to register read_procmem\n");
} else {
#ifdef IP2DEBUG_TRACE
static void start_net(u_long local);
/* void start_net(ray_dev_t *local); */
-static int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare);
/* Create symbol table for registering with kernel in init_module */
EXPORT_SYMBOL(ray_dev_ioctl);
EXPORT_SYMBOL(ray_rx);
static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry ray_cs_proc_entry = {
- 0, /* Dynamic inode # */
- 6,"ray_cs", /* name length and name */
- S_IFREG | S_IRUGO, /* mode */
- 1, 0, 0, /* nlinks, owner, group */
- 0, /* size (unused) */
- NULL, /* operations (default) */
- &ray_cs_proc_read, /* function to read data */
- /* The end ?? */
-};
-#endif
/*===========================================================================*/
static void cs_error(client_handle_t handle, int func, int ret)
{
rc = register_pcmcia_driver(&dev_info, &ray_attach, &ray_detach);
DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc);
#ifdef CONFIG_PROC_FS
- proc_register(&proc_root, &ray_cs_proc_entry);
+ /* [proc-namespace][fixme] It shouldn't be under root, damnit! */
+ create_proc_info_entry("ray_cs", 0, proc_root, ray_cs_proc_read);
#endif
if (translate != 0) translate = 1;
return 0;
ray_detach(dev_list);
}
#ifdef CONFIG_PROC_FS
- proc_unregister(&proc_root, ray_cs_proc_entry.low_ino);
+ remove_proc_entry("ray_cs", proc_root);
#endif
} /* exit_ray_cs */
static int isapnp_proc_done(void)
{
if (isapnp_proc_entry)
- proc_unregister(&proc_root, isapnp_proc_entry->low_ino);
+ remove_proc_entry("isapnp",&proc_root);
return 0;
}
#endif /* MODULE */
#undef USE_STATIC_SCSI_MEMORY
struct proc_dir_entry *proc_scsi = NULL;
+
+#ifdef CONFIG_PROC_FS
static int scsi_proc_info(char *buffer, char **start, off_t offset,
int length, int inout);
+static void scsi_dump_status(int level);
+#endif
/*
static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/scsi.c,v 1.38 1997/01/19 23:07:18 davem Exp $";
|| ((HOST)->host_blocked) \
|| ((DEVICE) != NULL && (DEVICE)->device_blocked) )
-static void scsi_dump_status(int level);
struct dev_info {
/*
* This makes /proc/scsi and /proc/scsi/scsi visible.
*/
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
proc_scsi = create_proc_entry ("scsi", S_IFDIR, 0);
if (!proc_scsi) {
printk (KERN_ERR "cannot init /proc/scsi\n");
* where token is one of [error,scan,mlqueue,mlcomplete,llqueue,
* llcomplete,hlqueue,hlcomplete]
*/
-#if CONFIG_SCSI_LOGGING /* { */
+#ifdef CONFIG_SCSI_LOGGING /* { */
if (!strncmp("log", buffer + 5, 3)) {
char *token;
scsi_hosts = tpnt;
/* Add the new driver to /proc/scsi */
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
build_proc_dir_entries(tpnt);
#endif
if (shpnt->loaded_as_module) {
pcount = next_scsi_host;
/* Remove the /proc/scsi directory entry */
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
proc_scsi_unregister(tpnt->proc_dir,
shpnt->host_no + PROC_SCSI_FILE);
#endif
break;
}
/* Rebuild the /proc/scsi directory entries */
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
proc_scsi_unregister(tpnt->proc_dir, tpnt->proc_dir->low_ino);
#endif
MOD_DEC_USE_COUNT;
#endif /* CONFIG_MODULES */
+#ifdef CONFIG_PROC_FS
/*
* Function: scsi_dump_status
*
*/
static void scsi_dump_status(int level)
{
-#if CONFIG_PROC_FS
-#if CONFIG_SCSI_LOGGING /* { */
+#ifdef CONFIG_SCSI_LOGGING /* { */
int i;
struct Scsi_Host *shpnt;
Scsi_Cmnd *SCpnt;
}
/* printk("wait_for_request = %p\n", &wait_for_request); */
#endif /* CONFIG_SCSI_LOGGING */ /* } */
-#endif /* CONFIG_PROC_FS */
}
+#endif /* CONFIG_PROC_FS */
#ifdef MODULE
/*
* This makes /proc/scsi and /proc/scsi/scsi visible.
*/
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
proc_scsi = create_proc_entry ("scsi", S_IFDIR, 0);
if (!proc_scsi) {
printk (KERN_ERR "cannot init /proc/scsi\n");
{
remove_bh(SCSI_BH);
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
/* No, we're not here anymore. Don't show the /proc/scsi files. */
remove_proc_entry ("scsi/scsi", 0);
remove_proc_entry ("scsi", 0);
#define _SCSI_H
#include <linux/config.h> /* for CONFIG_SCSI_LOGGING */
+#include <linux/proc_fs.h>
/*
* Some of the public constants are being moved to this file.
extern int max_scsi_hosts;
extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
+extern struct inode_operations proc_scsi_inode_operations;
+extern struct proc_dir_entry *proc_scsi;
+
+#ifdef CONFIG_PROC_FS
+
+extern inline int proc_scsi_register(struct proc_dir_entry *driver,
+ struct proc_dir_entry *x)
+{
+ x->ops = &proc_scsi_inode_operations;
+ if(x->low_ino < PROC_SCSI_FILE){
+ return(proc_register(proc_scsi, x));
+ }else{
+ return(proc_register(driver, x));
+ }
+}
+
+extern inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
+{
+ extern void scsi_init_free(char *ptr, unsigned int size);
+
+ if(x < PROC_SCSI_FILE)
+ return(proc_unregister(proc_scsi, x));
+ else {
+ struct proc_dir_entry **p = &driver->subdir, *dp;
+ int ret;
+
+ while ((dp = *p) != NULL) {
+ if (dp->low_ino == x)
+ break;
+ p = &dp->next;
+ }
+ ret = proc_unregister(driver, x);
+ scsi_init_free((char *) dp, sizeof(struct proc_dir_entry) + 4);
+ return(ret);
+ }
+}
+
+#else
+
+extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; }
+extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; }
+
+#endif /* CONFIG_PROC_FS */
+
extern void print_command(unsigned char *);
extern void print_sense(const char *, Scsi_Cmnd *);
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/blk.h>
+
+#include <asm/uaccess.h>
+
#include "scsi.h"
#include "hosts.h"
/* dispatch_scsi_info is the central dispatcher
* It is the interface between the proc-fs and the SCSI subsystem code
*/
-int dispatch_scsi_info(int ino, char *buffer, char **start,
+static int dispatch_scsi_info(int ino, char *buffer, char **start,
off_t offset, int length, int func)
{
struct Scsi_Host *hpnt = scsi_hostlist;
return;
}
-#else
-
-void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
-{
-}
-
/* forward references */
static ssize_t proc_readscsi(struct file * file, char * buf,
size_t count, loff_t *ppos);
extern void build_proc_dir_hba_entries(uint);
-/* the *_get_info() functions are in the respective scsi driver code */
-int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
- off_t offset, int length, int inout) = 0;
-
static struct file_operations proc_scsi_operations = {
proc_scsilseek, /* lseek */
proc_readscsi, /* read */
NULL /* revalidate */
};
-static int get_not_present_info(char *buffer, char **start, off_t offset, int length)
-{
- int len, pos, begin;
-
- begin = 0;
- pos = len = sprintf(buffer,
- "No low-level scsi modules are currently present\n");
- if(pos < offset) {
- len = 0;
- begin = pos;
- }
-
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin);
- if(len > length)
- len = length;
-
- return(len);
-}
-
#define PROC_BLOCK_SIZE (3*1024) /* 4K page size, but our output routines
* use some slack for overruns
*/
if(bytes > PROC_BLOCK_SIZE)
thistime = PROC_BLOCK_SIZE;
- if(dispatch_scsi_info_ptr)
- length = dispatch_scsi_info_ptr(inode->i_ino, page, &start,
- *ppos, thistime, 0);
- else
- length = get_not_present_info(page, &start, *ppos, thistime);
+ length = dispatch_scsi_info (inode->i_ino, page, &start,
+ *ppos, thistime, 0);
if(length < 0) {
free_page((ulong) page);
return(length);
return(-EOVERFLOW);
}
- if(dispatch_scsi_info_ptr != NULL) {
- if (!(page = (char *) __get_free_page(GFP_KERNEL)))
- return(-ENOMEM);
- copy_from_user(page, buf, count);
- ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
- } else
- return(-ENOPKG); /* Nothing here */
+ if (!(page = (char *) __get_free_page(GFP_KERNEL)))
+ return(-ENOMEM);
+ copy_from_user(page, buf, count);
+ ret = dispatch_scsi_info (inode->i_ino, page, 0, 0, count, 1);
free_page((ulong) page);
return(ret);
}
}
+#else /* if !CONFIG_PROC_FS */
+
+void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
+{
+}
+
+struct inode_operations proc_scsi_inode_operations = { 0, };
+
#endif /* CONFIG_PROC_FS */
/*
EXPORT_SYMBOL(proc_print_scsidevice);
EXPORT_SYMBOL(proc_scsi);
+EXPORT_SYMBOL(proc_scsi_inode_operations);
/*
* These are here only while I debug the rest of the scsi stuff.
struct buffer_head * bh;
int i,j;
- if (!dir || !(inode = get_empty_inode()))
+ inode = get_empty_inode();
+ if (!inode)
return NULL;
sb = dir->i_sb;
inode->i_sb = sb;
inode->i_flags = 0;
j = 8192;
bh = NULL;
+ lock_super(sb);
for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
bh = inode->i_sb->u.minix_sb.s_imap[i];
if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
}
if (!bh || j >= 8192) {
iput(inode);
+ unlock_super(sb);
return NULL;
}
if (minix_set_bit(j,bh->b_data)) { /* shouldn't happen */
printk("new_inode: bit already set");
iput(inode);
+ unlock_super(sb);
return NULL;
}
mark_buffer_dirty(bh, 1);
j += i*8192;
if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
iput(inode);
+ unlock_super(sb);
return NULL;
}
inode->i_nlink = 1;
++*pages;
if (pte_dirty(page))
++*dirty;
- if (MAP_NR(pte_page(page)) >= max_mapnr)
+ if (pte_pagenr(page) >= max_mapnr)
continue;
- if (page_count(mem_map + MAP_NR(pte_page(page))) > 1)
+ if (page_count(pte_page(page)) > 1)
++*shared;
} while (address < end);
}
#ifdef CONFIG_MODULES
{
struct module *m;
+ read_lock(&modlist_lock);
for (m=module_list; m; m=m->next) {
dhdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
dhdr->p_align = 0;
elf->e_phnum++;
}
+ read_unlock(&modlist_lock);
}
#endif
#define _LINUX_MODULE_H
#include <linux/config.h>
+#include <linux/spinlock.h>
#ifdef __GENKSYMS__
# define _set_ver(sym) sym
#define EXPORT_NO_SYMBOLS
#endif /* MODULE */
+extern rwlock_t modlist_lock;
extern unsigned long get_kcore_size(void);
#endif /* _LINUX_MODULE_H */
int deleted; /* delete flag */
};
-#if 0 /* FIXME! /proc/scsi is broken right now */
-extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
- off_t offset, int length, int inout);
-extern struct inode_operations proc_scsi_inode_operations;
-#endif
-
#define PROC_INODE_PROPER(inode) ((inode)->i_ino & ~0xffff)
#define PROC_INODE_OPENPROM(inode) \
((inode->i_ino >= PROC_OPENPROM_FIRST) \
extern struct proc_dir_entry proc_root;
extern struct proc_dir_entry *proc_root_fs;
extern struct proc_dir_entry *proc_net;
-extern struct proc_dir_entry *proc_scsi;
extern struct proc_dir_entry proc_sys;
extern struct proc_dir_entry proc_openprom;
extern struct proc_dir_entry *proc_mca;
extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
-extern inline int proc_scsi_register(struct proc_dir_entry *driver,
- struct proc_dir_entry *x)
-{
-#if 0 /* FIXME! */
- x->ops = &proc_scsi_inode_operations;
-#endif
- if(x->low_ino < PROC_SCSI_FILE){
- return(proc_register(proc_scsi, x));
- }else{
- return(proc_register(driver, x));
- }
-}
-
-extern inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
-{
- extern void scsi_init_free(char *ptr, unsigned int size);
-
- if(x < PROC_SCSI_FILE)
- return(proc_unregister(proc_scsi, x));
- else {
- struct proc_dir_entry **p = &driver->subdir, *dp;
- int ret;
-
- while ((dp = *p) != NULL) {
- if (dp->low_ino == x)
- break;
- p = &dp->next;
- }
- ret = proc_unregister(driver, x);
- scsi_init_free((char *) dp, sizeof(struct proc_dir_entry) + 4);
- return(ret);
- }
-}
-
-
/*
* retrieve the proc_dir_entry associated with /proc/driver/$module_name
*/
extern inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode,
get_info_t *get_info) {return NULL;}
extern inline void proc_net_remove(const char *name) {}
-extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; }
-extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; }
extern inline struct proc_dir_entry *create_proc_entry(const char *name,
mode_t mode, struct proc_dir_entry *parent) { return NULL; }
* 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
* Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
* Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
+ * Use rw spinlock instead of global kernel lock for module_list, by TA <tigran@sco.com>
*
* This source is covered by the GNU GPL, the same as all kernel sources.
*/
static struct module *find_module(const char *name);
static void free_module(struct module *, int tag_freed);
+rwlock_t modlist_lock = RW_LOCK_UNLOCKED;
+
/* needed for /proc/kcore, here because kernel_module is static (TA) */
unsigned long get_kcore_size(void)
if (module_list == &kernel_module)
return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE);
- /* shouldn't we have a rw spinlock for module_list? */
- lock_kernel();
+ read_lock(&modlist_lock);
for (m=module_list; m; m=m->next) {
try = (unsigned long)m + m->size;
if (try > size)
size = try;
}
- unlock_kernel();
+ read_unlock(&modlist_lock);
return (size - PAGE_OFFSET + PAGE_SIZE);
}
long namelen, error;
struct module *mod;
- lock_kernel();
+ write_lock(&modlist_lock);
if (!capable(CAP_SYS_MODULE)) {
error = -EPERM;
goto err0;
err1:
put_mod_name(name);
err0:
- unlock_kernel();
+ write_unlock(&modlist_lock);
return error;
}
unsigned long mod_user_size;
struct module_ref *dep;
- lock_kernel();
+ write_lock(&modlist_lock);
if (!capable(CAP_SYS_MODULE))
goto err0;
if ((namelen = get_mod_name(name_user, &name)) < 0) {
err1:
put_mod_name(name);
err0:
- unlock_kernel();
+ write_unlock(&modlist_lock);
return error;
}
long error = -EPERM;
int something_changed;
- lock_kernel();
+ write_lock(&modlist_lock);
if (!capable(CAP_SYS_MODULE))
goto out;
mod->flags &= ~MOD_JUST_FREED;
error = 0;
out:
- unlock_kernel();
+ write_unlock(&modlist_lock);
return error;
}
nmod = space = 0;
+ read_lock(&modlist_lock);
for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {
len = strlen(mod->name)+1;
if (len > bufsize)
goto calc_space_needed;
- if (copy_to_user(buf, mod->name, len))
+ if (copy_to_user(buf, mod->name, len)) {
+ read_unlock(&modlist_lock);
return -EFAULT;
+ }
buf += len;
bufsize -= len;
space += len;
}
+ read_unlock(&modlist_lock);
if (put_user(nmod, ret))
return -EFAULT;
else
while ((mod = mod->next) != &kernel_module)
space += strlen(mod->name)+1;
+ read_unlock(&modlist_lock);
if (put_user(space, ret))
return -EFAULT;
else
struct module *mod;
int err;
- lock_kernel();
+ read_lock(&modlist_lock);
if (name_user == NULL)
mod = &kernel_module;
else {
break;
}
out:
- unlock_kernel();
+ read_unlock(&modlist_lock);
return err;
}
int i;
struct kernel_sym ksym;
- lock_kernel();
+ read_lock(&modlist_lock);
for (mod = module_list, i = 0; mod; mod = mod->next) {
/* include the count for the module name! */
i += mod->nsyms + 1;
}
}
out:
- unlock_kernel();
+ read_unlock(&modlist_lock);
return i;
}
/*
* Look for a module by name, ignoring modules marked for deletion.
+ * Callers must hold modlist_lock at least in read mode.
*/
static struct module *
/*
* Free the given module.
+ * Callers must hold modlist_lock in exclusive (write) mode.
*/
static void
char tmpstr[64];
struct module_ref *ref;
+ read_lock(&modlist_lock);
for (mod = module_list; mod != &kernel_module; mod = mod->next) {
long len;
const char *q;
}
fini:
+ read_unlock(&modlist_lock);
return PAGE_SIZE - left;
}
off_t pos = 0;
off_t begin = 0;
+ read_lock(&modlist_lock);
for (mod = module_list; mod; mod = mod->next) {
unsigned i;
struct module_symbol *sym;
len -= (offset - begin);
if (len > length)
len = length;
+ read_unlock(&modlist_lock);
return len;
}
struct module_symbol *sym;
int i;
+ read_lock(&modlist_lock);
for (mp = module_list; mp; mp = mp->next) {
if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) &&
(mp->flags & (MOD_RUNNING | MOD_DELETED)) == MOD_RUNNING &&
i > 0; --i, ++sym) {
if (strcmp(sym->name, symname) == 0) {
+ read_unlock(&modlist_lock);
return sym->value;
}
}
}
}
+ read_unlock(&modlist_lock);
return 0;
}