]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.52pre3 2.3.52pre3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:32:52 +0000 (15:32 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:32:52 +0000 (15:32 -0500)
88 files changed:
arch/arm/kernel/arch.c
arch/i386/kernel/entry.S
arch/mips/kernel/irixelf.c
arch/sparc/kernel/sys_solaris.c
arch/sparc64/kernel/binfmt_aout32.c
arch/sparc64/solaris/misc.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/ppp_synctty.c
drivers/net/wan/comx-hw-comx.c
drivers/net/wan/comx-hw-locomx.c
drivers/net/wan/comx-hw-mixcom.c
drivers/net/wan/comx-proto-fr.c
drivers/net/wan/comx-proto-lapb.c
drivers/net/wan/comx-proto-ppp.c
drivers/net/wan/comx.h
drivers/scsi/Config.in
drivers/scsi/README.st
drivers/scsi/st.c
drivers/scsi/st.h
drivers/scsi/st_options.h
drivers/sound/Config.in
drivers/sound/dev_table.c
drivers/sound/dev_table.h
drivers/sound/mpu401.c
drivers/sound/sb_card.c
drivers/sound/soundcard.c
drivers/usb/ov511.c
drivers/video/hgafb.c
fs/adfs/dir.c
fs/affs/super.c
fs/bfs/inode.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_em86.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/coda/psdev.c
fs/efs/super.c
fs/exec.c
fs/fat/fatfs_syms.c
fs/fat/inode.c
fs/filesystems.c
fs/hfs/super.c
fs/hpfs/buffer.c
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/hpfs/super.c
fs/isofs/inode.c
fs/minix/inode.c
fs/msdos/msdosfs_syms.c
fs/msdos/namei.c
fs/ncpfs/inode.c
fs/ntfs/fs.c
fs/openpromfs/inode.c
fs/proc/procfs_syms.c
fs/qnx4/inode.c
fs/romfs/inode.c
fs/smbfs/inode.c
fs/sysv/inode.c
fs/udf/super.c
fs/ufs/super.c
fs/umsdos/inode.c
fs/vfat/namei.c
fs/vfat/vfatfs_syms.c
include/asm-i386/unistd.h
include/linux/affs_fs.h
include/linux/bfs_fs.h
include/linux/efs_fs.h
include/linux/hfs_fs.h
include/linux/hpfs_fs.h
include/linux/iso_fs.h
include/linux/minix_fs.h
include/linux/msdos_fs.h
include/linux/ncp_fs.h
include/linux/ntfs_fs.h
include/linux/personality.h
include/linux/proc_fs.h
include/linux/qnx4_fs.h
include/linux/romfs_fs.h
include/linux/smb_fs.h
include/linux/sysv_fs.h
include/linux/udf_fs.h
include/linux/ufs_fs.h
include/linux/umsdos_fs.h
kernel/exec_domain.c
kernel/exit.c
kernel/fork.c
mm/filemap.c

index 615ed568b87f96747050f1cd580be23586c085dc..8645497ae8ec264e4ca5ca81bee9f36ef6880a50 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Architecture specifics
  */
+#include <linux/config.h>
 #include <linux/tty.h>
 #include <linux/init.h>
 
index 0c3cae5d9ad102ff7b0a323b32edb1b2d8fe5a05..1381fb84252a4b0b32ed25c6690d6e2d92f7724c 100644 (file)
@@ -638,6 +638,7 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_setfsuid)         /* 215 */
        .long SYMBOL_NAME(sys_setfsgid)
        .long SYMBOL_NAME(sys_pivot_root)
+       .long SYMBOL_NAME(sys_mincore)
 
 
        /*
@@ -646,6 +647,6 @@ ENTRY(sys_call_table)
         * entries. Don't panic if you notice that this hasn't
         * been shrunk every time we add a new system call.
         */
-       .rept NR_syscalls-217
+       .rept NR_syscalls-218
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index 3e61f516b127f0dcaf6728a94b6a4c276b99d130..b6cc30fed8f8b7f4a3db368a166c27a17052359c 100644 (file)
@@ -602,8 +602,7 @@ void irix_map_prda_page (void)
 /* These are the functions used to load ELF style executables and shared
  * libraries.  There is no binary dependent code anywhere else.
  */
-static inline int do_load_irix_binary(struct linux_binprm * bprm,
-                                     struct pt_regs * regs)
+static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
        struct elfhdr elf_ex, interp_elf_ex;
        struct dentry *interpreter_dentry;
@@ -748,14 +747,11 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
        sys_close(elf_exec_fileno);
        current->personality = PER_IRIX32;
 
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
+       put_exec_domain(current->exec_domain);
        if (current->binfmt && current->binfmt->module)
                __MOD_DEC_USE_COUNT(current->binfmt->module);
        current->exec_domain = lookup_exec_domain(current->personality);
        current->binfmt = &irix_format;
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
        if (current->binfmt && current->binfmt->module)
                __MOD_INC_USE_COUNT(current->binfmt->module);
 
@@ -823,16 +819,6 @@ out_free_ph:
        goto out;
 }
 
-static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_irix_binary(bprm, regs);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 /* This is really simpleminded and specialized - we are loading an
  * a.out library that is given an ELF header.
  */
@@ -934,13 +920,11 @@ static int load_irix_library(int fd)
        int retval = -EACCES;
        struct file *file;
 
-       MOD_INC_USE_COUNT;
        file = fget(fd);
        if (file) {
                retval = do_load_irix_library(file);
                fput(file);
        }
-       MOD_DEC_USE_COUNT;
        return retval;
 }
        
@@ -1143,10 +1127,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
        elf_fpregset_t fpu;             /* NT_PRFPREG */
        struct elf_prpsinfo psinfo;     /* NT_PRPSINFO */
 
-#ifndef CONFIG_BINFMT_IRIX
-       MOD_INC_USE_COUNT;
-#endif
-
        /* Count what's needed to dump, up to the limit of coredump size. */
        segs = 0;
        size = 0;
@@ -1356,9 +1336,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
 
 end_coredump:
        set_fs(fs);
-#ifndef CONFIG_BINFMT_IRIX
-       MOD_DEC_USE_COUNT;
-#endif
        return has_dumped;
 }
 
index 6c46c60f0e43cbe591ace98ebb63ed5724faabba..8a9d54913068d525dfb1ec5495e388cb65f85811 100644 (file)
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
+/* CHECKME: this stuff looks rather bogus */
 asmlinkage int
 do_solaris_syscall (struct pt_regs *regs)
 {
        int ret;
 
        lock_kernel();
+       put_exec_domain(current->exec_domain);
        current->personality = PER_SVR4;
        current->exec_domain = lookup_exec_domain(PER_SVR4);
 
index 009c506a0fa867af21baf066e768ea07a3e76aa4..3e95ed9cfafe3ec18d5e85cf86c2e195faf8278c 100644 (file)
@@ -82,8 +82,7 @@ if (file->f_op->llseek) { \
  * dumping of the process results in another error..
  */
 
-static inline int
-do_aout32_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
 {
        mm_segment_t fs;
        int has_dumped = 0;
@@ -143,17 +142,6 @@ end_coredump:
        return has_dumped;
 }
 
-static int
-aout32_core_dump(long signr, struct pt_regs * regs, struct file * file)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_aout32_core_dump(signr, regs, file);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 /*
  * create_aout32_tables() parses the env- and arg-strings in new user
  * memory and creates the pointer tables from them, and puts their
@@ -207,8 +195,7 @@ static u32 *create_aout32_tables(char * p, struct linux_binprm * bprm)
  * libraries.  There is no binary dependent code anywhere else.
  */
 
-static inline int do_load_aout32_binary(struct linux_binprm * bprm,
-                                       struct pt_regs * regs)
+static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
        struct exec ex;
        struct file * file;
@@ -320,14 +307,11 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
                }
        }
 beyond_if:
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
+       put_exec_domain(current->exec_domain);
        if (current->binfmt && current->binfmt->module)
                __MOD_DEC_USE_COUNT(current->binfmt->module);
        current->exec_domain = lookup_exec_domain(current->personality);
        current->binfmt = &aout32_format;
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
        if (current->binfmt && current->binfmt->module)
                __MOD_INC_USE_COUNT(current->binfmt->module);
 
@@ -358,21 +342,8 @@ beyond_if:
        return 0;
 }
 
-
-static int
-load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_aout32_binary(bprm, regs);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 /* N.B. Move to .h file and use code in fs/binfmt_aout.c? */
-static inline int
-do_load_aout32_library(int fd)
+static int load_aout32_library(int fd)
 {
         struct file * file;
        struct inode * inode;
@@ -444,17 +415,6 @@ out:
        return retval;
 }
 
-static int
-load_aout32_library(int fd)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_aout32_library(fd);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 static int __init init_aout32_binfmt(void)
 {
        return register_binfmt(&aout32_format);
index 9e2bd4118f2980581950a6615e80cc52317265ec..9ac4027e4b9b8394ded3e679f8c84cec39eaf4b1 100644 (file)
@@ -721,11 +721,8 @@ asmlinkage void solaris_register(void)
 {
        lock_kernel();
        current->personality = PER_SVR4;
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
+       put_exec_domain(current->exec_domain);
        current->exec_domain = lookup_exec_domain(current->personality);
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
        unlock_kernel();
 }
 
index 2b5624b293eb5cc1650b261b0d374c4531f60aeb..53f841af2937aa03f963edc9ae9d7f6d63e4977f 100644 (file)
@@ -920,8 +920,6 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                  "status %4.4x.\n", dev->name, (long)skb->len,
                  inw(ioaddr + EL3_STATUS));
 
-       netif_stop_queue (dev);
-       
        outw(skb->len, ioaddr + TX_FIFO);
        outw(0, ioaddr + TX_FIFO);
        outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
@@ -929,13 +927,13 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
        /* TxFree appears only in Window 1, not offset 0x1c. */
-       if (inw(ioaddr + TxFree) > 1536) {
-               netif_start_queue (dev);
-       } else
+       if (inw(ioaddr + TxFree) <= 1536) {
+               netif_stop_queue (dev);
                /* Interrupt us when the FIFO has room for max-sized packet. 
                   The threshold is in units of dwords. */
                outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-
+       }
+       
        dev_kfree_skb (skb);
        pop_tx_status(dev);
 
@@ -976,8 +974,6 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        /* There's room in the FIFO for a full-sized packet. */
                        outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
                        netif_wake_queue (dev);
-               } else {
-                       netif_stop_queue (dev);
                }
 
                if (status & TxComplete)
