From 441b2211b6f34067b9dfb19b03c954dbc4241539 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:28:31 -0500 Subject: [PATCH] Import 2.3.27pre5 --- arch/alpha/mm/extable.c | 7 +- arch/arm/mm/extable.c | 7 +- arch/i386/mm/extable.c | 7 +- arch/m68k/mm/extable.c | 7 +- arch/mips/mm/extable.c | 7 +- arch/ppc/mm/extable.c | 7 +- arch/sh/mm/extable.c | 7 +- arch/sparc/mm/extable.c | 7 +- arch/sparc64/kernel/sys_sparc32.c | 5 +- arch/sparc64/mm/extable.c | 7 +- drivers/char/ftape/lowlevel/ftape-proc.c | 229 +---------------------- drivers/char/ip2main.c | 18 +- drivers/net/pcmcia/ray_cs.c | 18 +- drivers/pnp/isapnp_proc.c | 2 +- drivers/scsi/scsi.c | 25 +-- drivers/scsi/scsi.h | 45 +++++ drivers/scsi/scsi_proc.c | 61 ++---- drivers/scsi/scsi_syms.c | 1 + fs/minix/bitmap.c | 7 +- fs/proc/array.c | 4 +- fs/proc/kcore.c | 2 + include/linux/module.h | 2 + include/linux/proc_fs.h | 44 ----- kernel/module.c | 44 +++-- 24 files changed, 189 insertions(+), 381 deletions(-) diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index 12a1f4803fd1..ea1387f791d6 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c @@ -49,13 +49,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c index e603b6362041..c98ba5a9e029 100644 --- a/arch/arm/mm/extable.c +++ b/arch/arm/mm/extable.c @@ -42,13 +42,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c index ba34c0395812..398a62fa1a73 100644 --- a/arch/i386/mm/extable.c +++ b/arch/i386/mm/extable.c @@ -42,13 +42,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/m68k/mm/extable.c b/arch/m68k/mm/extable.c index 1f8d9e8c3323..7cd5d5c644da 100644 --- a/arch/m68k/mm/extable.c +++ b/arch/m68k/mm/extable.c @@ -42,13 +42,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/mips/mm/extable.c b/arch/mips/mm/extable.c index a92fdc482e9f..8a0febc38136 100644 --- a/arch/mips/mm/extable.c +++ b/arch/mips/mm/extable.c @@ -41,13 +41,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c index afcf705e14a6..dc57bf86845b 100644 --- a/arch/ppc/mm/extable.c +++ b/arch/ppc/mm/extable.c @@ -43,13 +43,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/sh/mm/extable.c b/arch/sh/mm/extable.c index dc77f57fe243..7c677a970bfe 100644 --- a/arch/sh/mm/extable.c +++ b/arch/sh/mm/extable.c @@ -45,13 +45,18 @@ search_exception_table(unsigned long addr) #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; diff --git a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c index 7fe26ad96edd..e66e4c72a003 100644 --- a/arch/sparc/mm/extable.c +++ b/arch/sparc/mm/extable.c @@ -56,13 +56,18 @@ search_exception_table(unsigned long addr, unsigned long *g2) #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; diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index a1e0f26dd9a6..c25879850a6e 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -2932,6 +2932,7 @@ put_mod_name(char *buf) 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; @@ -3161,7 +3162,7 @@ asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kerne 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) @@ -3211,7 +3212,7 @@ asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kerne break; } out: - unlock_kernel(); + read_unlock(&modlist_lock); return err; } diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c index b2df0e169ac0..a8d4964df0b3 100644 --- a/arch/sparc64/mm/extable.c +++ b/arch/sparc64/mm/extable.c @@ -56,13 +56,18 @@ search_exception_table(unsigned long addr, unsigned long *g2) #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; diff --git a/drivers/char/ftape/lowlevel/ftape-proc.c b/drivers/char/ftape/lowlevel/ftape-proc.c index edae52c38246..cfea418c5599 100644 --- a/drivers/char/ftape/lowlevel/ftape-proc.c +++ b/drivers/char/ftape/lowlevel/ftape-proc.c @@ -22,245 +22,25 @@ * * 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 #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 #include -#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 -#else -#define __initdata -#define __initfunc(__arg) __arg -#endif #include - #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 /* 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 - * entry for each WAN device - */ - -/* - * Generic /proc/net/ftape/ 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" , @@ -423,13 +203,14 @@ int ftape_read_proc(char *page, char **start, off_t off, 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 diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 8f0ef75ae7f4..b31f10ac9fbe 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -74,16 +74,6 @@ 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 */ /********************/ @@ -429,9 +419,7 @@ cleanup_module(void) 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++) { @@ -673,8 +661,8 @@ old_ip2_init(void) 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 diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c index 5594f51d1d54..4467b8af60fd 100644 --- a/drivers/net/pcmcia/ray_cs.c +++ b/drivers/net/pcmcia/ray_cs.c @@ -147,7 +147,6 @@ static void join_net(u_long local); 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); @@ -308,18 +307,6 @@ static char hop_pattern_length[] = { 1, static char rcsid[] = "Raylink/WebGear wireless LAN - Corey "; -#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) { @@ -2695,7 +2682,8 @@ static int __init init_ray_cs(void) 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; @@ -2726,7 +2714,7 @@ static void __exit exit_ray_cs(void) 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 */ diff --git a/drivers/pnp/isapnp_proc.c b/drivers/pnp/isapnp_proc.c index 784d371434be..32352c1e7113 100644 --- a/drivers/pnp/isapnp_proc.c +++ b/drivers/pnp/isapnp_proc.c @@ -247,7 +247,7 @@ static int __init isapnp_proc_init(void) 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 */ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index e5fa93ed6b1c..6b818225ef42 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -71,8 +71,12 @@ #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 $"; @@ -189,7 +193,6 @@ extern void scsi_old_times_out(Scsi_Cmnd * SCpnt); || ((HOST)->host_blocked) \ || ((DEVICE) != NULL && (DEVICE)->device_blocked) ) -static void scsi_dump_status(int level); struct dev_info { @@ -1983,7 +1986,7 @@ int __init scsi_dev_init(void) /* * 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"); @@ -2178,7 +2181,7 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, * 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; @@ -2614,7 +2617,7 @@ static int scsi_register_host(Scsi_Host_Template * tpnt) scsi_hosts = tpnt; /* Add the new driver to /proc/scsi */ -#if CONFIG_PROC_FS +#ifdef CONFIG_PROC_FS build_proc_dir_entries(tpnt); #endif @@ -2884,7 +2887,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) 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 @@ -2946,7 +2949,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) 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; @@ -3133,6 +3136,7 @@ void scsi_unregister_module(int module_type, void *ptr) #endif /* CONFIG_MODULES */ +#ifdef CONFIG_PROC_FS /* * Function: scsi_dump_status * @@ -3153,8 +3157,7 @@ void scsi_unregister_module(int module_type, void *ptr) */ 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; @@ -3233,8 +3236,8 @@ static void scsi_dump_status(int level) } /* printk("wait_for_request = %p\n", &wait_for_request); */ #endif /* CONFIG_SCSI_LOGGING */ /* } */ -#endif /* CONFIG_PROC_FS */ } +#endif /* CONFIG_PROC_FS */ #ifdef MODULE @@ -3246,7 +3249,7 @@ int init_module(void) /* * 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"); @@ -3303,7 +3306,7 @@ void cleanup_module(void) { 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); diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index f370c542a1eb..0b42a14666f4 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -16,6 +16,7 @@ #define _SCSI_H #include /* for CONFIG_SCSI_LOGGING */ +#include /* * Some of the public constants are being moved to this file. @@ -404,6 +405,50 @@ extern void scsi_release_command(Scsi_Cmnd *); 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 *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 5a92ddbf9380..d64b15f448f8 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -27,6 +27,9 @@ #include #include #include + +#include + #include "scsi.h" #include "hosts.h" @@ -77,7 +80,7 @@ int generic_proc_info(char *buffer, char **start, off_t offset, /* 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; @@ -290,12 +293,6 @@ void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len) 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); @@ -305,10 +302,6 @@ static long long proc_scsilseek(struct file *, long long, int); 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 */ @@ -349,26 +342,6 @@ struct inode_operations proc_scsi_inode_operations = { 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 */ @@ -392,11 +365,8 @@ static ssize_t proc_readscsi(struct file * file, char * buf, 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); @@ -438,13 +408,10 @@ static ssize_t proc_writescsi(struct file * file, const char * buf, 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); @@ -467,6 +434,14 @@ static long long proc_scsilseek(struct file * file, long long offset, int orig) } } +#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 */ /* diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c index d3cb4a1031dc..741b60710a2b 100644 --- a/drivers/scsi/scsi_syms.c +++ b/drivers/scsi/scsi_syms.c @@ -74,6 +74,7 @@ EXPORT_SYMBOL(scsi_sleep); 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. diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 060d5b26c550..21057e7dc8e2 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -251,13 +251,15 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) 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) @@ -265,17 +267,20 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) } 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; diff --git a/fs/proc/array.c b/fs/proc/array.c index c707dd57221e..181cc4e62fbf 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -403,9 +403,9 @@ static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned ++*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); } diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index db052fc63004..1db720ca6957 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -211,6 +211,7 @@ static void elf_kcore_store_hdr(char *bufp) #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); @@ -226,6 +227,7 @@ static void elf_kcore_store_hdr(char *bufp) dhdr->p_align = 0; elf->e_phnum++; } + read_unlock(&modlist_lock); } #endif diff --git a/include/linux/module.h b/include/linux/module.h index 88c260f658b0..bb3a3de158dc 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -8,6 +8,7 @@ #define _LINUX_MODULE_H #include +#include #ifdef __GENKSYMS__ # define _set_ver(sym) sym @@ -286,5 +287,6 @@ __attribute__((section("__ksymtab"))) = \ #define EXPORT_NO_SYMBOLS #endif /* MODULE */ +extern rwlock_t modlist_lock; extern unsigned long get_kcore_size(void); #endif /* _LINUX_MODULE_H */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 2c6b3874426c..d3edb886b044 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -145,12 +145,6 @@ struct proc_dir_entry { 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) \ @@ -161,7 +155,6 @@ extern struct inode_operations proc_scsi_inode_operations; 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; @@ -184,41 +177,6 @@ extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, 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 */ @@ -362,8 +320,6 @@ extern inline int proc_unregister(struct proc_dir_entry *a, int b) { return 0; } 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; } diff --git a/kernel/module.c b/kernel/module.c index 9b82e4e555b0..a79fa619f22f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -13,6 +13,7 @@ * 0.99.14 version by Jon Tombs , * Heavily modified by Bjorn Ekwall May 1994 (C) * Rewritten by Richard Henderson Dec 1996 + * Use rw spinlock instead of global kernel lock for module_list, by TA * * This source is covered by the GNU GPL, the same as all kernel sources. */ @@ -52,6 +53,8 @@ static void put_mod_name(char *buf); 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) @@ -62,14 +65,13 @@ 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); } @@ -131,7 +133,7 @@ sys_create_module(const char *name_user, size_t size) long namelen, error; struct module *mod; - lock_kernel(); + write_lock(&modlist_lock); if (!capable(CAP_SYS_MODULE)) { error = -EPERM; goto err0; @@ -169,7 +171,7 @@ sys_create_module(const char *name_user, size_t size) err1: put_mod_name(name); err0: - unlock_kernel(); + write_unlock(&modlist_lock); return error; } @@ -186,7 +188,7 @@ sys_init_module(const char *name_user, struct module *mod_user) 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) { @@ -365,7 +367,7 @@ err2: err1: put_mod_name(name); err0: - unlock_kernel(); + write_unlock(&modlist_lock); return error; } @@ -377,7 +379,7 @@ sys_delete_module(const char *name_user) long error = -EPERM; int something_changed; - lock_kernel(); + write_lock(&modlist_lock); if (!capable(CAP_SYS_MODULE)) goto out; @@ -430,7 +432,7 @@ restart: mod->flags &= ~MOD_JUST_FREED; error = 0; out: - unlock_kernel(); + write_unlock(&modlist_lock); return error; } @@ -444,17 +446,21 @@ qm_modules(char *buf, size_t bufsize, size_t *ret) 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 @@ -465,6 +471,7 @@ calc_space_needed: while ((mod = mod->next) != &kernel_module) space += strlen(mod->name)+1; + read_unlock(&modlist_lock); if (put_user(space, ret)) return -EFAULT; else @@ -651,7 +658,7 @@ sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, struct module *mod; int err; - lock_kernel(); + read_lock(&modlist_lock); if (name_user == NULL) mod = &kernel_module; else { @@ -697,7 +704,7 @@ sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, break; } out: - unlock_kernel(); + read_unlock(&modlist_lock); return err; } @@ -716,7 +723,7 @@ sys_get_kernel_syms(struct kernel_sym *table) 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; @@ -759,12 +766,13 @@ sys_get_kernel_syms(struct kernel_sym *table) } } 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 * @@ -784,6 +792,7 @@ find_module(const char *name) /* * Free the given module. + * Callers must hold modlist_lock in exclusive (write) mode. */ static void @@ -840,6 +849,7 @@ int get_module_list(char *p) 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; @@ -905,6 +915,7 @@ int get_module_list(char *p) } fini: + read_unlock(&modlist_lock); return PAGE_SIZE - left; } @@ -921,6 +932,7 @@ get_ksyms_list(char *buf, char **start, off_t offset, int length) 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; @@ -955,6 +967,7 @@ leave_the_loop: len -= (offset - begin); if (len > length) len = length; + read_unlock(&modlist_lock); return len; } @@ -971,6 +984,7 @@ get_module_symbol(char *modname, char *symname) 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 && @@ -979,11 +993,13 @@ get_module_symbol(char *modname, char *symname) i > 0; --i, ++sym) { if (strcmp(sym->name, symname) == 0) { + read_unlock(&modlist_lock); return sym->value; } } } } + read_unlock(&modlist_lock); return 0; } -- 2.39.5