index 1a69f6ede7f1b32a8c9758d0378bcf94be7f84bd..8bae76e1c480de6301d8776215ce87747d47fb7f 100644 (file)
@@ -439,7 +439,7 @@ ppp_sync_ioctl(struct tty_struct *tty, struct file *file,
                        break;
                ap->chan.private = ap;
                ap->chan.ops = &sync_ops;
-               err = ppp_register_channel(&ap->chan, val);
+               err = ppp_register_channel(&ap->chan);
                if (err != 0)
                        break;
                ap->connected = 1;
index 4e6913c62ebddad66a64373b791ff95a1e03a785..7381dc8a9c4706685fbb87144f9879bd31f36ae8 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/delay.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
index 00ab42c1fdee05d76dedeee9f3a70d57b9bdae9b..010f02373147d714f901c55a2bbfd85837769a18 100644 (file)
@@ -31,7 +31,6 @@
 
 #define VERSION "0.13"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
@@ -44,7 +43,6 @@
 #include <asm/dma.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/netdevice.h>
 
 #include "comx.h"
 #include "z85230.h"
index 89a706fd8029e5c951002bea5913c79632397312..552443f886c52ff1897f9b10ab623d7589d6007f 100644 (file)
@@ -33,7 +33,6 @@
 
 #define VERSION "0.64"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
index f3f89f8f7f90d4fe7544b4509258878fbbccbfa2..ad62e310c92b482ee57747933d488df7f477d1c2 100644 (file)
@@ -29,7 +29,6 @@
 
 #define VERSION "0.72"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
index 7c3adba484379d1da904a25014d18e3ebc70eece..c0fc0c6bd676383028deafbb035d900bad80f78b 100644 (file)
@@ -20,7 +20,6 @@
 
 #define VERSION "0.80"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
index 68472c0e1566b59baa64ff9d38d3810ab227b7d6..0b791685d0d97abc39e8011bc19061e32563bd4b 100644 (file)
@@ -33,7 +33,6 @@
 
 #define VERSION "0.23"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
index c3da445dffaf43a194648017f6e2792b3fdef773..e02849b90bf7efbcfb9a45b44add21f4f5c90aab 100644 (file)
@@ -25,6 +25,7 @@
  *     tx_carrier_errors       modem line status changes
  *     tx_fifo_errors          tx underrun (locomx)
  */
+#include <linux/config.h>
 
 struct comx_protocol {
        char    *name;
index b064b6fbf955fc55729cc00df17e8570fccb82e8..b0407de9e80e19940c653448b1e9c4a9b53898a7 100644 (file)
@@ -8,10 +8,6 @@ fi
 
 dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
 
-if [ "$CONFIG_CHR_DEV_ST" != "n" ]; then
-   int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
-fi
-
 dep_tristate '  SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
 
 if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
index b1b6362f30a2f7bf96e75a7fd3e86150749eb656..77121aa0b97168887a58191b434739f2e2b1c861 100644 (file)
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
 The driver is currently maintained by Kai M{kisara (email
 Kai.Makisara@metla.fi)
 
-Last modified: Sat Aug  7 13:52:16 1999 by makisara@kai.makisara.local
+Last modified: Sat Mar 11 10:34:44 2000 by makisara@kai.makisara.local
 
 
 BASICS
@@ -134,11 +134,7 @@ A small number of buffers are allocated at driver initialisation. The
 maximum number of these buffers is defined by ST_MAX_BUFFERS. The
 maximum can be changed with kernel or module startup options. One
 buffer is allocated for each drive detected when the driver is
-initialized up to the maximum. The minimum number of allocated buffers
-is ST_EXTRA_DEVS (in hosts.h) (unless this number exceeds the defined
-maximum). This ensures some functionality also for the drives found
-after tape driver initialization (a SCSI adapter driver is loaded as a
-module). The default for ST_EXTRA_DEVS is two.
+initialized up to the maximum.
 
 The driver tries to allocate new buffers at run-time if
 necessary. These buffers are freed after use. If the maximum number of
index 1de7686dc2a1b2521cabfc5e7d59a663dd172487..8df062781ee762693c89dc2a143d642543fe5195 100644 (file)
@@ -6,12 +6,13 @@
    Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
    Contribution and ideas from several people including (in alphabetical
    order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
-   Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
+   Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and
+   Eric Youngdale.
 
    Copyright 1992 - 2000 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Tue Feb 29 20:47:03 2000 by makisara@kai.makisara.local
+   Last modified: Mon Mar 13 21:15:29 2000 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
@@ -125,14 +126,17 @@ DEB( static int debugging = DEBUG; )
    24 bits) */
 #define SET_DENS_AND_BLK 0x10001
 
+#define ST_DEV_ARR_LUMP  6
+static rwlock_t st_dev_arr_lock = RW_LOCK_UNLOCKED;
+
 static int st_nbr_buffers;
-static ST_buffer **st_buffers;
+static ST_buffer **st_buffers = NULL;
 static int st_buffer_size = ST_BUFFER_SIZE;
 static int st_write_threshold = ST_WRITE_THRESHOLD;
 static int st_max_buffers = ST_MAX_BUFFERS;
 static int st_max_sg_segs = ST_MAX_SG;
 
-static Scsi_Tape *scsi_tapes = NULL;
+static Scsi_Tape **scsi_tapes = NULL;
 
 static int modes_defined = FALSE;
 
@@ -161,16 +165,14 @@ struct Scsi_Device_Template st_template =
 
 static int st_compression(Scsi_Tape *, int);
 
-static int find_partition(struct inode *);
-static int update_partition(struct inode *);
+static int find_partition(Scsi_Tape *);
+static int update_partition(Scsi_Tape *);
 
-static int st_int_ioctl(struct inode *inode, unsigned int cmd_in,
-                       unsigned long arg);
+static int st_int_ioctl(Scsi_Tape *, unsigned int, unsigned long);
 \f
 
-
 /* Convert the result to success code */
-static int st_chk_result(Scsi_Request * SRpnt)
+static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt)
 {
        int dev;
        int result = SRpnt->sr_result;
@@ -184,8 +186,10 @@ static int st_chk_result(Scsi_Request * SRpnt)
 
        if (driver_byte(result) & DRIVER_SENSE)
                scode = sense[2] & 0x0f;
-       else
+       else {
+               sense[0] = 0;
                scode = 0;
+       }
 
        dev = TAPE_NR(SRpnt->sr_request.rq_dev);
         DEB(
@@ -224,8 +228,8 @@ static int st_chk_result(Scsi_Request * SRpnt)
            && SRpnt->sr_cmnd[0] != WRITE_FILEMARKS
 #endif
            ) {
-               scsi_tapes[dev].recover_count++;
-               scsi_tapes[dev].mt_status->mt_erreg += (1 << MT_ST_SOFTERR_SHIFT);
+               STp->recover_count++;
+               STp->recover_reg++;
 
                 DEB(
                if (debugging) {
@@ -236,7 +240,7 @@ static int st_chk_result(Scsi_Request * SRpnt)
                        else
                                stp = "ioctl";
                        printk(ST_DEB_MSG "st%d: Recovered %s error (%d).\n", dev, stp,
-                              scsi_tapes[dev].recover_count);
+                              STp->recover_count);
                } ) /* end DEB */
 
                if ((sense[2] & 0xe0) == 0)
@@ -254,7 +258,9 @@ static void st_sleep_done(Scsi_Cmnd * SCpnt)
        Scsi_Tape *STp;
 
        if ((st_nbr = TAPE_NR(SCpnt->request.rq_dev)) < st_template.nr_dev) {
-               STp = &(scsi_tapes[st_nbr]);
+               read_lock(&st_dev_arr_lock);
+               STp = scsi_tapes[st_nbr];
+               read_unlock(&st_dev_arr_lock);
                if ((STp->buffer)->writing &&
                    (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
                    (SCpnt->sense_buffer[2] & 0x40)) {
@@ -330,7 +336,7 @@ static Scsi_Request *
        if (do_wait) {
                down(SRpnt->sr_request.sem);
                SRpnt->sr_request.sem = NULL;
-               (STp->buffer)->syscall_result = st_chk_result(SRpnt);
+               (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
        }
        return SRpnt;
 }
@@ -354,7 +360,7 @@ static void write_behind_check(Scsi_Tape * STp)
        down(&(STp->sem));
        (STp->buffer)->last_SRpnt->sr_request.sem = NULL;
 
-       (STp->buffer)->syscall_result = st_chk_result((STp->buffer)->last_SRpnt);
+       (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
        scsi_release_request((STp->buffer)->last_SRpnt);
 
        if (STbuffer->writing < STbuffer->buffer_bytes)
@@ -491,15 +497,12 @@ static int flush_write_buffer(Scsi_Tape * STp)
 
 /* Flush the tape buffer. The tape will be positioned correctly unless
    seek_next is true. */
-static int flush_buffer(struct inode *inode, struct file *filp, int seek_next)
+static int flush_buffer(Scsi_Tape *STp, int seek_next)
 {
        int backspace, result;
-       Scsi_Tape *STp;
        ST_buffer *STbuffer;
        ST_partstat *STps;
-       int dev = TAPE_NR(inode->i_rdev);
 
-       STp = &(scsi_tapes[dev]);
        STbuffer = STp->buffer;
 
        /*
@@ -538,7 +541,7 @@ static int flush_buffer(struct inode *inode, struct file *filp, int seek_next)
                        }
                }
                if (!result && backspace > 0)
-                       result = st_int_ioctl(inode, MTBSR, backspace);
+                       result = st_int_ioctl(STp, MTBSR, backspace);
        } else if (STps->eof == ST_FM_HIT) {
                if (STps->drv_file >= 0)
                        STps->drv_file++;
@@ -550,11 +553,11 @@ static int flush_buffer(struct inode *inode, struct file *filp, int seek_next)
 }
 \f
 /* Set the mode parameters */
-static int set_mode_densblk(struct inode *inode, Scsi_Tape * STp, ST_mode * STm)
+static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm)
 {
        int set_it = FALSE;
        unsigned long arg;
-       int dev = TAPE_NR(inode->i_rdev);
+       int dev = TAPE_NR(STp->devt);
 
        if (!STp->density_changed &&
            STm->default_density >= 0 &&
@@ -572,7 +575,7 @@ static int set_mode_densblk(struct inode *inode, Scsi_Tape * STp, ST_mode * STm)
        } else
                arg |= STp->block_size;
        if (set_it &&
-           st_int_ioctl(inode, SET_DENS_AND_BLK, arg)) {
+           st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {
                printk(KERN_WARNING
                       "st%d: Can't set default block size to %d bytes and density %x.\n",
                       dev, STm->default_blksize, STm->default_density);
@@ -597,22 +600,26 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
        int dev = TAPE_NR(inode->i_rdev);
        int mode = TAPE_MODE(inode->i_rdev);
 
-       if (dev >= st_template.dev_max || !scsi_tapes[dev].device)
+       read_lock(&st_dev_arr_lock);
+       STp = scsi_tapes[dev];
+       if (dev >= st_template.dev_max || STp == NULL) {
+               read_unlock(&st_dev_arr_lock);
                return (-ENXIO);
+       }
+       read_unlock(&st_dev_arr_lock);
 
-       if (!scsi_block_when_processing_errors(scsi_tapes[dev].device)) {
+       if (!scsi_block_when_processing_errors(STp->device)) {
                return -ENXIO;
        }
-       STp = &(scsi_tapes[dev]);
        if (STp->in_use) {
                DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
                return (-EBUSY);
        }
        STp->in_use = 1;
-       STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+       STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
 
-       if (scsi_tapes[dev].device->host->hostt->module)
-               __MOD_INC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+       if (STp->device->host->hostt->module)
+               __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
        if (st_template.module)
                __MOD_INC_USE_COUNT(st_template.module);
 
@@ -626,10 +633,14 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
 
        /* Allocate a buffer for this user */
        need_dma_buffer = STp->restr_dma;
+       read_lock(&st_dev_arr_lock);
        for (i = 0; i < st_nbr_buffers; i++)
                if (!st_buffers[i]->in_use &&
-                   (!need_dma_buffer || st_buffers[i]->dma))
+                   (!need_dma_buffer || st_buffers[i]->dma)) {
+                       STp->buffer = st_buffers[i];
                        break;
+               }
+       read_unlock(&st_dev_arr_lock);
        if (i >= st_nbr_buffers) {
                STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
                if (STp->buffer == NULL) {
@@ -637,8 +648,8 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                        retval = (-EBUSY);
                        goto err_out;
                }
-       } else
-               STp->buffer = st_buffers[i];
+       }
+
        (STp->buffer)->in_use = 1;
        (STp->buffer)->writing = 0;
        (STp->buffer)->syscall_result = 0;
@@ -824,7 +835,7 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                   partition support has been enabled. */
                 DEBC(printk(ST_DEB_MSG
                             "st%d: Updating partition number in status.\n", dev));
-               if ((STp->partition = find_partition(inode)) < 0) {
+               if ((STp->partition = find_partition(STp)) < 0) {
                        retval = STp->partition;
                        goto err_out;
                }
@@ -836,11 +847,11 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                STp->density_changed = STp->blksize_changed = FALSE;
                STp->compression_changed = FALSE;
                if (!(STm->defaults_for_writes) &&
-                   (retval = set_mode_densblk(inode, STp, STm)) < 0)
+                   (retval = set_mode_densblk(STp, STm)) < 0)
                    goto err_out;
 
                if (STp->default_drvbuffer != 0xff) {
-                       if (st_int_ioctl(inode, MTSETDRVBUFFER, STp->default_drvbuffer))
+                       if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))
                                printk(KERN_WARNING
                                        "st%d: Can't set default drive buffering to %d.\n",
                                       dev, STp->default_drvbuffer);
@@ -855,8 +866,8 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                STp->buffer = NULL;
        }
        STp->in_use = 0;
-       if (scsi_tapes[dev].device->host->hostt->module)
-           __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+       if (STp->device->host->hostt->module)
+           __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
        if (st_template.module)
            __MOD_DEC_USE_COUNT(st_template.module);
        return retval;
@@ -882,7 +893,9 @@ static int scsi_tape_flush(struct file *filp)
                return 0;
 
        dev = TAPE_NR(devt);
-       STp = &(scsi_tapes[dev]);
+       read_lock(&st_dev_arr_lock);
+       STp = scsi_tapes[dev];
+       read_unlock(&st_dev_arr_lock);
        STm = &(STp->modes[STp->current_mode]);
        STps = &(STp->ps[STp->partition]);
 
@@ -893,7 +906,7 @@ static int scsi_tape_flush(struct file *filp)
        }
 
        if (STp->can_partitions &&
-           (result2 = update_partition(inode)) < 0) {
+           (result2 = update_partition(STp)) < 0) {
                 DEBC(printk(ST_DEB_MSG
                                "st%d: update_partition at close failed.\n", dev));
                if (result == 0)
@@ -950,7 +963,7 @@ static int scsi_tape_flush(struct file *filp)
                STps = &(STp->ps[STp->partition]);
                if (!STm->sysv || STps->rw != ST_READING) {
                        if (STp->can_bsr)
-                               result = flush_buffer(inode, filp, 0);
+                               result = flush_buffer(STp, 0);
                        else if (STps->eof == ST_FM_HIT) {
                                result = cross_eof(STp, FALSE);
                                if (result) {
@@ -973,7 +986,7 @@ static int scsi_tape_flush(struct file *filp)
 
       out:
        if (STp->rew_at_close) {
-               result2 = st_int_ioctl(inode, MTREW, 1);
+               result2 = st_int_ioctl(STp, MTREW, 1);
                if (result == 0)
                        result = result2;
        }
@@ -991,10 +1004,12 @@ static int scsi_tape_close(struct inode *inode, struct file *filp)
        int dev;
 
        dev = TAPE_NR(devt);
-       STp = &(scsi_tapes[dev]);
+       read_lock(&st_dev_arr_lock);
+       STp = scsi_tapes[dev];
+       read_unlock(&st_dev_arr_lock);
 
        if (STp->door_locked == ST_LOCKED_AUTO)
-               st_int_ioctl(inode, MTUNLOCK, 0);
+               st_int_ioctl(STp, MTUNLOCK, 0);
 
        if (STp->buffer != NULL) {
                normalize_buffer(STp->buffer);
@@ -1002,8 +1017,8 @@ static int scsi_tape_close(struct inode *inode, struct file *filp)
        }
 
        STp->in_use = 0;
-       if (scsi_tapes[dev].device->host->hostt->module)
-               __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+       if (STp->device->host->hostt->module)
+               __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
        if (st_template.module)
                __MOD_DEC_USE_COUNT(st_template.module);
 
@@ -1028,7 +1043,9 @@ static ssize_t
        ST_partstat *STps;
        int dev = TAPE_NR(inode->i_rdev);
 
-       STp = &(scsi_tapes[dev]);
+       read_lock(&st_dev_arr_lock);
+       STp = scsi_tapes[dev];
+       read_unlock(&st_dev_arr_lock);
 
        /*
         * If we are in the middle of error recovery, don't let anyone
@@ -1079,7 +1096,7 @@ static ssize_t
        }
 
        if (STp->can_partitions &&
-           (retval = update_partition(inode)) < 0)
+           (retval = update_partition(STp)) < 0)
                return retval;
        STps = &(STp->ps[STp->partition]);
 
@@ -1092,17 +1109,17 @@ static ssize_t
                return (-EOVERFLOW);
 
        if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
-           !st_int_ioctl(inode, MTLOCK, 0))
+           !st_int_ioctl(STp, MTLOCK, 0))
                STp->door_locked = ST_LOCKED_AUTO;
 
        if (STps->rw == ST_READING) {
-               retval = flush_buffer(inode, filp, 0);
+               retval = flush_buffer(STp, 0);
                if (retval)
                        return retval;
                STps->rw = ST_WRITING;
        } else if (STps->rw != ST_WRITING &&
                   STps->drv_file == 0 && STps->drv_block == 0) {
-               if ((retval = set_mode_densblk(inode, STp, STm)) < 0)
+               if ((retval = set_mode_densblk(STp, STm)) < 0)
                        return retval;
                if (STm->default_compression != ST_DONT_TOUCH &&
                    !(STp->compression_changed)) {
@@ -1328,21 +1345,19 @@ static ssize_t
 /* Read data from the tape. Returns zero in the normal case, one if the
    eof status has changed, and the negative error code in case of a
    fatal error. Otherwise updates the buffer and the eof state. */
-static long read_tape(struct inode *inode, long count, Scsi_Request ** aSRpnt)
+static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt)
 {
        int transfer, blks, bytes;
        static unsigned char cmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt;
-       Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
-       int dev = TAPE_NR(inode->i_rdev);
+       int dev = TAPE_NR(STp->devt);
        int retval = 0;
 
        if (count == 0)
                return 0;
 
-       STp = &(scsi_tapes[dev]);
        STm = &(STp->modes[STp->current_mode]);
        STps = &(STp->ps[STp->partition]);
        if (STps->eof == ST_FM_HIT)
@@ -1418,7 +1433,7 @@ static long read_tape(struct inode *inode, long count, Scsi_Request ** aSRpnt)
                                                        printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);
                                                        if (STps->drv_block >= 0)
                                                                STps->drv_block += blks - transfer + 1;
-                                                       st_int_ioctl(inode, MTBSR, 1);
+                                                       st_int_ioctl(STp, MTBSR, 1);
                                                        return (-EIO);
                                                }
                                                /* We have some data, deliver it */
@@ -1429,7 +1444,7 @@ static long read_tape(struct inode *inode, long count, Scsi_Request ** aSRpnt)
                                                             dev, count, (STp->buffer)->buffer_bytes));
                                                if (STps->drv_block >= 0)
                                                        STps->drv_block += 1;
-                                               if (st_int_ioctl(inode, MTBSR, 1))
+                                               if (st_int_ioctl(STp, MTBSR, 1))
                                                        return (-EIO);
                                        }
                                } else if (SRpnt->sr_sense_buffer[2] & 0x80) {  /* FM overrides EOM */
@@ -1509,7 +1524,9 @@ static ssize_t
        ST_partstat *STps;
        int dev = TAPE_NR(inode->i_rdev);
 
-       STp = &(scsi_tapes[dev]);
+       read_lock(&st_dev_arr_lock);
+       STp = scsi_tapes[dev];
+       read_unlock(&st_dev_arr_lock);
 
        /*
         * If we are in the middle of error recovery, don't let anyone
@@ -1542,7 +1559,7 @@ static ssize_t
        } ) /* end DEB */
 
        if (STp->can_partitions &&
-           (total = update_partition(inode)) < 0)
+           (total = update_partition(STp)) < 0)
                return total;
 
        if (STp->block_size == 0 &&
@@ -1555,12 +1572,12 @@ static ssize_t
                return (-EIO);  /* Read must be integral number of blocks */
 
        if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
-           !st_int_ioctl(inode, MTLOCK, 0))
+           !st_int_ioctl(STp, MTLOCK, 0))
                STp->door_locked = ST_LOCKED_AUTO;
 
        STps = &(STp->ps[STp->partition]);
        if (STps->rw == ST_WRITING) {
-               transfer = flush_buffer(inode, filp, 0);
+               transfer = flush_buffer(STp, 0);
                if (transfer)
                        return transfer;
                STps->rw = ST_READING;
@@ -1596,7 +1613,7 @@ static ssize_t
 
                /* Get new data if the buffer is empty */
                if ((STp->buffer)->buffer_bytes == 0) {
-                       special = read_tape(inode, count - total, &SRpnt);
+                       special = read_tape(STp, count - total, &SRpnt);
                        if (special < 0) {      /* No need to continue read */
                                if (SRpnt != NULL) {
                                        scsi_release_request(SRpnt);
@@ -1684,15 +1701,13 @@ static void st_log_options(Scsi_Tape * STp, ST_mode * STm, int dev)
 }
 
 
-static int st_set_options(struct inode *inode, long options)
+static int st_set_options(Scsi_Tape *STp, long options)
 {
        int value;
        long code;
-       Scsi_Tape *STp;
        ST_mode *STm;
-       int dev = TAPE_NR(inode->i_rdev);
+       int dev = TAPE_NR(STp->devt);
 
-       STp = &(scsi_tapes[dev]);
        STm = &(STp->modes[STp->current_mode]);
        if (!STm->defined) {
                memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
@@ -1823,95 +1838,146 @@ static int st_set_options(struct inode *inode, long options)
        return 0;
 }
 \f
+#define MODE_HEADER_LENGTH  4
 
-#define COMPRESSION_PAGE        0x0f
-#define COMPRESSION_PAGE_LENGTH 16
+/* Mode header and page byte offsets */
+#define MH_OFF_DATA_LENGTH     0
+#define MH_OFF_MEDIUM_TYPE     1
+#define MH_OFF_DEV_SPECIFIC    2
+#define MH_OFF_BDESCS_LENGTH   3
+#define MP_OFF_PAGE_NBR        0
+#define MP_OFF_PAGE_LENGTH     1
 
-#define MODE_HEADER_LENGTH  4
+/* Mode header and page bit masks */
+#define MH_BIT_WP              0x80
+#define MP_MSK_PAGE_NBR        0x3f
 
-#define DCE_MASK  0x80
-#define DCC_MASK  0x40
-#define RED_MASK  0x60
+/* Don't return block descriptors */
+#define MODE_SENSE_OMIT_BDESCS 0x08
 
+#define MODE_SELECT_PAGE_FORMAT 0x10
 
-/* Control the compression with mode page 15. Algorithm not changed if zero. */
-static int st_compression(Scsi_Tape * STp, int state)
+/* Read a mode page into the tape buffer. The block descriptors are included
+   if incl_block_descs is true. */
+static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs)
 {
-       int dev;
        unsigned char cmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt = NULL;
 
-       if (STp->ready != ST_READY)
-               return (-EIO);
-
-       /* Read the current page contents */
        memset(cmd, 0, MAX_COMMAND_SIZE);
        cmd[0] = MODE_SENSE;
-       cmd[1] = 8;
-       cmd[2] = COMPRESSION_PAGE;
-       cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
+       if (omit_block_descs)
+               cmd[1] = MODE_SENSE_OMIT_BDESCS;
+       cmd[2] = page;
+       cmd[4] = 255;
 
        SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ,
                           STp->timeout, 0, TRUE);
        if (SRpnt == NULL)
                return (STp->buffer)->syscall_result;
 
-       dev = TAPE_NR(SRpnt->sr_request.rq_dev);
+       scsi_release_request(SRpnt);
 
-       if ((STp->buffer)->syscall_result != 0) {
+       return (STp->buffer)->syscall_result;
+}
+
+
+/* Send the mode page in the tape buffer to the drive. Assumes that the mode data
+   in the buffer is correctly formatted. */
+static int write_mode_page(Scsi_Tape *STp, int page)
+{
+       int pgo;
+       unsigned char cmd[MAX_COMMAND_SIZE];
+       Scsi_Request *SRpnt = NULL;
+
+       memset(cmd, 0, MAX_COMMAND_SIZE);
+       cmd[0] = MODE_SELECT;
+       cmd[1] = MODE_SELECT_PAGE_FORMAT;
+       pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH];
+       cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2;
+
+       /* Clear reserved fields */
+       (STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0;
+       (STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0;
+       (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
+       (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
+
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
+                          STp->timeout, 0, TRUE);
+       if (SRpnt == NULL)
+               return (STp->buffer)->syscall_result;
+
+       scsi_release_request(SRpnt);
+
+       return (STp->buffer)->syscall_result;
+}
+
+
+#define COMPRESSION_PAGE        0x0f
+#define COMPRESSION_PAGE_LENGTH 16
+
+#define CP_OFF_DCE_DCC          2
+
+#define DCE_MASK  0x80
+#define DCC_MASK  0x40
+#define RED_MASK  0x60
+
+
+/* Control the compression with mode page 15. Algorithm not changed if zero.
+
+   The block descriptors are read and written because Sony SDT-7000 does not
+   work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
+   Including block descriptors should not cause any harm to other drives. */
+
+static int st_compression(Scsi_Tape * STp, int state)
+{
+       int retval;
+       int mpoffs;  /* Offset to mode page start */
+       unsigned char *b_data = (STp->buffer)->b_data;
+       DEB( int dev = TAPE_NR(STp->devt); )
+
+       if (STp->ready != ST_READY)
+               return (-EIO);
+
+       /* Read the current page contents */
+       retval = read_mode_page(STp, COMPRESSION_PAGE, FALSE);
+       if (retval) {
                 DEBC(printk(ST_DEB_MSG "st%d: Compression mode page not supported.\n",
                             dev));
-               scsi_release_request(SRpnt);
-               SRpnt = NULL;
                return (-EIO);
        }
+
+       mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH];
         DEBC(printk(ST_DEB_MSG "st%d: Compression state is %d.\n", dev,
-                    ((STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] & DCE_MASK ? 1 : 0)));
+                    (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
 
        /* Check if compression can be changed */
-       if (((STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] & DCC_MASK) == 0) {
+       if ((b_data[mpoffs + 2] & DCC_MASK) == 0) {
                 DEBC(printk(ST_DEB_MSG "st%d: Compression not supported.\n", dev));
-               scsi_release_request(SRpnt);
-               SRpnt = NULL;
                return (-EIO);
        }
 
        /* Do the change */
        if (state)
-               (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] |= DCE_MASK;
+               b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK;
        else
-               (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] &= ~DCE_MASK;
+               b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK;
 
-       memset(cmd, 0, MAX_COMMAND_SIZE);
-       cmd[0] = MODE_SELECT;
-       cmd[1] = 0x10;
-       cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
-
-       (STp->buffer)->b_data[0] = 0;   /* Reserved data length */
-       (STp->buffer)->b_data[1] = 0;   /* Reserved media type byte */
-       (STp->buffer)->b_data[MODE_HEADER_LENGTH] &= 0x3f;
-       SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
-                          STp->timeout, 0, TRUE);
-
-       if ((STp->buffer)->syscall_result != 0) {
+       retval = write_mode_page(STp, COMPRESSION_PAGE);
+       if (retval) {
                 DEBC(printk(ST_DEB_MSG "st%d: Compression change failed.\n", dev));
-               scsi_release_request(SRpnt);
-               SRpnt = NULL;
                return (-EIO);
        }
         DEBC(printk(ST_DEB_MSG "st%d: Compression state changed to %d.\n",
                       dev, state));
 
-       scsi_release_request(SRpnt);
-       SRpnt = NULL;
        STp->compression_changed = TRUE;
        return 0;
 }
 \f
 
 /* Internal ioctl function */
-static int st_int_ioctl(struct inode *inode,
-                       unsigned int cmd_in, unsigned long arg)
+static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg)
 {
        int timeout;
        long ltmp;
@@ -1919,13 +1985,11 @@ static int st_int_ioctl(struct inode *inode,
        int chg_eof = TRUE;
        unsigned char cmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt;
-       Scsi_Tape *STp;
        ST_partstat *STps;
        int fileno, blkno, at_sm, undone;
        int datalen = 0, direction = SCSI_DATA_NONE;
-       int dev = TAPE_NR(inode->i_rdev);
+       int dev = TAPE_NR(STp->devt);
 
-       STp = &(scsi_tapes[dev]);
        if (STp->ready != ST_READY && cmd_in != MTLOAD) {
                if (STp->ready == ST_NO_TAPE)
                        return (-ENOMEDIUM);
@@ -2120,7 +2184,7 @@ static int st_int_ioctl(struct inode *inode,
        case MTEOM:
                if (!STp->fast_mteom) {
                        /* space to the end of tape */
-                       ioctl_result = st_int_ioctl(inode, MTFSF, 0x3fff);
+                       ioctl_result = st_int_ioctl(STp, MTFSF, 0x3fff);
                        fileno = STps->drv_file;
                        if (STps->eof >= ST_EOD_1)
                                return 0;
@@ -2247,9 +2311,9 @@ static int st_int_ioctl(struct inode *inode,
                        STp->door_locked = ST_UNLOCKED;
 
                if (cmd_in == MTBSFM)
-                       ioctl_result = st_int_ioctl(inode, MTFSF, 1);
+                       ioctl_result = st_int_ioctl(STp, MTFSF, 1);
                else if (cmd_in == MTFSFM)
-                       ioctl_result = st_int_ioctl(inode, MTBSF, 1);
+                       ioctl_result = st_int_ioctl(STp, MTBSF, 1);
 
                if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
                        STp->block_size = arg & MT_ST_BLKSIZE_MASK;
@@ -2275,7 +2339,7 @@ static int st_int_ioctl(struct inode *inode,
                if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
                        STp->rew_at_close = 0;
                else if (cmd_in == MTLOAD) {
-                       STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+                       STp->rew_at_close = STp->autorew_dev;
                        for (i = 0; i < ST_NBR_PARTITIONS; i++) {
                                STp->ps[i].rw = ST_IDLE;
                                STp->ps[i].last_block_valid = FALSE;
@@ -2368,16 +2432,14 @@ static int st_int_ioctl(struct inode *inode,
 /* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
    structure. */
 
-static int get_location(struct inode *inode, unsigned int *block, int *partition,
+static int get_location(Scsi_Tape *STp, unsigned int *block, int *partition,
                        int logical)
 {
-       Scsi_Tape *STp;
-       int dev = TAPE_NR(inode->i_rdev);
        int result;
        unsigned char scmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt;
+       DEB( int dev = TAPE_NR(STp->devt); )
 
-       STp = &(scsi_tapes[dev]);
        if (STp->ready != ST_READY)
                return (-EIO);
 
@@ -2430,19 +2492,17 @@ static int get_location(struct inode *inode, unsigned int *block, int *partition
 
 /* Set the tape block and partition. Negative partition means that only the
    block should be set in vendor specific way. */
-static int set_location(struct inode *inode, unsigned int block, int partition,
+static int set_location(Scsi_Tape *STp, unsigned int block, int partition,
                        int logical)
 {
-       Scsi_Tape *STp;
        ST_partstat *STps;
-       int dev = TAPE_NR(inode->i_rdev);
        int result, p;
        unsigned int blk;
        int timeout;
        unsigned char scmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt;
+       DEB( int dev = TAPE_NR(STp->devt); )
 
-       STp = &(scsi_tapes[dev]);
        if (STp->ready != ST_READY)
                return (-EIO);
        timeout = STp->long_timeout;
@@ -2458,7 +2518,7 @@ static int set_location(struct inode *inode, unsigned int block, int partition,
            partition >= ST_NBR_PARTITIONS)
                return (-EINVAL);
        if (partition != STp->partition) {
-               if (get_location(inode, &blk, &p, 1))
+               if (get_location(STp, &blk, &p, 1))
                        STps->last_block_valid = FALSE;
                else {
                        STps->last_block_valid = TRUE;
@@ -2508,7 +2568,7 @@ static int set_location(struct inode *inode, unsigned int block, int partition,
                result = (-EIO);
                if (STp->can_partitions &&
                    (STp->device)->scsi_level >= SCSI_2 &&
-                   (p = find_partition(inode)) >= 0)
+                   (p = find_partition(STp)) >= 0)
                        STp->partition = p;
        } else {
                if (STp->can_partitions) {
@@ -2535,12 +2595,12 @@ static int set_location(struct inode *inode, unsigned int block, int partition,
 
 /* Find the current partition number for the drive status. Called from open and
    returns either partition number of negative error code. */
-static int find_partition(struct inode *inode)
+static int find_partition(Scsi_Tape *STp)
 {
        int i, partition;
        unsigned int block;
 
-       if ((i = get_location(inode, &block, &partition, 1)) < 0)
+       if ((i = get_location(STp, &block, &partition, 1)) < 0)
                return i;
        if (partition >= ST_NBR_PARTITIONS)
                return (-EIO);
@@ -2549,60 +2609,52 @@ static int find_partition(struct inode *inode)
 
 
 /* Change the partition if necessary */
-static int update_partition(struct inode *inode)
+static int update_partition(Scsi_Tape *STp)
 {
-       int dev = TAPE_NR(inode->i_rdev);
-       Scsi_Tape *STp;
        ST_partstat *STps;
 
-       STp = &(scsi_tapes[dev]);
        if (STp->partition == STp->new_partition)
                return 0;
        STps = &(STp->ps[STp->new_partition]);
        if (!STps->last_block_valid)
                STps->last_block_visited = 0;
-       return set_location(inode, STps->last_block_visited, STp->new_partition, 1);
+       return set_location(STp, STps->last_block_visited, STp->new_partition, 1);
 }
 \f
 /* Functions for reading and writing the medium partition mode page. These
    seem to work with Wangtek 6200HS and HP C1533A. */
 
 #define PART_PAGE   0x11
-#define PART_PAGE_LENGTH 10
+#define PART_PAGE_FIXED_LENGTH 8
+
+#define PP_OFF_MAX_ADD_PARTS   2
+#define PP_OFF_NBR_ADD_PARTS   3
+#define PP_OFF_FLAGS           4
+#define PP_OFF_PART_UNITS      6
+#define PP_OFF_RESERVED        7
+
+#define PP_BIT_IDP             0x20
+#define PP_MSK_PSUM_MB         0x10
 
 /* Get the number of partitions on the tape. As a side effect reads the
    mode page into the tape buffer. */
-static int nbr_partitions(struct inode *inode)
+static int nbr_partitions(Scsi_Tape *STp)
 {
-       int dev = TAPE_NR(inode->i_rdev), result;
-       Scsi_Tape *STp;
-       Scsi_Request *SRpnt = NULL;
-       unsigned char cmd[MAX_COMMAND_SIZE];
+       int result;
+       DEB( int dev = TAPE_NR(STp->devt) );
 
-       STp = &(scsi_tapes[dev]);
        if (STp->ready != ST_READY)
                return (-EIO);
 
-       memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
-       cmd[0] = MODE_SENSE;
-       cmd[1] = 8;             /* Page format */
-       cmd[2] = PART_PAGE;
-       cmd[4] = 200;
-
-       SRpnt = st_do_scsi(SRpnt, STp, cmd, 200, SCSI_DATA_READ, STp->timeout,
-                          MAX_READY_RETRIES, TRUE);
-       if (SRpnt == NULL)
-               return (STp->buffer)->syscall_result;
+       result = read_mode_page(STp, PART_PAGE, TRUE);
 
-       scsi_release_request(SRpnt);
-       SRpnt = NULL;
-
-       if ((STp->buffer)->syscall_result != 0) {
+       if (result) {
                 DEBC(printk(ST_DEB_MSG "st%d: Can't read medium partition page.\n",
                             dev));
                result = (-EIO);
        } else {
-               result = (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] + 1;
+               result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
+                                             PP_OFF_NBR_ADD_PARTS] + 1;
                 DEBC(printk(ST_DEB_MSG "st%d: Number of partitions %d.\n", dev, result));
        }
 
@@ -2611,62 +2663,69 @@ static int nbr_partitions(struct inode *inode)
 
 
 /* Partition the tape into two partitions if size > 0 or one partition if
-   size == 0 */
-static int partition_tape(struct inode *inode, int size)
+   size == 0.
+
+   The block descriptors are read and written because Sony SDT-7000 does not
+   work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
+
+   My HP C1533A drive returns only one partition size field. This is used to
+   set the size of partition 1. There is no size field for the default partition.
+   Michael Schaefer's Sony SDT-7000 returns two descriptors and the second is
+   used to set the size of partition 1 (this is what the SCSI-3 standard specifies).
+   The following algorithm is used to accomodate both drives: if the number of
+   partition size fields is greater than the maximum number of additional partitions
+   in the mode page, the second field is used. Otherwise the first field is used.
+ */
+static int partition_tape(Scsi_Tape *STp, int size)
 {
-       int dev = TAPE_NR(inode->i_rdev), result;
-       int length;
-       Scsi_Tape *STp;
-       Scsi_Request *SRpnt = NULL;
-       unsigned char cmd[MAX_COMMAND_SIZE], *bp;
+       int dev = TAPE_NR(STp->devt), result;
+       int pgo, psd_cnt, psdo;
+       unsigned char *bp;
 
-       if ((result = nbr_partitions(inode)) < 0)
+       result = read_mode_page(STp, PART_PAGE, FALSE);
+       if (result) {
+               DEBC(printk(ST_DEB_MSG "st%d: Can't read partition mode page.\n", dev));
                return result;
-       STp = &(scsi_tapes[dev]);
-
+       }
        /* The mode page is in the buffer. Let's modify it and write it. */
-       bp = &((STp->buffer)->b_data[0]);
+       bp = (STp->buffer)->b_data;
+       pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
+       DEBC(printk(ST_DEB_MSG "st%d: Partition page length is %d bytes.\n",
+                   dev, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
+
+       psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
+       psdo = pgo + PART_PAGE_FIXED_LENGTH;
+       if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
+               bp[psdo] = bp[psdo + 1] = 0xff;  /* Rest of the tape */
+               psdo += 2;
+       }
+       memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
+
+       DEBC(printk("st%d: psd_cnt %d, max.parts %d, nbr_parts %d\n", dev,
+                   psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
+                   bp[pgo + PP_OFF_NBR_ADD_PARTS]));
+
        if (size <= 0) {
-               length = 8;
-               bp[MODE_HEADER_LENGTH + 3] = 0;
+               bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
                 DEBC(printk(ST_DEB_MSG "st%d: Formatting tape with one partition.\n",
                             dev));
        } else {
-               length = 10;
-               bp[MODE_HEADER_LENGTH + 3] = 1;
-               bp[MODE_HEADER_LENGTH + 8] = (size >> 8) & 0xff;
-               bp[MODE_HEADER_LENGTH + 9] = size & 0xff;
+               bp[psdo] = (size >> 8) & 0xff;
+               bp[psdo + 1] = size & 0xff;
+               bp[pgo + 3] = 1;
                 DEBC(printk(ST_DEB_MSG
-                            "st%d: Formatting tape with two partition (1 = %d MB).\n",
+                            "st%d: Formatting tape with two partitions (1 = %d MB).\n",
                             dev, size));
        }
-       bp[MODE_HEADER_LENGTH + 6] = 0;
-       bp[MODE_HEADER_LENGTH + 7] = 0;
-       bp[MODE_HEADER_LENGTH + 4] = 0x30;      /* IDP | PSUM = MB */
-
-       bp[0] = 0;
-       bp[1] = 0;
-       bp[MODE_HEADER_LENGTH] &= 0x3f;
-       bp[MODE_HEADER_LENGTH + 1] = length - 2;
+       bp[pgo + PP_OFF_PART_UNITS] = 0;
+       bp[pgo + PP_OFF_RESERVED] = 0;
+       bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
 
-       memset(cmd, 0, MAX_COMMAND_SIZE);
-       cmd[0] = MODE_SELECT;
-       cmd[1] = 0x10;
-       cmd[4] = length + MODE_HEADER_LENGTH;
-
-       SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
-                          STp->long_timeout, MAX_READY_RETRIES, TRUE);
-       if (SRpnt == NULL)
-               return (STp->buffer)->syscall_result;
-
-       scsi_release_request(SRpnt);
-       SRpnt = NULL;
-
-       if ((STp->buffer)->syscall_result != 0) {
+       result = write_mode_page(STp, PART_PAGE);
+       if (result) {
                printk(KERN_INFO "st%d: Partitioning of tape failed.\n", dev);
                result = (-EIO);
-       } else
-               result = 0;
+       }
 
        return result;
 }
@@ -2679,14 +2738,15 @@ static int st_ioctl(struct inode *inode, struct file *file,
 {
        int i, cmd_nr, cmd_type, bt;
        unsigned int blk;
-       struct mtop mtc;
-       struct mtpos mt_pos;
        Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
        int dev = TAPE_NR(inode->i_rdev);
 
-       STp = &(scsi_tapes[dev]);
+       read_lock(&st_dev_arr_lock);
+       STp = scsi_tapes[dev];
+       read_unlock(&st_dev_arr_lock);
+
         DEB(
        if (debugging && !STp->in_use) {
                printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
@@ -2709,6 +2769,8 @@ static int st_ioctl(struct inode *inode, struct file *file,
        cmd_nr = _IOC_NR(cmd_in);
 
        if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
+               struct mtop mtc;
+
                if (_IOC_SIZE(cmd_in) != sizeof(mtc))
                        return (-EINVAL);
 
@@ -2751,7 +2813,7 @@ static int st_ioctl(struct inode *inode, struct file *file,
                                    mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
                                    mtc.mt_op == MTCOMPRESSION;
                        }
-                       i = flush_buffer(inode, file, i);
+                       i = flush_buffer(STp, i);
                        if (i < 0)
                                return i;
                } else {
@@ -2770,7 +2832,7 @@ static int st_ioctl(struct inode *inode, struct file *file,
                        STp->device->was_reset = 0;
                        if (STp->door_locked != ST_UNLOCKED &&
                            STp->door_locked != ST_LOCK_FAILS) {
-                               if (st_int_ioctl(inode, MTLOCK, 0)) {
+                               if (st_int_ioctl(STp, MTLOCK, 0)) {
                                        printk(KERN_NOTICE
                                                "st%d: Could not relock door after bus reset.\n",
                                               dev);
@@ -2785,18 +2847,18 @@ static int st_ioctl(struct inode *inode, struct file *file,
                        STps->rw = ST_IDLE;     /* Prevent automatic WEOF and fsf */
 
                if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
-                       st_int_ioctl(inode, MTUNLOCK, 0);       /* Ignore result! */
+                       st_int_ioctl(STp, MTUNLOCK, 0); /* Ignore result! */
 
                if (mtc.mt_op == MTSETDRVBUFFER &&
                    (mtc.mt_count & MT_ST_OPTIONS) != 0)
-                       return st_set_options(inode, mtc.mt_count);
+                       return st_set_options(STp, mtc.mt_count);
 
                if (mtc.mt_op == MTSETPART) {
                        if (!STp->can_partitions ||
                            mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
                                return (-EINVAL);
                        if (mtc.mt_count >= STp->nbr_partitions &&
-                       (STp->nbr_partitions = nbr_partitions(inode)) < 0)
+                       (STp->nbr_partitions = nbr_partitions(STp)) < 0)
                                return (-EIO);
                        if (mtc.mt_count >= STp->nbr_partitions)
                                return (-EINVAL);
@@ -2807,8 +2869,8 @@ static int st_ioctl(struct inode *inode, struct file *file,
                if (mtc.mt_op == MTMKPART) {
                        if (!STp->can_partitions)
                                return (-EINVAL);
-                       if ((i = st_int_ioctl(inode, MTREW, 0)) < 0 ||
-                           (i = partition_tape(inode, mtc.mt_count)) < 0)
+                       if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
+                           (i = partition_tape(STp, mtc.mt_count)) < 0)
                                return i;
                        for (i = 0; i < ST_NBR_PARTITIONS; i++) {
                                STp->ps[i].rw = ST_IDLE;
@@ -2822,93 +2884,97 @@ static int st_ioctl(struct inode *inode, struct file *file,
                }
 
                if (mtc.mt_op == MTSEEK) {
-                       i = set_location(inode, mtc.mt_count, STp->new_partition, 0);
+                       i = set_location(STp, mtc.mt_count, STp->new_partition, 0);
                        if (!STp->can_partitions)
                                STp->ps[0].rw = ST_IDLE;
                        return i;
                }
 
                if (STp->can_partitions && STp->ready == ST_READY &&
-                   (i = update_partition(inode)) < 0)
+                   (i = update_partition(STp)) < 0)
                        return i;
 
                if (mtc.mt_op == MTCOMPRESSION)
                        return st_compression(STp, (mtc.mt_count & 1));
                else
-                       return st_int_ioctl(inode, mtc.mt_op, mtc.mt_count);
+                       return st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
        }
        if (!STm->defined)
                return (-ENXIO);
 
-       if ((i = flush_buffer(inode, file, FALSE)) < 0)
+       if ((i = flush_buffer(STp, FALSE)) < 0)
                return i;
        if (STp->can_partitions &&
-           (i = update_partition(inode)) < 0)
+           (i = update_partition(STp)) < 0)
                return i;
 
        if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
+               struct mtget mt_status;
 
                if (_IOC_SIZE(cmd_in) != sizeof(struct mtget))
                         return (-EINVAL);
 
-               (STp->mt_status)->mt_dsreg =
+               mt_status.mt_type = STp->tape_type;
+               mt_status.mt_dsreg =
                    ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
                    ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
-               (STp->mt_status)->mt_blkno = STps->drv_block;
-               (STp->mt_status)->mt_fileno = STps->drv_file;
+               mt_status.mt_blkno = STps->drv_block;
+               mt_status.mt_fileno = STps->drv_file;
                if (STp->block_size != 0) {
                        if (STps->rw == ST_WRITING)
-                               (STp->mt_status)->mt_blkno +=
+                               mt_status.mt_blkno +=
                                    (STp->buffer)->buffer_bytes / STp->block_size;
                        else if (STps->rw == ST_READING)
-                               (STp->mt_status)->mt_blkno -=
+                               mt_status.mt_blkno -=
                                         ((STp->buffer)->buffer_bytes +
                                          STp->block_size - 1) / STp->block_size;
                }
 
-               (STp->mt_status)->mt_gstat = 0;
+               mt_status.mt_gstat = 0;
                if (STp->drv_write_prot)
-                       (STp->mt_status)->mt_gstat |= GMT_WR_PROT(0xffffffff);
-               if ((STp->mt_status)->mt_blkno == 0) {
-                       if ((STp->mt_status)->mt_fileno == 0)
-                               (STp->mt_status)->mt_gstat |= GMT_BOT(0xffffffff);
+                       mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
+               if (mt_status.mt_blkno == 0) {
+                       if (mt_status.mt_fileno == 0)
+                               mt_status.mt_gstat |= GMT_BOT(0xffffffff);
                        else
-                               (STp->mt_status)->mt_gstat |= GMT_EOF(0xffffffff);
+                               mt_status.mt_gstat |= GMT_EOF(0xffffffff);
                }
-               (STp->mt_status)->mt_resid = STp->partition;
+               mt_status.mt_erreg = (STp->recover_reg << MT_ST_SOFTERR_SHIFT);
+               mt_status.mt_resid = STp->partition;
                if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
-                       (STp->mt_status)->mt_gstat |= GMT_EOT(0xffffffff);
+                       mt_status.mt_gstat |= GMT_EOT(0xffffffff);
                else if (STps->eof >= ST_EOM_OK)
-                       (STp->mt_status)->mt_gstat |= GMT_EOD(0xffffffff);
+                       mt_status.mt_gstat |= GMT_EOD(0xffffffff);
                if (STp->density == 1)
-                       (STp->mt_status)->mt_gstat |= GMT_D_800(0xffffffff);
+                       mt_status.mt_gstat |= GMT_D_800(0xffffffff);
                else if (STp->density == 2)
-                       (STp->mt_status)->mt_gstat |= GMT_D_1600(0xffffffff);
+                       mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
                else if (STp->density == 3)
-                       (STp->mt_status)->mt_gstat |= GMT_D_6250(0xffffffff);
+                       mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
                if (STp->ready == ST_READY)
-                       (STp->mt_status)->mt_gstat |= GMT_ONLINE(0xffffffff);
+                       mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
                if (STp->ready == ST_NO_TAPE)
-                       (STp->mt_status)->mt_gstat |= GMT_DR_OPEN(0xffffffff);
+                       mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
                if (STps->at_sm)
-                       (STp->mt_status)->mt_gstat |= GMT_SM(0xffffffff);
+                       mt_status.mt_gstat |= GMT_SM(0xffffffff);
                if (STm->do_async_writes ||
                     (STm->do_buffer_writes && STp->block_size != 0) ||
                    STp->drv_buffer != 0)
-                       (STp->mt_status)->mt_gstat |= GMT_IM_REP_EN(0xffffffff);
+                       mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
 
-               i = copy_to_user((char *) arg, (char *) (STp->mt_status),
+               i = copy_to_user((char *) arg, (char *) &(mt_status),
                                 sizeof(struct mtget));
                if (i)
                        return (-EFAULT);
 
-               (STp->mt_status)->mt_erreg = 0;         /* Clear after read */
+               STp->recover_reg = 0;           /* Clear after read */
                return 0;
        }                       /* End of MTIOCGET */
        if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
+               struct mtpos mt_pos;
                if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
                         return (-EINVAL);
-               if ((i = get_location(inode, &blk, &bt, 0)) < 0)
+               if ((i = get_location(STp, &blk, &bt, 0)) < 0)
                        return i;
                mt_pos.mt_blkno = blk;
                i = copy_to_user((char *) arg, (char *) (&mt_pos), sizeof(struct mtpos));
@@ -2920,15 +2986,21 @@ static int st_ioctl(struct inode *inode, struct file *file,
 }
 \f
 
-/* Try to allocate a new tape buffer */
+/* Try to allocate a new tape buffer. Calling function must not hold
+   dev_arr_lock. */
 static ST_buffer *
  new_tape_buffer(int from_initialization, int need_dma)
 {
        int i, priority, b_size, order, got = 0, segs = 0;
+       unsigned long flags;
        ST_buffer *tb;
 
-       if (st_nbr_buffers >= st_template.dev_max)
+       read_lock(&st_dev_arr_lock);
+       if (st_nbr_buffers >= st_template.dev_max) {
+               read_unlock(&st_dev_arr_lock);
                return NULL;    /* Should never happen */
+       }
+       read_unlock(&st_dev_arr_lock);
 
        if (from_initialization)
                priority = GFP_ATOMIC;
@@ -3014,7 +3086,10 @@ static ST_buffer *
        tb->dma = need_dma;
        tb->buffer_size = got;
        tb->writing = 0;
+
+       write_lock_irqsave(&st_dev_arr_lock, flags);
        st_buffers[st_nbr_buffers++] = tb;
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
 
        return tb;
 }
@@ -3039,7 +3114,8 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
                priority |= GFP_DMA;
        for (b_size = PAGE_SIZE, order=0;
             b_size * nbr < new_size - STbuffer->buffer_size;
-            order++, b_size *= 2);
+            order++, b_size *= 2)
+               ;  /* empty */
 
        for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
             segs < max_segs && got < new_size;) {
@@ -3080,7 +3156,7 @@ static void normalize_buffer(ST_buffer * STbuffer)
        for (i = STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) {
                for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length;
                     order++, b_size *= 2)
-                       ;
+                       ; /* empty */
                free_pages((unsigned long)(STbuffer->sg[i].address), order);
                STbuffer->buffer_size -= STbuffer->sg[i].length;
        }
@@ -3239,23 +3315,77 @@ static int st_attach(Scsi_Device * SDp)
        Scsi_Tape *tpnt;
        ST_mode *STm;
        ST_partstat *STps;
-       int i, mode;
+       int i, mode, target_nbr;
+       unsigned long flags = 0;
 
        if (SDp->type != TYPE_TAPE)
                return 1;
 
+       write_lock_irqsave(&st_dev_arr_lock, flags);
        if (st_template.nr_dev >= st_template.dev_max) {
-               SDp->attached--;
-               return 1;
+               Scsi_Tape **tmp_da;
+               ST_buffer **tmp_ba;
+               int tmp_dev_max;
+
+               tmp_dev_max = st_template.nr_dev + ST_DEV_ARR_LUMP;
+               if (tmp_dev_max > ST_MAX_TAPES)
+                       tmp_dev_max = ST_MAX_TAPES;
+               if (tmp_dev_max <= st_template.nr_dev) {
+                       SDp->attached--;
+                       write_unlock_irqrestore(&st_dev_arr_lock, flags);
+                       printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
+                              ST_MAX_TAPES);
+                       return 1;
+               }
+
+               tmp_da = (Scsi_Tape **) kmalloc(tmp_dev_max * sizeof(Scsi_Tape *),
+                                               GFP_ATOMIC);
+               tmp_ba = (ST_buffer **) kmalloc(tmp_dev_max * sizeof(ST_buffer *),
+                                               GFP_ATOMIC);
+               if (tmp_da == NULL || tmp_ba == NULL) {
+                       if (tmp_da != NULL)
+                               kfree(tmp_da);
+                       SDp->attached--;
+                       write_unlock_irqrestore(&st_dev_arr_lock, flags);
+                       printk(KERN_ERR "st: Can't extend device array.\n");
+                       return 1;
+               }
+
+               memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *));
+               if (scsi_tapes != NULL) {
+                       memcpy(tmp_da, scsi_tapes,
+                              st_template.dev_max * sizeof(Scsi_Tape *));
+                       kfree(scsi_tapes);
+               }
+               scsi_tapes = tmp_da;
+
+               memset(tmp_ba, 0, tmp_dev_max * sizeof(ST_buffer *));
+               if (st_buffers != NULL) {
+                       memcpy(tmp_ba, st_buffers,
+                              st_template.dev_max * sizeof(ST_buffer *));
+                       kfree(st_buffers);
+               }
+               st_buffers = tmp_ba;
+
+               st_template.dev_max = tmp_dev_max;
        }
 
-       for (tpnt = scsi_tapes, i = 0; i < st_template.dev_max; i++, tpnt++)
-               if (!tpnt->device)
+       for (i = 0; i < st_template.dev_max; i++)
+               if (scsi_tapes[i] == NULL)
                        break;
-
        if (i >= st_template.dev_max)
                panic("scsi_devices corrupt (st)");
 
+       tpnt = (Scsi_Tape *)kmalloc(sizeof(Scsi_Tape), GFP_ATOMIC);
+       if (tpnt == NULL) {
+               SDp->attached--;
+               write_unlock_irqrestore(&st_dev_arr_lock, flags);
+               printk(KERN_ERR "st: Can't allocate device descriptor.\n");
+               return 1;
+       }
+       memset(tpnt, 0, sizeof(Scsi_Tape));
+       scsi_tapes[i] = tpnt;
+
        for (mode = 0; mode < ST_NBR_MODES; ++mode) {
            char name[8];
            static char *formats[ST_NBR_MODES] ={"", "l", "m", "a"};
@@ -3276,11 +3406,11 @@ static int st_attach(Scsi_Device * SDp)
                                0, 0, &st_fops, NULL);
        }
        devfs_register_tape (tpnt->de_r[0]);
-       scsi_tapes[i].device = SDp;
+       tpnt->device = SDp;
        if (SDp->scsi_level <= 2)
-               scsi_tapes[i].mt_status->mt_type = MT_ISSCSI1;
+               tpnt->tape_type = MT_ISSCSI1;
        else
-               scsi_tapes[i].mt_status->mt_type = MT_ISSCSI2;
+               tpnt->tape_type = MT_ISSCSI2;
 
         tpnt->inited = 0;
        tpnt->devt = MKDEV(SCSI_TAPE_MAJOR, i);
@@ -3333,6 +3463,20 @@ static int st_attach(Scsi_Device * SDp)
            tpnt->blksize_changed = FALSE;
 
        st_template.nr_dev++;
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
+
+       /* See if we need to allocate more static buffers */
+       target_nbr = st_template.nr_dev;
+       if (target_nbr > st_max_buffers)
+               target_nbr = st_max_buffers;
+       for (i=st_nbr_buffers; i < target_nbr; i++)
+               if (!new_tape_buffer(TRUE, TRUE)) {
+                       printk(KERN_INFO "st: Unable to allocate new static buffer.\n");
+                       break;
+               }
+       /* If the previous allocation fails, we will try again when the buffer is
+          really needed. */
+
        return 0;
 };
 
@@ -3354,90 +3498,28 @@ static int st_registered = 0;
 /* Driver initialization (not __init because may be called later) */
 static int st_init()
 {
-       int i, j;
-       Scsi_Tape *STp;
-       int target_nbr;
+       unsigned long flags;
 
-       if (st_template.dev_noticed == 0)
+       if (st_template.dev_noticed == 0 || st_registered)
                return 0;
 
        printk(KERN_INFO "st: bufsize %d, wrt %d, max init. buffers %d, s/g segs %d.\n",
               st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
 
+       write_lock_irqsave(&st_dev_arr_lock, flags);
        if (!st_registered) {
                if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops)) {
+                       write_unlock_irqrestore(&st_dev_arr_lock, flags);
                        printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
                                MAJOR_NR);
                        return 1;
                }
                st_registered++;
        }
-       if (scsi_tapes)
-               return 0;
-       st_template.dev_max = st_template.dev_noticed + ST_EXTRA_DEVS;
-       if (st_template.dev_max < ST_MAX_TAPES)
-               st_template.dev_max = ST_MAX_TAPES;
-       if (st_template.dev_max > 128 / ST_NBR_MODES)
-               printk(KERN_INFO "st: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
-       scsi_tapes =
-               (Scsi_Tape *) kmalloc(st_template.dev_max * sizeof(Scsi_Tape),
-                                     GFP_ATOMIC);
-       if (scsi_tapes == NULL) {
-               printk(KERN_ERR "Unable to allocate descriptors for SCSI tapes.\n");
-               devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
-               return 1;
-       }
-
-        DEB(printk(ST_DEB_MSG "st: Buffer size %d bytes, write threshold %d bytes.\n",
-                   st_buffer_size, st_write_threshold));
 
-       memset(scsi_tapes, 0, st_template.dev_max * sizeof(Scsi_Tape));
-       for (i = 0; i < st_template.dev_max; ++i) {
-               STp = &(scsi_tapes[i]);
-               STp->capacity = 0xfffff;
-               STp->mt_status = (struct mtget *) kmalloc(sizeof(struct mtget),
-                                                         GFP_ATOMIC);
-               if (STp->mt_status == NULL) {
-                       for (j=0; j < i; j++)
-                               kfree(scsi_tapes[j].mt_status);
-                       kfree(scsi_tapes);
-                       devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
-                       return 1;
-               }
-               /* Initialize status */
-               memset((void *) scsi_tapes[i].mt_status, 0, sizeof(struct mtget));
-       }
-
-       /* Allocate the buffers */
-       st_buffers =
-           (ST_buffer **) kmalloc(st_template.dev_max * sizeof(ST_buffer *),
-                                  GFP_ATOMIC);
-       if (st_buffers == NULL) {
-               printk(KERN_ERR "Unable to allocate tape buffer pointers.\n");
-               devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
-               for (i=0; i < st_template.dev_max; i++)
-                       kfree(scsi_tapes[i].mt_status);
-               kfree(scsi_tapes);
-               unregister_chrdev(SCSI_TAPE_MAJOR, "st");
-               return 1;
-       }
-       target_nbr = st_template.dev_noticed;
-       if (target_nbr < ST_EXTRA_DEVS)
-               target_nbr = ST_EXTRA_DEVS;
-       if (target_nbr > st_max_buffers)
-               target_nbr = st_max_buffers;
-
-       for (i = st_nbr_buffers = 0; i < target_nbr; i++) {
-               if (!new_tape_buffer(TRUE, TRUE)) {
-                       if (i == 0) {
-                               printk(KERN_INFO
-                                       "No tape buffers allocated at initialization.\n");
-                               break;
-                       }
-                       printk(KERN_INFO "Number of tape buffers adjusted.\n");
-                       break;
-               }
-       }
+       st_template.dev_max = 0;
+       st_nbr_buffers = 0;
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
 
        return 0;
 }
@@ -3446,9 +3528,12 @@ static void st_detach(Scsi_Device * SDp)
 {
        Scsi_Tape *tpnt;
        int i, mode;
+       unsigned long flags;
 
-       for (tpnt = scsi_tapes, i = 0; i < st_template.dev_max; i++, tpnt++)
-               if (tpnt->device == SDp) {
+       write_lock_irqsave(&st_dev_arr_lock, flags);
+       for (i = 0; i < st_template.dev_max; i++) {
+               tpnt = scsi_tapes[i];
+               if (tpnt != NULL && tpnt->device == SDp) {
                        tpnt->device = NULL;
                        for (mode = 0; mode < ST_NBR_MODES; ++mode) {
                                devfs_unregister (tpnt->de_r[mode]);
@@ -3456,11 +3541,17 @@ static void st_detach(Scsi_Device * SDp)
                                devfs_unregister (tpnt->de_n[mode]);
                                tpnt->de_n[mode] = NULL;
                        }
+                       kfree(tpnt);
+                       scsi_tapes[i] = 0;
                        SDp->attached--;
                        st_template.nr_dev--;
                        st_template.dev_noticed--;
+                       write_unlock_irqrestore(&st_dev_arr_lock, flags);
                        return;
                }
+       }
+
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
        return;
 }
 
@@ -3484,7 +3575,8 @@ void cleanup_module(void)
        st_registered--;
        if (scsi_tapes != NULL) {
                for (i=0; i < st_template.dev_max; ++i)
-                       kfree(scsi_tapes[i].mt_status);
+                       if (scsi_tapes[i])
+                               kfree(scsi_tapes[i]);
                kfree(scsi_tapes);
                if (st_buffers != NULL) {
                        for (i = 0; i < st_nbr_buffers; i++) {
index e751efc28d3401a343928f02d097ec69bcf98176..47b3fbff59d78cc0371be37309eb55489c1a2756 100644 (file)
@@ -47,6 +47,7 @@ typedef struct {
 #define ST_NBR_MODES (1 << ST_NBR_MODE_BITS)
 #define ST_MODE_SHIFT (7 - ST_NBR_MODE_BITS)
 #define ST_MODE_MASK ((ST_NBR_MODES - 1) << ST_MODE_SHIFT)
+#define ST_MAX_TAPES (1 << ST_MODE_SHIFT)
 
 /* The status related to each partition */
 typedef struct {
@@ -64,7 +65,6 @@ typedef struct {
 /* The tape drive descriptor */
 typedef struct {
        kdev_t devt;
-       unsigned capacity;
        Scsi_Device *device;
        struct semaphore sem;
        ST_buffer *buffer;
@@ -79,6 +79,7 @@ typedef struct {
        unsigned char restr_dma;
        unsigned char scsi2_logical;
        unsigned char default_drvbuffer;        /* 0xff = don't touch, value 3 bits */
+       int tape_type;
        int write_threshold;
        int timeout;            /* timeout for normal commands */
        int long_timeout;       /* timeout for commands known to take long time */
@@ -105,13 +106,14 @@ typedef struct {
        unsigned char drv_buffer;
        unsigned char density;
        unsigned char door_locked;
-       unsigned char rew_at_close;
+       unsigned char autorew_dev;   /* auto-rewind device */
+       unsigned char rew_at_close;  /* rewind necessary at close */
        unsigned char inited;
        int block_size;
        int min_block;
        int max_block;
-       int recover_count;
-       struct mtget *mt_status;
+       int recover_count;     /* From tape opening */
+       int recover_reg;       /* From last status call */
 
 #if DEBUG
        unsigned char write_pending;
@@ -122,7 +124,6 @@ typedef struct {
 #endif
 } Scsi_Tape;
 
-extern Scsi_Tape *scsi_tapes;
 
 /* Values of eof */
 #define        ST_NOEOF        0
index 8cbc1c69eb80099b0c2a92e0179f31b7f9a6289a..fa3926c5d96f6b1e544effe5867e0e1593a5b0fb 100644 (file)
@@ -3,17 +3,12 @@
 
    Copyright 1995-2000 Kai Makisara.
 
-   Last modified: Sat Jan  1 18:34:38 2000 by makisara@kai.makisara.local
+   Last modified: Sat Mar 11 10:32:00 2000 by makisara@kai.makisara.local
 */
 
 #ifndef _ST_OPTIONS_H
 #define _ST_OPTIONS_H
 
-/* The minimum limit for the number of SCSI tape devices is determined by
-   ST_MAX_TAPES. If the number of tape devices and the "slack" defined by
-   ST_EXTRA_DEVS exceeds ST_MAX_TAPES, the large number is used. */
-#define ST_MAX_TAPES 4
-
 /* The driver does not wait for some operations to finish before returning
    to the user program if ST_NOWAIT is non-zero. This helps if the SCSI
    adapter does not support multiple outstanding commands. However, the user
@@ -47,7 +42,7 @@
    driver initialisation. The number is also constrained by the number
    of drives detected. If more buffers are needed, they are allocated
    at run time and freed after use. */
-#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
+#define ST_MAX_BUFFERS 4
 
 /* Maximum number of scatter/gather segments */
 #define ST_MAX_SG      16
index f79919b9f6eca0c982aab0db551d0ca8d6313fe2..947e0294eb0347e55de233107aabcbe329e86576 100644 (file)
@@ -81,10 +81,12 @@ fi
 dep_tristate '  OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
 
 if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
+   bool '      Verbose initialisation' CONFIG_SOUND_TRACEINIT
+   bool '      Persistent DMA buffers' CONFIG_SOUND_DMAP
+
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       dep_tristate '    AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND
    fi
-
    dep_tristate '    Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS
    dep_tristate '    Adlib Cards' CONFIG_SOUND_ADLIB $CONFIG_SOUND_OSS
    dep_tristate '    ACI mixer (miroPCM12)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
index 52d4d79f84c768004233e931507d611ee41514e0..99a4d8f44962e1502a8c252093ab8c56eea493cb 100644 (file)
@@ -17,8 +17,6 @@
 #include "sound_config.h"
 
 int softoss_dev = 0;
-int sound_started = 0;
-int sndtable_get_cardcount(void);
 
 int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
                        int driver_size, int flags, unsigned int format_mask,
index db2b141d694b1ca9fcf12b48b1e37d04f80f0f19..a5525a4bf21cb26c0b78659600521e67c5065c9e 100644 (file)
@@ -43,8 +43,6 @@
  *     NOTE!   NOTE!   NOTE!   NOTE!
  */
 
-extern int sound_started;
-
 struct driver_info 
 {
        char *driver_id;
@@ -350,11 +348,14 @@ struct sound_timer_operations
 
 #ifdef _DEV_TABLE_C_   
 
-struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0;
-struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
-struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
-struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
-
+struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL};
+int num_audiodevs = 0;
+struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL};
+int num_mixers = 0;
+struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL};
+int num_synths = 0;
+struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL};
+int num_midis = 0;
 #ifndef EXCLUDE_TIMERS
 extern struct sound_timer_operations default_sound_timer;
 struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {
@@ -370,18 +371,17 @@ int num_sound_timers = 0;
 
 
 #else
-extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs;
-extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
-extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths;
-extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis;
-extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV]; extern int num_sound_timers;
+extern struct audio_operations *audio_devs[MAX_AUDIO_DEV];
+extern int num_audiodevs;
+extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
+extern int num_mixers;
+extern struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV];
+extern int num_synths;
+extern struct midi_operations *midi_devs[MAX_MIDI_DEV];
+extern int num_midis;
+extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV];
+extern int num_sound_timers;
 #endif /* _DEV_TABLE_C_ */
-void setup_cards(void);
-int sndtable_get_cardcount (void);
-void sound_chconf(int card_type, int ioaddr, int irq, int dma);
-int snd_find_driver(int type);
-void sound_unload_driver(int type);
-int sndtable_identify_card(char *name);
 
 extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
 int sndtable_probe (int unit, struct address_info *hw_config);
index 2757659aceb7cecad864d4dfcb5249b7d4d742b4..a329f0e72198c4ac804d7e6b8dc57ce08be6cdbe 100644 (file)
@@ -1726,25 +1726,24 @@ int init_mpu401(void)
 {
        /* Can be loaded either for module use or to provide functions
           to others */
-       cfg.irq = irq;
-       cfg.io_base = io;
-       
-       if (cfg.io_base != -1 && cfg.irq != -1) {
-               printk(KERN_WARNING "mpu401: need io and irq !");
-               return -ENODEV;
+       if (io != -1 && irq != -1) {
+               cfg.irq = irq;
+               cfg.io_base = io;
+               if (probe_mpu401(&cfg) == 0)
+                       return -ENODEV;
+               attach_mpu401(&cfg);
        }
        
-       if (probe_mpu401(&cfg) == 0)
-               return -ENODEV;
-       attach_mpu401(&cfg);
-
        SOUND_LOCK;
        return 0;
 }
 
 void cleanup_mpu401(void)
 {
-       unload_mpu401(&cfg);
+       if (io != -1 && irq != -1) {
+               /* Check for use by, for example, sscape driver */
+               unload_mpu401(&cfg);
+       }
        SOUND_LOCK_END;
 }
 
index 40804417c3cb1ba5726467f84a8d2a064d6d179d..c471163efc3dc523a341eca2cd6b2fba8bc31858 100644 (file)
@@ -399,7 +399,6 @@ static struct pci_dev *sb_init_diamond(struct pci_bus *bus, struct pci_dev *card
        /*  @X@0001:mpu
         */
 
-#ifdef CONFIG_MIDI
        if((mpu_dev = isapnp_find_dev(bus,
                                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL)))
        {
@@ -413,7 +412,6 @@ static struct pci_dev *sb_init_diamond(struct pci_bus *bus, struct pci_dev *card
        }
        else
                printk(KERN_ERR "sb: DT0197H panic: mpu not found\n");
-#endif
 
 
        /*  @P@:Gameport
index 00f8b6e7b49a82491e20953d38d15b10206b346a..ea90ed81ca67bc70bb23d8f73336a3fc2e29c1f4 100644 (file)
@@ -74,7 +74,12 @@ caddr_t         sound_mem_blocks[1024];
 int             sound_nblocks = 0;
 
 /* Persistent DMA buffers */
-int            sound_dmap_flag = 0;
+#ifdef CONFIG_SOUND_DMAP
+int             sound_dmap_flag = 1;
+#else
+int             sound_dmap_flag = 0;
+#endif
+
 static int      soundcard_configured = 0;
 static char     dma_alloc_map[MAX_DMA_CHANNELS] = {0};
 
@@ -92,8 +97,6 @@ unsigned long seq_time = 0;   /* Time for /dev/sequencer */
 static mixer_vol_table mixer_vols[MAX_MIXER_DEV];
 static int num_mixer_volumes = 0;
 
-int traceinit = 0;
-
 int *load_mixer_volumes(char *name, int *levels, int present)
 {
        int             i, n;
@@ -637,11 +640,6 @@ soundcard_init(void)
 
        soundcard_configured = 1;
 
-#if defined(CONFIG_LOWLEVEL_SOUND) && !defined(MODULE)
-        sound_preinit_lowlevel_drivers();
-       sound_init_lowlevel_drivers();
-#endif
-
        audio_init_devices();
 
        soundcard_register_devfs(1); /* register after we know # of devices */
@@ -663,38 +661,15 @@ static int      sound[20] = {
 static int dmabuf = 0;
 static int dmabug = 0;
 
-MODULE_PARM(traceinit, "i");
 MODULE_PARM(dmabuf, "i");
 MODULE_PARM(dmabug, "i");
 
 int init_module(void)
 {
        int             err;
-#if FIXED_FOR_2_4_0
-       int             ints[21];
-       int             i;
-#endif
 
-#ifdef HAS_BRIDGE_BUGGY_FUNC
        if(dmabug)
                isa_dma_bridge_buggy = dmabug;
-#else
-       if(dmabug)
-               printk(KERN_ERR "sound: rebuild with PCI_QUIRKS enabled to configure this.\n");
-#endif
-               
-#if FIXED_FOR_2_4_0
-       /*
-        * "sound=" command line handling by Harald Milz.
-        */
-       i = 0;
-       while (i < 20 && sound[i])
-               ints[i + 1] = sound[i++];
-       ints[0] = i;
-
-       if (i)
-               sound_setup("sound=", ints);
-#endif
 
        err = create_special_devices();
        if (err)
@@ -730,13 +705,6 @@ void cleanup_module(void)
 
        sound_stop_timer();
 
-#ifdef CONFIG_LOWLEVEL_SOUND
-       {
-               extern void     sound_unload_lowlevel_drivers(void);
-
-               sound_unload_lowlevel_drivers();
-       }
-#endif
        sequencer_unload();
 
        for (i = 0; i < MAX_DMA_CHANNELS; i++)
@@ -855,8 +823,9 @@ void sound_stop_timer(void)
 
 void conf_printf(char *name, struct address_info *hw_config)
 {
-       if (!traceinit)
-               return;
+#ifndef CONFIG_SOUND_TRACEINIT
+       return;
+#else
        printk("<%s> at 0x%03x", name, hw_config->io_base);
 
        if (hw_config->irq)
@@ -870,12 +839,13 @@ void conf_printf(char *name, struct address_info *hw_config)
        }
        printk("\n");
 }
+#endif
 
 void conf_printf2(char *name, int base, int irq, int dma, int dma2)
 {
-       if (!traceinit)
-               return;
-
+#ifndef CONFIG_SOUND_TRACEINIT
+       return;
+#else
        printk("<%s> at 0x%03x", name, base);
 
        if (irq)
@@ -889,6 +859,7 @@ void conf_printf2(char *name, int base, int irq, int dma, int dma2)
        }
        printk("\n");
 }
+#endif
 
 /*
  *     Module and lock management
index 764b37753d82bccd5b9cb96ef3bcdeb46f614009..d1f5048e39544364d4cbd5876a401049463e8baa 100644 (file)
@@ -36,7 +36,6 @@
 
 /* Handle mangled (versioned) external symbols */
 
-#include <linux/config.h>   /* retrieve the CONFIG_* macros */
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/list.h>
index bffa6b02ef356d48b0d3c71428e79b2eef86a8d9..dead9038bd9b98b18b27abd9d926b8ef609b0bcb 100644 (file)
@@ -7,6 +7,8 @@
  *
  * History:
  *
+ * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
+ *                                 minor fixes
  * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for 
  *                                  HGA-only systems
  * - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure
@@ -27,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
@@ -53,7 +56,7 @@
 #define DPRINTK(args...)
 #endif
 
-#if 1
+#if 0
 #define CHKINFO(ret) if (info != &fb_info) { printk(KERN_DEBUG __FILE__": This should never happen, line:%d \n", __LINE__); return ret; }
 #else
 #define CHKINFO(ret)
@@ -97,6 +100,10 @@ static char *hga_type_name;
 #define HGA_GFX_MODE_EN                0x01
 #define HGA_GFX_PAGE_EN                0x02
 
+/* Global locks */
+
+spinlock_t hga_reg_lock = SPIN_LOCK_UNLOCKED;
+
 /* Framebuffer driver structures */
 
 static struct fb_var_screeninfo hga_default_var = {
@@ -158,55 +165,46 @@ static int nologo = 0;
 
 static void write_hga_b(unsigned int val, unsigned char reg)
 {
-       unsigned long flags;
-
-       save_flags(flags); cli();
-
        outb_p(reg, HGA_INDEX_PORT); 
        outb_p(val, HGA_VALUE_PORT);
-
-       restore_flags(flags);
 }
 
 static void write_hga_w(unsigned int val, unsigned char reg)
 {
-       unsigned long flags;
-
-       save_flags(flags); cli();
-
        outb_p(reg,   HGA_INDEX_PORT); outb_p(val >> 8,   HGA_VALUE_PORT);
        outb_p(reg+1, HGA_INDEX_PORT); outb_p(val & 0xff, HGA_VALUE_PORT);
-
-       restore_flags(flags);
 }
 
 static int test_hga_b(unsigned char val, unsigned char reg)
 {
-       unsigned long flags;
-
-       save_flags(flags); cli();
-
        outb_p(reg, HGA_INDEX_PORT); 
        outb  (val, HGA_VALUE_PORT);
-
        udelay(20); val = (inb_p(HGA_VALUE_PORT) == val);
-
-       restore_flags(flags);
-
        return val;
 }
 
 static void hga_clear_screen(void)
 {
+       unsigned char fillchar = 0xbf; /* magic */
+       unsigned long flags;
+
+       spin_lock_irqsave(&hga_reg_lock, flags);
        if (hga_mode == HGA_TXT)
-               memset((char *)hga_vram_base, ' ', hga_vram_len);
+               fillchar = ' ';
        else if (hga_mode == HGA_GFX)
-               memset((char *)hga_vram_base, 0, hga_vram_len);
+               fillchar = 0x00;
+       spin_unlock_irqrestore(&hga_reg_lock, flags);
+       if (fillchar != 0xbf)
+               memset((char *)hga_vram_base, fillchar, hga_vram_len);
 }
 
 
+#ifdef MODULE
 static void hga_txt_mode(void)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&hga_reg_lock, flags);
        outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_BLINK_EN, HGA_MODE_PORT);
        outb_p(0x00, HGA_GFX_PORT);
        outb_p(0x00, HGA_STATUS_PORT);
@@ -230,10 +228,15 @@ static void hga_txt_mode(void)
        write_hga_w(0x0000, 0x0e);      /* cursor location */
 
        hga_mode = HGA_TXT;
+       spin_unlock_irqrestore(&hga_reg_lock, flags);
 }
+#endif /* MODULE */
 
 static void hga_gfx_mode(void)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&hga_reg_lock, flags);
        outb_p(0x00, HGA_STATUS_PORT);
        outb_p(HGA_GFX_MODE_EN, HGA_GFX_PORT);
        outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
@@ -257,6 +260,7 @@ static void hga_gfx_mode(void)
        write_hga_w(0x0000, 0x0e);      /* cursor location */
 
        hga_mode = HGA_GFX;
+       spin_unlock_irqrestore(&hga_reg_lock, flags);
 }
 
 #ifdef MODULE
@@ -274,12 +278,29 @@ static void hga_show_logo(void)
 static void hga_pan(unsigned int xoffset, unsigned int yoffset)
 {
        unsigned int base;
+       unsigned long flags;
+       
        base = (yoffset / 8) * 90 + xoffset;
+       spin_lock_irqsave(&hga_reg_lock, flags);
        write_hga_w(base, 0x0c);        /* start address */
+       spin_unlock_irqrestore(&hga_reg_lock, flags);
        DPRINTK("hga_pan: base:%d\n", base);
 }
 
-static int hga_card_detect(void)
+static void hga_blank(int blank_mode)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hga_reg_lock, flags);
+       if (blank_mode) {
+               outb_p(0x00, HGA_MODE_PORT);    /* disable video */
+       } else {
+               outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
+       }
+       spin_unlock_irqrestore(&hga_reg_lock, flags);
+}
+
+static int __init hga_card_detect(void)
 {
        int count=0;
        u16 *p, p_save;
@@ -288,11 +309,6 @@ static int hga_card_detect(void)
        hga_vram_base = VGA_MAP_MEM(0xb0000);
        hga_vram_len  = 0x08000;
 
-       if (!request_mem_region(hga_vram_base, hga_vram_len, "hgafb")) {
-               printk(KERN_ERR "hgafb: cannot reserve video memory at 0x%lX\n",
-                               hga_vram_base);
-               return 0;
-       }
        if (request_region(0x3b0, 12, "hgafb"))
                release_io_ports = 1;
        if (request_region(0x3bf, 1, "hgafb"))
@@ -598,11 +614,7 @@ static void hgafbcon_blank(int blank_mode, struct fb_info *info)
        CHKINFO( );
        DPRINTK("hga_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info);
 
-       if (blank_mode) {
-               outb_p(0x00, HGA_MODE_PORT);    /* disable video */
-       } else {
-               outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
-       }
+       hga_blank(blank_mode);
 }
 
 
@@ -642,7 +654,12 @@ int __init hgafb_init(void)
        disp.line_length = hga_fix.line_length;
        disp.can_soft_blank = 1;
        disp.inverse = 0;
+#ifdef FBCON_HAS_HGA
        disp.dispsw = &fbcon_hga;
+#else
+#warning HGAFB will not work as a console!
+       disp.dispsw = &fbcon_dummy;
+#endif
        disp.dispsw_data = NULL;
 
        disp.scrollmode = SCROLL_YREDRAW;
@@ -723,7 +740,6 @@ static void hgafb_cleanup(struct fb_info *info)
        unregister_framebuffer(info);
        if (release_io_ports) release_region(0x3b0, 12);
        if (release_io_port) release_region(0x3bf, 1);
-       release_mem_region(hga_vram_base, hga_vram_len);
 }
 #endif /* MODULE */
 
index 0dd364c664f6430e620056e054258fbd3dc55009..c9226513e0d148fa6b5dfc0eb2020df774a0fe46 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Common directory handling for ADFS
  */
+#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
index 5f2387bdecf39f5e9f8ee3452c3c232e49bb37df..46c11a8e221959f0f1b3d434ea4dc8f1f14c0f82 100644 (file)
@@ -672,24 +672,17 @@ affs_statfs(struct super_block *sb, struct statfs *buf)
 
 static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
 
-int __init init_affs_fs(void)
+static int __init init_affs_fs(void)
 {
        return register_filesystem(&affs_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int
-init_module(void)
-{
-       return register_filesystem(&affs_fs_type);
-}
-
-void
-cleanup_module(void)
+static void __exit exit_affs_fs(void)
 {
        unregister_filesystem(&affs_fs_type);
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_affs_fs)
+module_exit(exit_affs_fs)
index 2c38ccafe5976d52afef6c8a08ee19d8367472e4..6f3765399250e247f37bc96be1521f793adafab5 100644 (file)
@@ -322,16 +322,15 @@ out:
 
 static DECLARE_FSTYPE_DEV( bfs_fs_type, "bfs", bfs_read_super);
 
-#ifdef MODULE
-#define init_bfs_fs init_module
-
-void cleanup_module(void)
+static int __init init_bfs_fs(void)
 {
-       unregister_filesystem(&bfs_fs_type);
+       return register_filesystem(&bfs_fs_type);
 }
-#endif
 
-int __init init_bfs_fs(void)
+static void __exit exit_bfs_fs(void)
 {
-       return register_filesystem(&bfs_fs_type);
+       unregister_filesystem(&bfs_fs_type);
 }
+
+module_init(init_bfs_fs)
+module_exit(exit_bfs_fs)
index 41138e3fd3e85e99a11eea4a9966992440ebac0e..5aa2f1b351d8232cf0e7905b202223e8167d8f61 100644 (file)
@@ -78,8 +78,7 @@ if (file->f_op->llseek) { \
  * dumping of the process results in another error..
  */
 
-static inline int
-do_aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
 {
        mm_segment_t fs;
        int has_dumped = 0;
@@ -183,17 +182,6 @@ end_coredump:
        return has_dumped;
 }
 
-static int
-aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_aout_core_dump(signr, regs, file);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 /*
  * create_aout_tables() parses the env- and arg-strings in new user
  * memory and creates the pointer tables from them, and puts their
@@ -261,7 +249,7 @@ static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
  * libraries.  There is no binary dependent code anywhere else.
  */
 
-static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static inload_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
        struct exec ex;
        struct file * file;
@@ -398,14 +386,11 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs
                }
        }
 beyond_if:
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
+       put_exec_domain(current->exec_domain);
        if (current->binfmt && current->binfmt->module)
                __MOD_DEC_USE_COUNT(current->binfmt->module);
        current->exec_domain = lookup_exec_domain(current->personality);
        current->binfmt = &aout_format;
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
        if (current->binfmt && current->binfmt->module)
                __MOD_INC_USE_COUNT(current->binfmt->module);
 
@@ -429,20 +414,7 @@ beyond_if:
        return 0;
 }
 
-
-static int
-load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_aout_binary(bprm, regs);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
-static inline int
-do_load_aout_library(int fd)
+static int load_aout_library(int fd)
 {
         struct file * file;
        struct inode * inode;
@@ -529,18 +501,6 @@ out:
        return retval;
 }
 
-static int
-load_aout_library(int fd)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_aout_library(fd);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
-
 static int __init init_aout_binfmt(void)
 {
        return register_binfmt(&aout_format);
@@ -555,4 +515,3 @@ EXPORT_NO_SYMBOLS;
 
 module_init(init_aout_binfmt);
 module_exit(exit_aout_binfmt);
-
index c329b725067ffc851581e10eecc3b54a33709074..307037153dee1e892c2dc46f423187cf11e70e9b 100644 (file)
@@ -383,8 +383,7 @@ out:
 #define INTERPRETER_ELF 2
 
 
-static inline int
-do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
        struct file * file;
        struct dentry *interpreter_dentry = NULL; /* to shut gcc up */
@@ -695,14 +694,11 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        if (interpreter_type != INTERPRETER_AOUT)
                sys_close(elf_exec_fileno);
 
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
+       put_exec_domain(current->exec_domain);
        if (current->binfmt && current->binfmt->module)
                __MOD_DEC_USE_COUNT(current->binfmt->module);
        current->exec_domain = lookup_exec_domain(current->personality);
        current->binfmt = &elf_format;
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
        if (current->binfmt && current->binfmt->module)
                __MOD_INC_USE_COUNT(current->binfmt->module);
 
@@ -792,22 +788,10 @@ out_free_ph:
        goto out;
 }
 
-static int
-load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_elf_binary(bprm, regs);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 /* This is really simpleminded and specialized - we are loading an
    a.out library that is given an ELF header. */
 
-static inline int
-do_load_elf_library(int fd)
+static int load_elf_library(int fd)
 {
        struct file * file;
        struct dentry * dentry;
@@ -899,16 +883,6 @@ out:
        return error;
 }
 
-static int load_elf_library(int fd)
-{
-       int retval;
-
-       MOD_INC_USE_COUNT;
-       retval = do_load_elf_library(fd);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 /*
  * Note that some platforms still use traditional core dumps and not
  * the ELF core dump.  Each platform can select it as appropriate.
@@ -1061,10 +1035,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
        elf_fpregset_t fpu;             /* NT_PRFPREG */
        struct elf_prpsinfo psinfo;     /* NT_PRPSINFO */
 
-#ifndef CONFIG_BINFMT_ELF
-       MOD_INC_USE_COUNT;
-#endif
-
        /* Count what's needed to dump, up to the limit of coredump size */
        segs = 0;
        size = 0;
@@ -1294,9 +1264,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
 
  end_coredump:
        set_fs(fs);
-#ifndef CONFIG_BINFMT_ELF
-       MOD_DEC_USE_COUNT;
-#endif
        return has_dumped;
 }
 #endif         /* USE_ELF_CORE_DUMP */
index d89bd9ca8e11027e0c134e7afccff0ffc353c056..189d130cafabf9dc7df4ab044370a799b8e0d66f 100644 (file)
@@ -20,7 +20,7 @@
 #define EM86_INTERP    "/usr/bin/em86"
 #define EM86_I_NAME    "em86"
 
-static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
+static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
 {
        char *interp, *i_name, *i_arg;
        struct dentry * dentry;
@@ -95,15 +95,6 @@ static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
        return search_binary_handler(bprm, regs);
 }
 
-static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
-{
-       int retval;
-       MOD_INC_USE_COUNT;
-       retval = do_load_em86(bprm,regs);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 struct linux_binfmt em86_format = {
        NULL, THIS_MODULE, load_em86, NULL, NULL, 0
 };
index 5d5d17bc4ce92f0d8c76be96a7cfec4bc97954ed..c530a6ff29d8dc893e088e78a262d6da67372a67 100644 (file)
@@ -185,7 +185,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        char *iname_addr = iname;
        int retval;
 
-       MOD_INC_USE_COUNT;
        retval = -ENOEXEC;
        if (!enabled)
                goto _ret;
@@ -224,7 +223,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (retval >= 0)
                retval = search_binary_handler(bprm, regs);
 _ret:
-       MOD_DEC_USE_COUNT;
        return retval;
 }
 
index 8c71ec4a92b26f018ecc9ea24d783fc7e21cb638..84dbf11b0aa092bdbaee9ccf24eeb27f93110823 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
-static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
 {
        char *cp, *i_name, *i_arg;
        struct dentry * dentry;
@@ -94,15 +94,6 @@ static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
        return search_binary_handler(bprm,regs);
 }
 
-static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
-{
-       int retval;
-       MOD_INC_USE_COUNT;
-       retval = do_load_script(bprm,regs);
-       MOD_DEC_USE_COUNT;
-       return retval;
-}
-
 struct linux_binfmt script_format = {
        NULL, THIS_MODULE, load_script, NULL, NULL, 0
 };
index c00a6945c696445413dc20e2af6d100f190af6d9..cc12ccaef6f320d382e017bbf3935ff02c526cde 100644 (file)
@@ -260,7 +260,6 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
        }
        
        vcp->vc_inuse++;
-       MOD_INC_USE_COUNT;
 
        if ( file->f_flags == O_RDWR ) {
                vcp->vc_pid = current->pid;
@@ -290,7 +289,6 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
        }
 
        vcp->vc_inuse--;
-       MOD_DEC_USE_COUNT;
        CDEBUG(D_PSDEV, "inuse: %d, vc_pid %d, caller %d\n",
               vcp->vc_inuse, vcp->vc_pid, current->pid);
 
index 092c2f0a7d2fac5f38a161417cd3d3b656b629ae..7917bef5c6a353308c74e37b8235aa3b1071e900 100644 (file)
@@ -17,26 +17,22 @@ static DECLARE_FSTYPE_DEV(efs_fs_type, "efs", efs_read_super);
 
 static struct super_operations efs_superblock_operations = {
        read_inode:     efs_read_inode,
-       put_super:      efs_put_super,
        statfs:         efs_statfs,
 };
 
-int __init init_efs_fs(void) {
-       return register_filesystem(&efs_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void) {
+static int __init init_efs_fs(void) {
        printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
-       return init_efs_fs();
+       return register_filesystem(&efs_fs_type);
 }
 
-void cleanup_module(void) {
+static void __exit exit_efs_fs(void) {
        unregister_filesystem(&efs_fs_type);
 }
-#endif
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_efs_fs)
+module_exit(exit_efs_fs)
 
 static efs_block_t efs_validate_vh(struct volume_header *vh) {
        int             i;
@@ -209,9 +205,6 @@ out_no_fs:
        return(NULL);
 }
 
-void efs_put_super(struct super_block *s) {
-}
-
 int efs_statfs(struct super_block *s, struct statfs *buf) {
        struct efs_sb_info *sb = SUPER_INFO(s);
 
index 1b881e12312b2470486c5dc894b50f2480d86ae8..e3ff2d0055eec3f2727621d5fa98ca88d15a6c58 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -33,6 +33,9 @@
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
+#include <linux/spinlock.h>
+#define __NO_VERSION__
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -43,6 +46,7 @@
 #endif
 
 static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
+static spinlock_t binfmt_lock = SPIN_LOCK_UNLOCKED;
 
 int register_binfmt(struct linux_binfmt * fmt)
 {
@@ -52,13 +56,17 @@ int register_binfmt(struct linux_binfmt * fmt)
                return -EINVAL;
        if (fmt->next)
                return -EBUSY;
+       spin_lock(&binfmt_lock);
        while (*tmp) {
-               if (fmt == *tmp)
+               if (fmt == *tmp) {
+                       spin_unlock(&binfmt_lock);
                        return -EBUSY;
+               }
                tmp = &(*tmp)->next;
        }
        fmt->next = formats;
        formats = fmt;
+       spin_unlock(&binfmt_lock);
        return 0;       
 }
 
@@ -66,16 +74,25 @@ int unregister_binfmt(struct linux_binfmt * fmt)
 {
        struct linux_binfmt ** tmp = &formats;
 
+       spin_lock(&binfmt_lock);
        while (*tmp) {
                if (fmt == *tmp) {
                        *tmp = fmt->next;
+                       spin_unlock(&binfmt_lock);
                        return 0;
                }
                tmp = &(*tmp)->next;
        }
+       spin_unlock(&binfmt_lock);
        return -EINVAL;
 }
 
+static inline void put_binfmt(struct linux_binfmt * fmt)
+{
+       if (fmt->module)
+               __MOD_DEC_USE_COUNT(fmt->module);
+}
+
 /* N.B. Error returns must be < 0 */
 int open_dentry(struct dentry * dentry, int mode)
 {
@@ -146,15 +163,22 @@ asmlinkage long sys_uselib(const char * library)
        file = fget(fd);
        retval = -ENOEXEC;
        if (file && file->f_dentry && file->f_op && file->f_op->read) {
+               spin_lock(&binfmt_lock);
                for (fmt = formats ; fmt ; fmt = fmt->next) {
                        int (*fn)(int) = fmt->load_shlib;
                        if (!fn)
                                continue;
+                       if (!try_inc_mod_count(fmt->module))
+                               continue;
+                       spin_unlock(&binfmt_lock);
                        /* N.B. Should use file instead of fd */
                        retval = fn(fd);
+                       spin_lock(&binfmt_lock);
+                       put_binfmt(fmt);
                        if (retval != -ENOEXEC)
                                break;
                }
+               spin_unlock(&binfmt_lock);
        }
        fput(file);
        sys_close(fd);
@@ -767,12 +791,17 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
        }
 #endif
        for (try=0; try<2; try++) {
+               spin_lock(&binfmt_lock);
                for (fmt = formats ; fmt ; fmt = fmt->next) {
                        int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
                        if (!fn)
                                continue;
+                       if (!try_inc_mod_count(fmt->module))
+                               continue;
+                       spin_unlock(&binfmt_lock);
                        retval = fn(bprm, regs);
                        if (retval >= 0) {
+                               put_binfmt(fmt);
                                if (bprm->dentry) {
                                        lock_kernel();
                                        dput(bprm->dentry);
@@ -782,11 +811,16 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                                current->did_exec = 1;
                                return retval;
                        }
+                       spin_lock(&binfmt_lock);
+                       put_binfmt(fmt);
                        if (retval != -ENOEXEC)
                                break;
-                       if (!bprm->dentry) /* We don't have the dentry anymore */
+                       if (!bprm->dentry) {
+                               spin_unlock(&binfmt_lock);
                                return retval;
+                       }
                }
+               spin_unlock(&binfmt_lock);
                if (retval != -ENOEXEC) {
                        break;
 #ifdef CONFIG_KMOD
index 3a2e4ea820ec9282f2d6097f288ffc25e68db428..22ce56b685fbb415151db53e3cb0f127c8a661de 100644 (file)
@@ -7,6 +7,7 @@
 #define ASC_LINUX_VERSION(V, P, S)     (((V) * 65536) + ((P) * 256) + (S))
 #include <linux/version.h>
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
@@ -54,8 +55,10 @@ EXPORT_SYMBOL(fat_add_entries);
 EXPORT_SYMBOL(fat_dir_empty);
 EXPORT_SYMBOL(fat_truncate);
 
-int init_fat_fs(void)
+static int __init init_fat_fs(void)
 {
        fat_hash_init();
        return 0;
 }
+
+module_init(init_fat_fs)
index f95adc0fdcd8014617e66d9fbb48d469e544e39e..cedd3ba2bda254b8ec698788087e2a0b579db8ee 100644 (file)
@@ -920,19 +920,3 @@ int fat_notify_change(struct dentry * dentry, struct iattr * attr)
            ~MSDOS_SB(sb)->options.fs_umask;
        return 0;
 }
-
-
-#ifdef MODULE
-int init_module(void)
-{
-       return init_fat_fs();
-}
-
-
-void cleanup_module(void)
-{
-       /* Nothing to be done, really! */
-       return;
-}
-#endif
-
index cedf675456eaf112deeb50f25b3b9674e05dab22..6ad3ec407cfc2cbab3a7fdc20f1529b256aba18c 100644 (file)
@@ -9,30 +9,10 @@
 #include <linux/config.h>
 #include <linux/fs.h>
 
-#include <linux/minix_fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/umsdos_fs.h>
-#include <linux/proc_fs.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/nfs_fs.h>
-#include <linux/iso_fs.h>
-#include <linux/sysv_fs.h>
-#include <linux/hpfs_fs.h>
-#include <linux/smb_fs.h>
-#include <linux/ncp_fs.h>
-#include <linux/affs_fs.h>
-#include <linux/ufs_fs.h>
-#include <linux/efs_fs.h>
-#include <linux/romfs_fs.h>
 #include <linux/auto_fs.h>
-#include <linux/qnx4_fs.h>
-#include <linux/udf_fs.h>
-#include <linux/ntfs_fs.h>
-#include <linux/hfs_fs.h>
 #include <linux/devpts_fs.h>
-#include <linux/bfs_fs.h>
-#include <linux/openprom_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -51,40 +31,8 @@ extern int init_coda(void);
 extern int init_devpts_fs(void);
 #endif
 
-#ifdef CONFIG_SUN_OPENPROMFS
-extern int init_openprom_fs(void);
-#endif
-
 void __init filesystem_setup(void)
 {
-#ifdef CONFIG_MINIX_FS
-       init_minix_fs();
-#endif
-
-#ifdef CONFIG_ROMFS_FS
-       init_romfs_fs();
-#endif
-
-#ifdef CONFIG_UMSDOS_FS
-       init_umsdos_fs();
-#endif
-
-#ifdef CONFIG_FAT_FS
-       init_fat_fs();
-#endif
-
-#ifdef CONFIG_MSDOS_FS
-       init_msdos_fs();
-#endif
-
-#ifdef CONFIG_VFAT_FS
-       init_vfat_fs();
-#endif
-
-#ifdef CONFIG_PROC_FS
-       init_proc_fs();
-#endif
-
        init_devfs_fs();  /*  Header file may make this empty  */
 
 #ifdef CONFIG_NFS_FS
@@ -95,65 +43,9 @@ void __init filesystem_setup(void)
        init_coda();
 #endif
 
-#ifdef CONFIG_SMB_FS
-       init_smb_fs();
-#endif
-
-#ifdef CONFIG_NCP_FS
-       init_ncp_fs();
-#endif
-
-#ifdef CONFIG_ISO9660_FS
-       init_iso9660_fs();
-#endif
-
-#ifdef CONFIG_SYSV_FS
-       init_sysv_fs();
-#endif
-
-#ifdef CONFIG_HPFS_FS
-       init_hpfs_fs();
-#endif
-
-#ifdef CONFIG_NTFS_FS
-       init_ntfs_fs();
-#endif
-
-#ifdef CONFIG_HFS_FS
-       init_hfs_fs();
-#endif
-
-#ifdef CONFIG_AFFS_FS
-       init_affs_fs();
-#endif
-
-#ifdef CONFIG_UFS_FS
-       init_ufs_fs();
-#endif
-
-#ifdef CONFIG_EFS_FS
-       init_efs_fs();
-#endif
-
 #ifdef CONFIG_DEVPTS_FS
        init_devpts_fs();
 #endif
-
-#ifdef CONFIG_QNX4FS_FS
-       init_qnx4_fs();
-#endif
-
-#ifdef CONFIG_UDF_FS
-       init_udf_fs();
-#endif
-
-#ifdef CONFIG_BFS_FS
-       init_bfs_fs();
-#endif
-
-#ifdef CONFIG_SUN_OPENPROMFS
-       init_openprom_fs();
-#endif
 }
 
 #ifndef CONFIG_NFSD
index 251690dc8e7c699127c87041a76deaf22edc89e0..8c91758d60ee7de085d252fede6dbc5e395db93a 100644 (file)
@@ -472,38 +472,19 @@ bail3:
        return NULL;    
 }
 
-int __init init_hfs_fs(void)
+static int __init init_hfs_fs(void)
 {
         hfs_cat_init();
        return register_filesystem(&hfs_fs);
 }
 
-#ifdef MODULE
-int init_module(void) {
-       int error;
-
-#if defined(DEBUG_SIZES) || defined(DEBUG_ALL)
-       hfs_warn("HFS inode: %d bytes available\n",
-                sizeof(struct ext2_inode_info)-sizeof(struct hfs_inode_info));
-       hfs_warn("HFS super_block: %d bytes available\n",
-                sizeof(struct ext2_sb_info)-sizeof(struct hfs_sb_info));
-       if ((sizeof(struct hfs_inode_info)>sizeof(struct ext2_inode_info)) ||
-           (sizeof(struct hfs_sb_info)>sizeof(struct ext2_sb_info))) {
-               return -ENOMEM; /* well sort of */
-       }
-#endif
-       error = init_hfs_fs();
-       if (!error) {
-               /* register_symtab(NULL); */
-       }
-       return error;
-}
-
-void cleanup_module(void) {
+static void __exit exit_hfs_fs(void) {
        hfs_cat_free();
        unregister_filesystem(&hfs_fs);
 }
-#endif
+
+module_init(init_hfs_fs)
+module_exit(exit_hfs_fs)
 
 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
 long int hfs_alloc = 0;
index 8bcbf28fcabdefebf4804cd8d032fb0a2443200a..dc9ccf624e9aea12f342eaa14f48a30c96a86394 100644 (file)
@@ -125,7 +125,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
        kdev_t dev = s->s_dev;
        struct buffer_head *bh;
 
-       if (!ahead || secno + ahead >= s->s_hpfs_fs_size)
+                                       /* vvvv - workaround for the breada bug */
+       if (!ahead || secno + ahead + (read_ahead[MAJOR(dev)] >> 9) >= s->s_hpfs_fs_size)
                *bhp = bh = bread(dev, secno, 512);
        else *bhp = bh = breada(dev, secno, 512, 0, (ahead + 1) << 9);
        if (bh != NULL)
@@ -144,6 +145,7 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
        /*return hpfs_map_sector(s, secno, bhp, 0);*/
 
        if ((*bhp = bh = getblk(s->s_dev, secno, 512)) != NULL) {
+               if (!buffer_uptodate(bh)) wait_on_buffer(bh);
                mark_buffer_uptodate(bh, 1);
                return bh->b_data;
        } else {
@@ -172,8 +174,9 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
                goto bail;
        }
 
-       if (!ahead || secno + 4 + ahead > s->s_hpfs_fs_size)
-               qbh->bh[0] = bh = breada(dev, secno, 512, 0, 2048);
+                                       /* vvvv - workaround for the breada bug */
+       if (!ahead || secno + 4 + ahead + (read_ahead[MAJOR(dev)] >> 9) > s->s_hpfs_fs_size)
+               qbh->bh[0] = bh = bread(dev, secno, 512);
        else qbh->bh[0] = bh = breada(dev, secno, 512, 0, (ahead + 4) << 9);
        if (!bh)
                goto bail0;
index 677fda52c0a2d2dc03c8f5b3be9ccc9954f7baf8..5071782b0d6ebae6072f62956fb64e3f1babe838 100644 (file)
@@ -312,6 +312,5 @@ int hpfs_remount_fs(struct super_block *, int *, char *);
 void hpfs_put_super(struct super_block *);
 unsigned hpfs_count_one_bitmap(struct super_block *, secno);
 int hpfs_statfs(struct super_block *, struct statfs *);
-struct super_block *hpfs_read_super(struct super_block *, void *, int);
 
 extern struct address_space_operations hpfs_aops;
index c8283c6723eafaa4427fe381790ba68b8ae1a85f..69303cb9e91a153c3138f127104fe66f56d4d18a 100644 (file)
@@ -314,4 +314,5 @@ void hpfs_write_if_changed(struct inode *inode)
 void hpfs_delete_inode(struct inode *inode)
 {
        hpfs_remove_fnode(inode->i_sb, inode->i_ino);
+       clear_inode(inode);
 }
index d29f6e57415f21a1136ac516abe8f0fafb978e3c..04cd6428d1696ef18755d0115cbd25be73a6adc8 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/string.h>
 #include "hpfs_fn.h"
 #include <linux/module.h>
+#include <linux/init.h>
 
 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
 
@@ -557,26 +558,17 @@ bail0:
 
 DECLARE_FSTYPE_DEV(hpfs_fs_type, "hpfs", hpfs_read_super);
 
-int init_hpfs_fs(void)
+static int __init init_hpfs_fs(void)
 {
        return register_filesystem(&hpfs_fs_type);
 }
 
-#ifdef MODULE
-
-/*int register_symtab_from(struct symbol_table *, long *);*/
-
-int init_module(void)
-{
-       /*int status;
-       if (!(status = init_hpfs_fs())) register_symtab(NULL);
-       return status;*/
-       return init_hpfs_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_hpfs_fs(void)
 {
        unregister_filesystem(&hpfs_fs_type);
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_hpfs_fs)
+module_exit(exit_hpfs_fs)
index 784e7c18343066b87dc66a11c38fdefa2e202498..4ecd72cd2f703aee711f695dd04d72b329204def 100644 (file)
@@ -1436,22 +1436,17 @@ void leak_check_brelse(struct buffer_head * bh){
 
 static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
 
-int __init init_iso9660_fs(void)
+static int __init init_iso9660_fs(void)
 {
         return register_filesystem(&iso9660_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
+static void __exit exit_iso9660_fs(void)
 {
-       return init_iso9660_fs();
+        unregister_filesystem(&iso9660_fs_type);
 }
 
-void cleanup_module(void)
-{
-       unregister_filesystem(&iso9660_fs_type);
-}
+EXPORT_NO_SYMBOLS;
 
-#endif
+module_init(init_iso9660_fs)
+module_exit(exit_iso9660_fs)
index 31d4c99c7e39b5486daf41f8d42457a64e9f3419..4c9fa16a36355b77584c8928edc246587821bc21 100644 (file)
@@ -1267,22 +1267,17 @@ int minix_sync_inode(struct inode * inode)
 
 static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
 
-int __init init_minix_fs(void)
+static int __init init_minix_fs(void)
 {
         return register_filesystem(&minix_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
+static void __exit exit_minix_fs(void)
 {
-       return init_minix_fs();
+        unregister_filesystem(&minix_fs_type);
 }
 
-void cleanup_module(void)
-{
-       unregister_filesystem(&minix_fs_type);
-}
+EXPORT_NO_SYMBOLS;
 
-#endif
+module_init(init_minix_fs)
+module_exit(exit_minix_fs)
index 8e9897f2f4fa6d4a75cd38c31397e94fa05186ea..7b578f00fe748905b0a265a55e1c89d2c0785a6d 100644 (file)
@@ -26,10 +26,17 @@ EXPORT_SYMBOL(msdos_unlink);
 EXPORT_SYMBOL(msdos_read_super);
 EXPORT_SYMBOL(msdos_put_super);
 
+static DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
 
-DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
-
-int __init init_msdos_fs(void)
+static int __init init_msdos_fs(void)
 {
        return register_filesystem(&msdos_fs_type);
 }
+
+static void __exit exit_msdos_fs(void)
+{
+       unregister_filesystem(&msdos_fs_type);
+}
+
+module_init(init_msdos_fs)
+module_exit(exit_msdos_fs)
index 7febeaa8b453df042a94b2842802ad6496a347d1..495df7cd192c9b75b9707cd5adc36337c4779f4e 100644 (file)
@@ -599,28 +599,7 @@ struct super_block *msdos_read_super(struct super_block *sb,void *data, int sile
 
        MSDOS_SB(sb)->options.isvfat = 0;
        res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
-       if (res == NULL)
-               goto out_fail;
-       sb->s_root->d_op = &msdos_dentry_operations;
+       if (res)
+               sb->s_root->d_op = &msdos_dentry_operations;
        return res;
-
-out_fail:
-       return NULL;
-}
-
-
-
-#ifdef MODULE
-int init_module(void)
-{
-       return init_msdos_fs();
 }
-
-
-void cleanup_module(void)
-{
-       unregister_filesystem(&msdos_fs_type);
-}
-
-#endif
-
index 349eec58925f6fd670c41e672ddbc35b824c4598..1c3b857f3cb77991de5d6fcf3601238a90e23778 100644 (file)
@@ -698,15 +698,7 @@ int ncp_current_malloced;
 
 static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
 
-int __init init_ncp_fs(void)
-{
-       return register_filesystem(&ncp_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
+static int __init init_ncp_fs(void)
 {
        DPRINTK("ncpfs: init_module called\n");
 
@@ -717,7 +709,7 @@ int init_module(void)
        return init_ncp_fs();
 }
 
-void cleanup_module(void)
+static void __exit exit_ncp_fs(void)
 {
        DPRINTK("ncpfs: cleanup_module called\n");
        unregister_filesystem(&ncp_fs_type);
@@ -727,4 +719,7 @@ void cleanup_module(void)
 #endif
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_ncp_fs)
+module_exit(exit_ncp_fs)
index a24faac65d894310ce07c735bde6d30f7a086cde..e95a36179b9369d9325a6b321ad6b5e4d0d115d7 100644 (file)
@@ -921,13 +921,7 @@ ntfs_read_super_dec:
  */
 static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
 
-/* When this code is not compiled as a module, this is the main entry point,
- * called by do_sys_setup() in fs/filesystems.c
- *
- * NOTE : __init is a macro used to remove this function from memory
- * once initialization is done
- */
-int __init init_ntfs_fs(void)
+static int __init init_ntfs_fs(void)
 {
        /* Comment this if you trust klogd. There are reasons not to trust it
         */
@@ -942,44 +936,21 @@ int __init init_ntfs_fs(void)
        return register_filesystem(&ntfs_fs_type);
 }
 
-#ifdef MODULE
-/* A module is a piece of code which can be inserted in and removed
- * from the running kernel whenever you want using lsmod, or on demand using
- * kmod
- */
+static __exit void exit_ntfs_fs(void)
+{
+       SYSCTL(0);
+       ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);
+       unregister_filesystem(&ntfs_fs_type);
+}
 
-/* No function of this module is needed by another module */
 EXPORT_NO_SYMBOLS;
-/* Only used for documentation purposes at the moment,
- * see include/linux/module.h
- */
 MODULE_AUTHOR("Martin von Löwis");
 MODULE_DESCRIPTION("NTFS driver");
-/* no MODULE_SUPPORTED_DEVICE() */
-/* Load-time parameter */
 MODULE_PARM(ntdebug, "i");
 MODULE_PARM_DESC(ntdebug, "Debug level");
 
-/* When this code is compiled as a module, if you use mount -t ntfs when no
- * ntfs filesystem is registered (see /proc/filesystems), get_fs_type() in
- * fs/super.c asks kmod to load the module named ntfs in memory.
- *
- * Therefore, this function is the main entry point in this case
- */
-int init_module(void)
-{
-       return init_ntfs_fs();
-}
-
-/* Called by kmod just before the kernel removes the module from memory */
-void cleanup_module(void)
-{
-       SYSCTL(0);
-       ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);
-       unregister_filesystem(&ntfs_fs_type);
-}
-#endif
-
+module_init(init_ntfs_fs)
+module_exit(exit_ntfs_fs)
 /*
  * Local variables:
  *  c-file-style: "linux"
index 2b97d6c50e5d597329fc396dac67da9f3c409778..5199aceaac33b479075141145b887633826d88b9 100644 (file)
@@ -1026,7 +1026,7 @@ out_no_root:
 
 static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0);
 
-int init_openprom_fs(void)
+static int __init init_openprom_fs(void)
 {
        nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
        if (!nodes) {
@@ -1041,25 +1041,7 @@ int init_openprom_fs(void)
        return register_filesystem(&openprom_fs_type);
 }
 
-#ifdef MODULE
-
-EXPORT_NO_SYMBOLS;
-
-int init_module (void)
-{
-       return init_openprom_fs();
-}
-
-#else
-
-void __init openpromfs_init (void)
-{
-       init_openprom_fs();
-}
-#endif
-
-#ifdef MODULE
-void cleanup_module (void)
+static void __exit exit_openprom_fs(void)
 {
        int i;
        unregister_filesystem(&openprom_fs_type);
@@ -1069,4 +1051,8 @@ void cleanup_module (void)
                        kfree (alias_names [i]);
        nodes = NULL;
 }
-#endif
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_openprom_fs)
+module_exit(exit_openprom_fs)
index 0203b9776e1ac4fbf494e662c08437d36448a745..097e83468ed4dffcb4b02b45262e386a17d96f3d 100644 (file)
@@ -22,7 +22,15 @@ EXPORT_SYMBOL(proc_root_driver);
 
 static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, 0);
 
-int __init init_proc_fs(void)
+static int __init init_proc_fs(void)
 {
-       return register_filesystem(&proc_fs_type) == 0;
+       return register_filesystem(&proc_fs_type);
 }
+
+static void __exit exit_proc_fs(void)
+{
+       unregister_filesystem(&proc_fs_type);
+}
+
+module_init(init_proc_fs)
+module_exit(exit_proc_fs)
index b85483d3d0aec88d0d0f7d94988ca6ee443037fb..9e78119c9e7be40b2954cb2c6efa85e5680c0e06 100644 (file)
@@ -491,23 +491,18 @@ static void qnx4_read_inode(struct inode *inode)
 
 static DECLARE_FSTYPE_DEV(qnx4_fs_type, "qnx4", qnx4_read_super);
 
-int __init init_qnx4_fs(void)
+static int __init init_qnx4_fs(void)
 {
        printk("QNX4 filesystem 0.2.2 registered.\n");
        return register_filesystem(&qnx4_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
-       return init_qnx4_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_qnx4_fs(void)
 {
        unregister_filesystem(&qnx4_fs_type);
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_qnx4_fs)
+module_exit(exit_qnx4_fs)
index 15e80519fba5dd3bcaf70ccc61029ec0804ed2dd..7f5f2dee616aa33b55c266be17792db69c8b3b23 100644 (file)
@@ -532,26 +532,19 @@ static struct super_operations romfs_ops = {
 
 static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);
 
-int __init init_romfs_fs(void)
+static int __init init_romfs_fs(void)
 {
        return register_filesystem(&romfs_fs_type);
 }
 
-#ifdef MODULE
+static void __exit exit_romfs_fs(void)
+{
+       unregister_filesystem(&romfs_fs_type);
+}
 
 /* Yes, works even as a module... :) */
 
 EXPORT_NO_SYMBOLS;
 
-int
-init_module(void)
-{
-       return init_romfs_fs();
-}
-
-void
-cleanup_module(void)
-{
-       unregister_filesystem(&romfs_fs_type);
-}
-#endif
+module_init(init_romfs_fs)
+module_exit(exit_romfs_fs)
index 94923fbad7d292af132b1bf5840cdb1963d2027f..cef1e93cf4a60aa83ddd45b9c99dd2b1d960f25a 100644 (file)
@@ -536,16 +536,7 @@ int smb_current_vmalloced;
 
 static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
 
-int __init init_smb_fs(void)
-{
-       return register_filesystem(&smb_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int
-init_module(void)
+static int __init init_smb_fs(void)
 {
        pr_debug("smbfs: init_module called\n");
 
@@ -558,8 +549,7 @@ init_module(void)
        return init_smb_fs();
 }
 
-void
-cleanup_module(void)
+static void __exit exit_smb_fs(void)
 {
        pr_debug("smbfs: cleanup_module called\n");
        unregister_filesystem(&smb_fs_type);
@@ -570,4 +560,7 @@ cleanup_module(void)
 #endif
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_smb_fs)
+module_exit(exit_smb_fs)
index c1b95f28dfaf3b5a49401d3a61f7fdeb81ee2a23..3367c02efac324c62299c86f6c1adc07ab0e5a4b 100644 (file)
@@ -1188,22 +1188,17 @@ int sysv_sync_inode(struct inode * inode)
 
 static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
 
-int __init init_sysv_fs(void)
+static int __init init_sysv_fs(void)
 {
        return register_filesystem(&sysv_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
-       return init_sysv_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_sysv_fs(void)
 {
        unregister_filesystem(&sysv_fs_type);
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_sysv_fs)
+module_exit(exit_sysv_fs)
index 761cdcb6c4af3ca51c41d9abc6c9f0a09eae76e5..81f59e9a383175e107de6b1ba0d7ea450406aaf2 100644 (file)
@@ -127,62 +127,22 @@ struct udf_options
        uid_t uid;
 };
 
-#if defined(MODULE)
-       
-/*
- * cleanup_module
- *
- * PURPOSE
- *     Unregister the UDF filesystem type.
- *
- * DESCRIPTION
- *     Clean-up before the module is unloaded.
- *     This routine only applies when compiled as a module.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-int
-cleanup_module(void)
-{
-       printk(KERN_NOTICE "udf: unregistering filesystem\n");
-       return unregister_filesystem(&udf_fstype);
-}
 
-/*
- * init_module / init_udf_fs
- *
- * PURPOSE
- *     Register the UDF filesystem type.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-int init_module(void)
-#else /* if !defined(MODULE) */
-int __init init_udf_fs(void)
-#endif
+static int __init init_udf_fs(void)
 {
        printk(KERN_NOTICE "udf: registering filesystem\n");
-       {
-               struct super_block sb;
-               int size;
-
-               size = sizeof(struct super_block) +
-                       (long)&sb.u - (long)&sb;
-               if ( size < sizeof(struct udf_sb_info) )
-               {
-                       printk(KERN_ERR "udf: Danger! Kernel was compiled without enough room for udf_sb_info\n");
-                       printk(KERN_ERR "udf: Kernel has room for %u bytes, udf needs %lu\n",
-                               size, (unsigned long)sizeof(struct udf_sb_info));
-                       return 0;
-               }
-       }
        return register_filesystem(&udf_fstype);
 }
 
+static void __exit exit_udf_fs(void)
+{
+       printk(KERN_NOTICE "udf: unregistering filesystem\n");
+       unregister_filesystem(&udf_fstype);
+}
+
+module_init(init_udf_fs)
+module_exit(exit_udf_fs)
+
 /*
  * udf_parse_options
  *
index 1fe9de9bd3993030d175c59a0e333dc4e356c298..d9620a1c6ca963d07a6e8488ccf16ff93881160f 100644 (file)
@@ -951,22 +951,17 @@ static struct super_operations ufs_super_ops = {
 
 static DECLARE_FSTYPE_DEV(ufs_fs_type, "ufs", ufs_read_super);
 
-int __init init_ufs_fs(void)
+static int __init init_ufs_fs(void)
 {
        return register_filesystem(&ufs_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
-       return init_ufs_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_ufs_fs(void)
 {
        unregister_filesystem(&ufs_fs_type);
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_ufs_fs)
+module_exit(exit_ufs_fs)
index 61c832ed4cb18a50c8f92d51c8722562946ffd9f..649ce16d48df30123b40b1a8b3fa3a2c5baaa9cf 100644 (file)
@@ -435,22 +435,17 @@ out_noroot:
 
 static DECLARE_FSTYPE_DEV(umsdos_fs_type, "umsdos", UMSDOS_read_super);
 
-int __init init_umsdos_fs (void)
+static int __init init_umsdos_fs (void)
 {
        return register_filesystem (&umsdos_fs_type);
 }
 
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module (void)
-{
-       return init_umsdos_fs ();
-}
-
-void cleanup_module (void)
+static void __exit exit_umsdos_fs (void)
 {
        unregister_filesystem (&umsdos_fs_type);
 }
 
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_umsdos_fs)
+module_exit(exit_umsdos_fs)
index 2124941424329675bdba1ff3c9ac8823980d335f..1f7c788f58cb546f526a3f1ba89b39f9f5962f41 100644 (file)
@@ -1292,16 +1292,3 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data,
 
        return res;
 }
-
-#ifdef MODULE
-int init_module(void)
-{
-       return init_vfat_fs();
-}
-
-void cleanup_module(void)
-{
-       unregister_filesystem(&vfat_fs_type);
-}
-
-#endif /* ifdef MODULE */
index d57d153edf297bf1f5f224c517b639ea4e9ab2d7..6f1a121e00321f8b5ccb6ae057e2e14a6292f299 100644 (file)
@@ -8,6 +8,7 @@
 #define ASC_LINUX_VERSION(V, P, S)     (((V) * 65536) + ((P) * 256) + (S))
 #include <linux/version.h>
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
@@ -22,8 +23,15 @@ EXPORT_SYMBOL(vfat_rename);
 EXPORT_SYMBOL(vfat_read_super);
 EXPORT_SYMBOL(vfat_lookup);
 
-int init_vfat_fs(void)
+static int __init init_vfat_fs(void)
 {
        return register_filesystem(&vfat_fs_type);
 }
 
+static void __exit exit_vfat_fs(void)
+{
+       unregister_filesystem(&vfat_fs_type);
+}
+
+module_init(init_vfat_fs)
+module_exit(exit_vfat_fs)
index 6ec03679f42575ab10e31025f70e7914764680a8..239257b2177672d8bc8b9773dabaf08d3890924b 100644 (file)
 #define __NR_setfsuid32                215
 #define __NR_setfsgid32                216
 #define __NR_pivot_root                217
+#define __NR_mincore           218
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
index ab3b8c0784c7adcadc65886b247a3b4ae1df1f73..60af0d40cc5da02d2f1c593dba36ed226c30e477 100644 (file)
@@ -89,7 +89,6 @@ extern void                    affs_write_inode(struct inode *inode);
 /* super.c */
 
 extern int                      affs_fs(void);
-extern int                      init_affs_fs(void);
 
 /* file.c */
 
index 9525293cbd890602dccf85e96abdc728680c6864..afe274a4ce14ebfbdbe6d6ffd90366cab73bb96d 100644 (file)
@@ -78,9 +78,6 @@ struct bfs_super_block {
 
 #ifdef __KERNEL__
 
-/* inode.c */
-extern int init_bfs_fs(void);
-
 /* file.c */
 extern struct inode_operations bfs_file_inops;
 extern struct file_operations bfs_file_operations;
index cc23e2e0c629e14352071716449e281164804a07..ae049ed2f1478684893d8513efc0b78566e9a162 100644 (file)
@@ -49,10 +49,7 @@ extern struct inode_operations efs_dir_inode_operations;
 extern struct file_operations efs_dir_operations;
 extern struct address_space_operations efs_symlink_aops;
 
-extern int init_module(void);
-extern void cleanup_module(void);
 extern struct super_block *efs_read_super(struct super_block *, void *, int);
-extern void efs_put_super(struct super_block *);
 extern int efs_statfs(struct super_block *, struct statfs *);
 
 extern void efs_read_inode(struct inode *);
@@ -61,7 +58,4 @@ extern efs_block_t efs_map_block(struct inode *, efs_block_t);
 extern struct dentry *efs_lookup(struct inode *, struct dentry *);
 extern int efs_bmap(struct inode *, int);
 
-extern int init_efs_fs(void);
-
 #endif /* __EFS_FS_H__ */
-
index 3c39139433849e8f32ff85e8eed4471a289e7b11..65392fc39d8aaec5473d2017fbe111853015f36d 100644 (file)
@@ -302,7 +302,6 @@ extern void hfs_sngl_ifill(struct inode *, ino_t, const int);
 
 /* super.c */
 extern struct super_block *hfs_read_super(struct super_block *,void *,int);
-extern int init_hfs_fs(void);
 
 /* trans.c */
 extern void hfs_colon2mac(struct hfs_name *, const char *, int);
index 2b7926aba4dce137d3b6338b69accda829478cc6..a5028dd94d3105a4c78b42a62047dcbf3f213b88 100644 (file)
@@ -5,9 +5,4 @@
 
 #define HPFS_SUPER_MAGIC 0xf995e849
 
-/* The entry point for a VFS */
-
-extern struct super_block *hpfs_read_super (struct super_block *, void *, int);
-extern int init_hpfs_fs(void);
-
 #endif
index 47fab891482b713ead6a0c36c9c842e2880b804e..63543da77790d42de3bca9f66c3482e1c285e654 100644 (file)
@@ -186,7 +186,6 @@ int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
 extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
 extern int isofs_get_block(struct inode *, long, struct buffer_head *, int);
 extern int isofs_bmap(struct inode *, int);
-extern int init_iso9660_fs(void);
 extern int isofs_lookup_grandparent(struct inode *, int);
 
 extern struct inode_operations isofs_dir_inode_operations;
index 6f63a54c4171986471207db5f41da15c9aaeda5e..1eca767b46f6a147efd3cd20da43d448ac978157 100644 (file)
@@ -100,7 +100,6 @@ extern struct buffer_head * minix_getblk(struct inode *, int, int);
 extern struct buffer_head * minix_bread(struct inode *, int, int);
 
 extern void minix_truncate(struct inode *);
-extern int init_minix_fs(void);
 extern int minix_sync_inode(struct inode *);
 extern int minix_sync_file(struct file *, struct dentry *);
 
index ce7837f1dd4518324f6dcf75d25f990f2c8a300c..adcfb751dda52f960dfa640dfd02b5baf6b32d3e 100644 (file)
@@ -272,14 +272,6 @@ extern ssize_t fat_file_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *);
 extern void fat_truncate(struct inode *inode);
 
-/* vfat.c */
-extern int init_vfat_fs(void);
-
-
-/* msdosfs_syms.c */
-extern int init_msdos_fs(void);
-extern struct file_system_type msdos_fs_type;
-
 /* msdos.c */
 extern struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent);
 
@@ -294,7 +286,6 @@ extern int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
                        struct inode *new_dir,struct dentry *new_dentry);
 
 /* nls.c */
-extern int init_fat_nls(void);
 extern struct fat_nls_table *fat_load_nls(int codepage);
 
 /* tables.c */
index b028f984c3487e8b85909262c4fa68e946f274f1..87dfef8cbfedd602cc2241c45ec888b58d172f09 100644 (file)
@@ -228,7 +228,6 @@ struct super_block *ncp_read_super(struct super_block *, void *, int);
 struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
 void ncp_update_inode(struct inode *, struct ncp_entry_info *);
 void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
-extern int init_ncp_fs(void);
 
 /* linux/fs/ncpfs/dir.c */
 extern struct inode_operations ncp_dir_inode_operations;
index acbfc2939313243f89e68ee5c6c96d9f694e7ba8..7b30dd7b01745ecd01148840f7c1fd4845a6b03f 100644 (file)
@@ -1,7 +1,3 @@
 #ifndef _LINUX_NTFS_FS_H
 #define _LINUX_NTFS_FS_H
-
-int init_ntfs_fs(void);
-
 #endif
-
index 31a42d62c3cb4467e902d64944d7ca1a6c85a683..7607cf6ff47e84995bf88121515824b54ecb58e8 100644 (file)
@@ -54,6 +54,8 @@ extern struct exec_domain default_exec_domain;
 extern struct exec_domain *lookup_exec_domain(unsigned long personality);
 extern int register_exec_domain(struct exec_domain *it);
 extern int unregister_exec_domain(struct exec_domain *it);
+#define put_exec_domain(it) \
+       if (it && it->module) __MOD_DEC_USE_COUNT(it->module);
 asmlinkage long sys_personality(unsigned long personality);
 
 #endif /* _PERSONALITY_H */
index f5927109adbdbc3cf69dca7b1e8d0971a0e40a4d..f92195a3e5661c572ad5c0f46914892b91df8257 100644 (file)
@@ -98,7 +98,6 @@ extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 extern struct super_block *proc_super_blocks;
 extern struct super_block *proc_read_super(struct super_block *,void *,int);
-extern int init_proc_fs(void);
 extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
 
 extern int proc_match(int, const char *,struct proc_dir_entry *);
index 4e68ee5a6b931145500c76f86558638875acece5..ad5ca5543e08e6c210a068860f79139faa7279a5 100644 (file)
@@ -104,7 +104,6 @@ extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
 extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
 extern struct buffer_head *qnx4_bread(struct inode *, int, int);
 
-extern int init_qnx4_fs(void);
 extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
 extern struct inode_operations qnx4_file_inode_operations;
 extern struct inode_operations qnx4_dir_inode_operations;
index 844e22f994c6e2fc1d20ab7380db7d5946a9340f..8f452cbd4c085816f701da3bd3c6d2f7cdc6eccc 100644 (file)
@@ -56,7 +56,6 @@ struct romfs_inode {
 #ifdef __KERNEL__
 
 /* Not much now */
-extern int init_romfs_fs(void);
 
 #endif /* __KERNEL__ */
 #endif
index d11573ca59fb2cc775cb2a77c825d1a95af33e98..5df1ef295b2488e8ca8df8a28f60d9364ed577a4 100644 (file)
@@ -120,7 +120,6 @@ int  smb_revalidate_inode(struct dentry *);
 int  smb_notify_change(struct dentry *, struct iattr *);
 unsigned long smb_invent_inos(unsigned long);
 struct inode *smb_iget(struct super_block *, struct smb_fattr *);
-extern int init_smb_fs(void);
 
 /* linux/fs/smbfs/proc.c */
 __u32 smb_len(unsigned char *);
index 9e177c3d4b5b7f097b43d81a3bbb58b989e0d130..d9c2557e562ecbaacf2fd95527710fea3e39fd66 100644 (file)
@@ -377,7 +377,6 @@ extern unsigned long sysv_count_free_blocks(struct super_block *sb);
 extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
 
 extern void sysv_truncate(struct inode *);
-extern int init_sysv_fs(void);
 extern void sysv_write_inode(struct inode *);
 extern int sysv_sync_inode(struct inode *);
 extern int sysv_sync_file(struct file *, struct dentry *);
index 47980eaaf7ef08b10fce537d4927301c036f8e92..4f842ac3088818178261d65c58ef7f2723a64d39 100644 (file)
@@ -60,7 +60,6 @@
 /*
  * Function prototypes (all other prototypes included in udfdecl.h)
  */
-extern int init_udf_fs(void);
 
 #endif /* __KERNEL__ */
 
index d7c14cd74d957323cb72b609b69101a3f2195475..631791186172d693e3633853c005bd313e1c01bc 100644 (file)
@@ -546,7 +546,6 @@ extern struct file_system_type ufs_fs_type;
 extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern int init_ufs_fs(void);
 extern void ufs_write_super (struct super_block *);
 
 /* symlink.c */
index 6f113d28c5a52737d75eee20e3e0079d2a8977a8..8dcb93719cd718a944e1970f9d37357c014da008 100644 (file)
@@ -177,7 +177,6 @@ extern struct inode_operations umsdos_dir_inode_operations;
 extern struct inode_operations umsdos_rdir_inode_operations;
 extern struct file_operations umsdos_dir_operations;
 extern struct file_operations umsdos_rdir_operations;
-extern int init_umsdos_fs (void);
 
 #include <linux/umsdos_fs.p>
 
index 1ee1eee4d9d33ad02b4c17cf400848e10fd3386d..111a3d69c1d99b104d639abe6c6cc30843bf2847 100644 (file)
@@ -23,7 +23,7 @@ struct exec_domain default_exec_domain = {
 };
 
 static struct exec_domain *exec_domains = &default_exec_domain;
-
+static spinlock_t exec_domains_lock = SPIN_LOCK_UNLOCKED;
 
 static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
 {
@@ -32,15 +32,10 @@ static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
    * personality set incorrectly.  Check to see whether SVr4 is available,
    * and use it, otherwise give the user a SEGV.
    */
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
-
+       put_exec_domain(current->exec_domain);
        current->personality = PER_SVR4;
        current->exec_domain = lookup_exec_domain(current->personality);
 
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
-
        if (current->exec_domain && current->exec_domain->handler
        && current->exec_domain->handler != no_lcall7) {
                current->exec_domain->handler(segment, regs);
@@ -55,10 +50,15 @@ struct exec_domain *lookup_exec_domain(unsigned long personality)
        unsigned long pers = personality & PER_MASK;
        struct exec_domain *it;
 
+       spin_lock(&exec_domains_lock);
        for (it=exec_domains; it; it=it->next)
-               if (pers >= it->pers_low
-               && pers <= it->pers_high)
+               if (pers >= it->pers_low && pers <= it->pers_high) {
+                       if (!try_inc_mod_count(it->module))
+                               continue;
+                       spin_unlock(&exec_domains_lock);
                        return it;
+               }
+       spin_unlock(&exec_domains_lock);
 
        /* Should never get this far. */
        printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
@@ -73,11 +73,15 @@ int register_exec_domain(struct exec_domain *it)
                return -EINVAL;
        if (it->next)
                return -EBUSY;
+       spin_lock(&exec_domains_lock);
        for (tmp=exec_domains; tmp; tmp=tmp->next)
-               if (tmp == it)
+               if (tmp == it) {
+                       spin_unlock(&exec_domains_lock);
                        return -EBUSY;
+               }
        it->next = exec_domains;
        exec_domains = it;
+       spin_unlock(&exec_domains_lock);
        return 0;
 }
 
@@ -86,14 +90,17 @@ int unregister_exec_domain(struct exec_domain *it)
        struct exec_domain ** tmp;
 
        tmp = &exec_domains;
+       spin_lock(&exec_domains_lock);
        while (*tmp) {
                if (it == *tmp) {
                        *tmp = it->next;
                        it->next = NULL;
+                       spin_unlock(&exec_domains_lock);
                        return 0;
                }
                tmp = &(*tmp)->next;
        }
+       spin_unlock(&exec_domains_lock);
        return -EINVAL;
 }
 
@@ -113,12 +120,9 @@ asmlinkage long sys_personality(unsigned long personality)
                goto out;
 
        old_personality = current->personality;
-       if (current->exec_domain && current->exec_domain->module)
-               __MOD_DEC_USE_COUNT(current->exec_domain->module);
+       put_exec_domain(current->exec_domain);
        current->personality = personality;
        current->exec_domain = it;
-       if (current->exec_domain->module)
-               __MOD_INC_USE_COUNT(current->exec_domain->module);
        ret = old_personality;
 out:
        unlock_kernel();
@@ -130,9 +134,11 @@ int get_exec_domain_list(char * page)
        int len = 0;
        struct exec_domain * e;
 
+       spin_lock(&exec_domains_lock);
        for (e=exec_domains; e && len < PAGE_SIZE - 80; e=e->next)
                len += sprintf(page+len, "%d-%d\t%-16s\t[%s]\n",
                        e->pers_low, e->pers_high, e->name,
                        e->module ? e->module->name : "kernel");
+       spin_unlock(&exec_domains_lock);
        return len;
 }
index fcc83f997624b6bbbce1f9a5ff5b893b53dcd5dc..7c834b8934f6b55bf7e649c4482dd313e1bdb81c 100644 (file)
@@ -425,8 +425,7 @@ fake_volatile:
        tsk->exit_code = code;
        exit_notify();
        task_unlock(tsk);
-       if (tsk->exec_domain && tsk->exec_domain->module)
-               __MOD_DEC_USE_COUNT(tsk->exec_domain->module);
+       put_exec_domain(tsk->exec_domain);
        if (tsk->binfmt && tsk->binfmt->module)
                __MOD_DEC_USE_COUNT(tsk->binfmt->module);
        schedule();
index f30adb90878c2e3c66f58166976679251705e19f..da4de2c9bbf690ab6428e2d2911204a2a8b48a94 100644 (file)
@@ -748,8 +748,7 @@ bad_fork_cleanup_fs:
 bad_fork_cleanup_files:
        exit_files(p); /* blocking */
 bad_fork_cleanup:
-       if (p->exec_domain && p->exec_domain->module)
-               __MOD_DEC_USE_COUNT(p->exec_domain->module);
+       put_exec_domain(p->exec_domain);
        if (p->binfmt && p->binfmt->module)
                __MOD_DEC_USE_COUNT(p->binfmt->module);
 bad_fork_cleanup_count:
index b5febc2e5edc446da37f496695c8f107eb58e19d..4fa56405bc990ac0ffee7c6007d1e4322a3dab5d 100644 (file)
@@ -1727,6 +1727,160 @@ out:
        return error;
 }
 
+/*
+ * Later we can get more picky about what "in core" means precisely.
+ * For now, simply check to see if the page is in the page cache,
+ * and is up to date; i.e. that no page-in operation would be required
+ * at this time if an application were to map and access this page.
+ */
+static unsigned char mincore_page(struct vm_area_struct * vma,
+       unsigned long pgoff)
+{
+       unsigned char present = 0;
+       struct address_space * as = &vma->vm_file->f_dentry->d_inode->i_data;
+       struct page * page, ** hash = page_hash(as, pgoff);
+
+       spin_lock(&pagecache_lock);
+       page = __find_page_nolock(as, pgoff, *hash);
+       if ((page) && (Page_Uptodate(page)))
+               present = 1;
+       spin_unlock(&pagecache_lock);
+
+       return present;
+}
+
+static long mincore_vma(struct vm_area_struct * vma,
+       unsigned long start, unsigned long end, unsigned char * vec)
+{
+       long error, i, remaining;
+       unsigned char * tmp;
+
+       error = -ENOMEM;
+       if (!vma->vm_file)
+               return error;
+
+       start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+       if (end > vma->vm_end)
+               end = vma->vm_end;
+       end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+
+       error = -EAGAIN;
+       tmp = (unsigned char *) __get_free_page(GFP_KERNEL);
+       if (!tmp)
+               return error;
+
+       /* (end - start) is # of pages, and also # of bytes in "vec */
+       remaining = (end - start),
+
+       error = 0;
+       for (i = 0; remaining > 0; remaining -= PAGE_SIZE, i++) {
+               int j = 0;
+               long thispiece = (remaining < PAGE_SIZE) ?
+                                               remaining : PAGE_SIZE;
+
+               while (j < thispiece)
+                       tmp[j++] = mincore_page(vma, start++);
+
+               if (copy_to_user(vec + PAGE_SIZE * i, tmp, thispiece)) {
+                       error = -EFAULT;
+                       break;
+               }
+       }
+
+       free_page((unsigned long) tmp);
+       return error;
+}
+
+/*
+ * The mincore(2) system call.
+ *
+ * mincore() returns the memory residency status of the pages in the
+ * current process's address space specified by [addr, addr + len).
+ * The status is returned in a vector of bytes.  The least significant
+ * bit of each byte is 1 if the referenced page is in memory, otherwise
+ * it is zero.
+ *
+ * Because the status of a page can change after mincore() checks it
+ * but before it returns to the application, the returned vector may
+ * contain stale information.  Only locked pages are guaranteed to
+ * remain in memory.
+ *
+ * return values:
+ *  zero    - success
+ *  -EFAULT - vec points to an illegal address
+ *  -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE,
+ *             or len has a nonpositive value
+ *  -ENOMEM - Addresses in the range [addr, addr + len] are
+ *             invalid for the address space of this process, or
+ *             specify one or more pages which are not currently
+ *             mapped
+ *  -EAGAIN - A kernel resource was temporarily unavailable.
+ */
+asmlinkage long sys_mincore(unsigned long start, size_t len,
+       unsigned char * vec)
+{
+       int index = 0;
+       unsigned long end;
+       struct vm_area_struct * vma;
+       int unmapped_error = 0;
+       long error = -EINVAL;
+
+       down(&current->mm->mmap_sem);
+
+       if (start & ~PAGE_MASK)
+               goto out;
+       len = (len + ~PAGE_MASK) & PAGE_MASK;
+       end = start + len;
+       if (end < start)
+               goto out;
+
+       error = 0;
+       if (end == start)
+               goto out;
+
+       /*
+        * If the interval [start,end) covers some unmapped address
+        * ranges, just ignore them, but return -ENOMEM at the end.
+        */
+       vma = find_vma(current->mm, start);
+       for (;;) {
+               /* Still start < end. */
+               error = -ENOMEM;
+               if (!vma)
+                       goto out;
+
+               /* Here start < vma->vm_end. */
+               if (start < vma->vm_start) {
+                       unmapped_error = -ENOMEM;
+                       start = vma->vm_start;
+               }
+
+               /* Here vma->vm_start <= start < vma->vm_end. */
+               if (end <= vma->vm_end) {
+                       if (start < end) {
+                               error = mincore_vma(vma, start, end,
+                                                       &vec[index]);
+                               if (error)
+                                       goto out;
+                       }
+                       error = unmapped_error;
+                       goto out;
+               }
+
+               /* Here vma->vm_start <= start < vma->vm_end < end. */
+               error = mincore_vma(vma, start, vma->vm_end, &vec[index]);
+               if (error)
+                       goto out;
+               index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT;
+               start = vma->vm_end;
+               vma = vma->vm_next;
+       }
+
+out:
+       up(&current->mm->mmap_sem);
+       return error;
+}
+
 struct page *read_cache_page(struct address_space *mapping,
                                unsigned long index,
                                int (*filler)(void *,struct page*),