From a1bcda3256956318c95c8da8bee09f79190bb034 Mon Sep 17 00:00:00 2001 From: linus1 Date: Fri, 10 Mar 2000 12:00:00 -0600 Subject: [PATCH] Import 2.3.52pre3 --- arch/arm/kernel/arch.c | 1 + arch/i386/kernel/entry.S | 3 +- arch/mips/kernel/irixelf.c | 27 +- arch/sparc/kernel/sys_solaris.c | 2 + arch/sparc64/kernel/binfmt_aout32.c | 48 +- arch/sparc64/solaris/misc.c | 5 +- drivers/net/pcmcia/3c574_cs.c | 12 +- drivers/net/ppp_synctty.c | 2 +- drivers/net/wan/comx-hw-comx.c | 1 - drivers/net/wan/comx-hw-locomx.c | 2 - drivers/net/wan/comx-hw-mixcom.c | 1 - drivers/net/wan/comx-proto-fr.c | 1 - drivers/net/wan/comx-proto-lapb.c | 1 - drivers/net/wan/comx-proto-ppp.c | 1 - drivers/net/wan/comx.h | 1 + drivers/scsi/Config.in | 4 - drivers/scsi/README.st | 8 +- drivers/scsi/st.c | 738 ++++++++++++++++------------ drivers/scsi/st.h | 11 +- drivers/scsi/st_options.h | 9 +- drivers/sound/Config.in | 4 +- drivers/sound/dev_table.c | 2 - drivers/sound/dev_table.h | 36 +- drivers/sound/mpu401.c | 21 +- drivers/sound/sb_card.c | 2 - drivers/sound/soundcard.c | 57 +-- drivers/usb/ov511.c | 1 - drivers/video/hgafb.c | 86 ++-- fs/adfs/dir.c | 1 + fs/affs/super.c | 19 +- fs/bfs/inode.c | 15 +- fs/binfmt_aout.c | 49 +- fs/binfmt_elf.c | 39 +- fs/binfmt_em86.c | 11 +- fs/binfmt_misc.c | 2 - fs/binfmt_script.c | 11 +- fs/coda/psdev.c | 2 - fs/efs/super.c | 23 +- fs/exec.c | 38 +- fs/fat/fatfs_syms.c | 5 +- fs/fat/inode.c | 16 - fs/filesystems.c | 108 ---- fs/hfs/super.c | 29 +- fs/hpfs/buffer.c | 9 +- fs/hpfs/hpfs_fn.h | 1 - fs/hpfs/inode.c | 1 + fs/hpfs/super.c | 22 +- fs/isofs/inode.c | 17 +- fs/minix/inode.c | 17 +- fs/msdos/msdosfs_syms.c | 13 +- fs/msdos/namei.c | 25 +- fs/ncpfs/inode.c | 17 +- fs/ntfs/fs.c | 47 +- fs/openpromfs/inode.c | 28 +- fs/proc/procfs_syms.c | 12 +- fs/qnx4/inode.c | 17 +- fs/romfs/inode.c | 21 +- fs/smbfs/inode.c | 19 +- fs/sysv/inode.c | 17 +- fs/udf/super.c | 60 +-- fs/ufs/super.c | 17 +- fs/umsdos/inode.c | 17 +- fs/vfat/namei.c | 13 - fs/vfat/vfatfs_syms.c | 10 +- include/asm-i386/unistd.h | 1 + include/linux/affs_fs.h | 1 - include/linux/bfs_fs.h | 3 - include/linux/efs_fs.h | 6 - include/linux/hfs_fs.h | 1 - include/linux/hpfs_fs.h | 5 - include/linux/iso_fs.h | 1 - include/linux/minix_fs.h | 1 - include/linux/msdos_fs.h | 9 - include/linux/ncp_fs.h | 1 - include/linux/ntfs_fs.h | 4 - include/linux/personality.h | 2 + include/linux/proc_fs.h | 1 - include/linux/qnx4_fs.h | 1 - include/linux/romfs_fs.h | 1 - include/linux/smb_fs.h | 1 - include/linux/sysv_fs.h | 1 - include/linux/udf_fs.h | 1 - include/linux/ufs_fs.h | 1 - include/linux/umsdos_fs.h | 1 - kernel/exec_domain.c | 34 +- kernel/exit.c | 3 +- kernel/fork.c | 3 +- mm/filemap.c | 154 ++++++ 88 files changed, 920 insertions(+), 1172 deletions(-) diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c index 615ed568b87f9..8645497ae8ec2 100644 --- a/arch/arm/kernel/arch.c +++ b/arch/arm/kernel/arch.c @@ -3,6 +3,7 @@ * * Architecture specifics */ +#include #include #include diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 0c3cae5d9ad10..1381fb84252a4 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -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 diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 3e61f516b127f..b6cc30fed8f8b 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -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 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, 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; } diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c index 6c46c60f0e43c..8a9d54913068d 100644 --- a/arch/sparc/kernel/sys_solaris.c +++ b/arch/sparc/kernel/sys_solaris.c @@ -15,12 +15,14 @@ #include #include +/* 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); diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index 009c506a0fa86..3e95ed9cfafe3 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -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 @@ do_aout32_core_dump(long signr, struct pt_regs * regs, struct file *file) 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 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm, 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 @@ do_load_aout32_library(int fd) 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); diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 9e2bd4118f298..9ac4027e4b9b8 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -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(); } diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 2b5624b293eb5..53f841af2937a 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -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) diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 1a69f6ede7f1b..8bae76e1c480d 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -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; diff --git a/drivers/net/wan/comx-hw-comx.c b/drivers/net/wan/comx-hw-comx.c index 4e6913c62ebdd..7381dc8a9c470 100644 --- a/drivers/net/wan/comx-hw-comx.c +++ b/drivers/net/wan/comx-hw-comx.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wan/comx-hw-locomx.c b/drivers/net/wan/comx-hw-locomx.c index 00ab42c1fdee0..010f02373147d 100644 --- a/drivers/net/wan/comx-hw-locomx.c +++ b/drivers/net/wan/comx-hw-locomx.c @@ -31,7 +31,6 @@ #define VERSION "0.13" -#include #include #include #include @@ -44,7 +43,6 @@ #include #include #include -#include #include "comx.h" #include "z85230.h" diff --git a/drivers/net/wan/comx-hw-mixcom.c b/drivers/net/wan/comx-hw-mixcom.c index 89a706fd8029e..552443f886c52 100644 --- a/drivers/net/wan/comx-hw-mixcom.c +++ b/drivers/net/wan/comx-hw-mixcom.c @@ -33,7 +33,6 @@ #define VERSION "0.64" -#include #include #include #include diff --git a/drivers/net/wan/comx-proto-fr.c b/drivers/net/wan/comx-proto-fr.c index f3f89f8f7f90d..ad62e310c92b4 100644 --- a/drivers/net/wan/comx-proto-fr.c +++ b/drivers/net/wan/comx-proto-fr.c @@ -29,7 +29,6 @@ #define VERSION "0.72" -#include #include #include #include diff --git a/drivers/net/wan/comx-proto-lapb.c b/drivers/net/wan/comx-proto-lapb.c index 7c3adba484379..c0fc0c6bd6763 100644 --- a/drivers/net/wan/comx-proto-lapb.c +++ b/drivers/net/wan/comx-proto-lapb.c @@ -20,7 +20,6 @@ #define VERSION "0.80" -#include #include #include #include diff --git a/drivers/net/wan/comx-proto-ppp.c b/drivers/net/wan/comx-proto-ppp.c index 68472c0e1566b..0b791685d0d97 100644 --- a/drivers/net/wan/comx-proto-ppp.c +++ b/drivers/net/wan/comx-proto-ppp.c @@ -33,7 +33,6 @@ #define VERSION "0.23" -#include #include #include #include diff --git a/drivers/net/wan/comx.h b/drivers/net/wan/comx.h index c3da445dffaf4..e02849b90bf7e 100644 --- a/drivers/net/wan/comx.h +++ b/drivers/net/wan/comx.h @@ -25,6 +25,7 @@ * tx_carrier_errors modem line status changes * tx_fifo_errors tx underrun (locomx) */ +#include struct comx_protocol { char *name; diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in index b064b6fbf955f..b0407de9e80e1 100644 --- a/drivers/scsi/Config.in +++ b/drivers/scsi/Config.in @@ -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 diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st index b1b6362f30a2f..77121aa0b9716 100644 --- a/drivers/scsi/README.st +++ b/drivers/scsi/README.st @@ -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 diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 1de7686dc2a1b..8df062781ee76 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -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 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); - /* 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) } /* 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; } +#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 ). + 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; } /* 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); } /* 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 ). + + 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, } -/* 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++) { diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index e751efc28d340..47b3fbff59d78 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -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 diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h index 8cbc1c69eb800..fa3926c5d96f6 100644 --- a/drivers/scsi/st_options.h +++ b/drivers/scsi/st_options.h @@ -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 diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index f79919b9f6eca..947e0294eb034 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -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 diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 52d4d79f84c76..99a4d8f44962e 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -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, diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index db2b141d694b1..a5525a4bf21cb 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -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); diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index 2757659aceb7c..a329f0e72198c 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -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; } diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index 40804417c3cb1..c471163efc3dc 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -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 diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index 00f8b6e7b49a8..ea90ed81ca67b 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -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 diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index 764b37753d82b..d1f5048e39544 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -36,7 +36,6 @@ /* Handle mangled (versioned) external symbols */ -#include /* retrieve the CONFIG_* macros */ #include #include #include diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index bffa6b02ef356..dead9038bd9b9 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -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 #include #include +#include #include #include #include @@ -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 */ diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 0dd364c664f64..c9226513e0d14 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -5,6 +5,7 @@ * * Common directory handling for ADFS */ +#include #include #include #include diff --git a/fs/affs/super.c b/fs/affs/super.c index 5f2387bdecf39..46c11a8e22195 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -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) diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 2c38ccafe5976..6f3765399250e 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -322,16 +322,15 @@ static struct super_block * bfs_read_super(struct super_block * s, 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) diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 41138e3fd3e85..5aa2f1b351d82 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -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 @@ do_aout_core_dump(long signr, struct pt_regs * regs, struct file *file) 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 int load_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 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs 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 @@ do_load_aout_library(int fd) 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); - diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index c329b725067ff..307037153dee1 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -383,8 +383,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex, #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 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) 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 @@ do_load_elf_library(int fd) 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 */ diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index d89bd9ca8e110..189d130cafabf 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -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 }; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 5d5d17bc4ce92..c530a6ff29d8d 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -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; } diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 8c71ec4a92b26..84dbf11b0aa09 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -13,7 +13,7 @@ #include #include -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 }; diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index c00a6945c6964..cc12ccaef6f32 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -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); diff --git a/fs/efs/super.c b/fs/efs/super.c index 092c2f0a7d2fa..7917bef5c6a35 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -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 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int silent) { 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); diff --git a/fs/exec.c b/fs/exec.c index 1b881e12312b2..e3ff2d0055eec 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -33,6 +33,9 @@ #include #include #include +#include +#define __NO_VERSION__ +#include #include #include @@ -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 diff --git a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c index 3a2e4ea820ec9..22ce56b685fbb 100644 --- a/fs/fat/fatfs_syms.c +++ b/fs/fat/fatfs_syms.c @@ -7,6 +7,7 @@ #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) #include #include +#include #include #include @@ -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) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index f95adc0fdcd80..cedd3ba2bda25 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -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 - diff --git a/fs/filesystems.c b/fs/filesystems.c index cedf675456eaf..6ad3ec407cfc2 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -9,30 +9,10 @@ #include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include -#include #include #include #include @@ -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 diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 251690dc8e7c6..8c91758d60ee7 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -472,38 +472,19 @@ struct super_block *hfs_read_super(struct super_block *s, void *data, 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; diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 8bcbf28fcabde..dc9ccf624e9ae 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -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; diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 677fda52c0a2d..5071782b0d6eb 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -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; diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index c8283c6723eaf..69303cb9e91a1 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -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); } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index d29f6e57415f2..04cd6428d1696 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -9,6 +9,7 @@ #include #include "hpfs_fn.h" #include +#include /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ @@ -557,26 +558,17 @@ bail2: brelse(bh0); 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) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 784e7c1834306..4ecd72cd2f703 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -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) diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 31d4c99c7e39b..4c9fa16a36355 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -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) diff --git a/fs/msdos/msdosfs_syms.c b/fs/msdos/msdosfs_syms.c index 8e9897f2f4fa6..7b578f00fe748 100644 --- a/fs/msdos/msdosfs_syms.c +++ b/fs/msdos/msdosfs_syms.c @@ -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) diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 7febeaa8b453d..495df7cd192c9 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -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 - diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 349eec58925f6..1c3b857f3cb77 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -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) diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index a24faac65d894..e95a36179b936 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -921,13 +921,7 @@ struct super_block * ntfs_read_super(struct super_block *sb, */ 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" diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 2b97d6c50e5d5..5199aceaac33b 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -1026,7 +1026,7 @@ struct super_block *openprom_read_super(struct super_block *s,void *data, 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) diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c index 0203b9776e1ac..097e83468ed4d 100644 --- a/fs/proc/procfs_syms.c +++ b/fs/proc/procfs_syms.c @@ -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) diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index b85483d3d0aec..9e78119c9e7be 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -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) diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 15e80519fba5d..7f5f2dee616aa 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -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) diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 94923fbad7d29..cef1e93cf4a60 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -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) diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index c1b95f28dfaf3..3367c02efac32 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -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) diff --git a/fs/udf/super.c b/fs/udf/super.c index 761cdcb6c4af3..81f59e9a38317 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -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 * diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 1fe9de9bd3993..d9620a1c6ca96 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -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) diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index 61c832ed4cb18..649ce16d48df3 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -435,22 +435,17 @@ init->d_parent->d_name.name, init->d_name.name); 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) diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 2124941424329..1f7c788f58cb5 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -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 */ diff --git a/fs/vfat/vfatfs_syms.c b/fs/vfat/vfatfs_syms.c index d57d153edf297..6f1a121e00321 100644 --- a/fs/vfat/vfatfs_syms.c +++ b/fs/vfat/vfatfs_syms.c @@ -8,6 +8,7 @@ #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) #include #include +#include #include #include @@ -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) diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 6ec03679f4257..239257b217767 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -222,6 +222,7 @@ #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 */ diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h index ab3b8c0784c7a..60af0d40cc5da 100644 --- a/include/linux/affs_fs.h +++ b/include/linux/affs_fs.h @@ -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 */ diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h index 9525293cbd890..afe274a4ce14e 100644 --- a/include/linux/bfs_fs.h +++ b/include/linux/bfs_fs.h @@ -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; diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h index cc23e2e0c629e..ae049ed2f1478 100644 --- a/include/linux/efs_fs.h +++ b/include/linux/efs_fs.h @@ -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__ */ - diff --git a/include/linux/hfs_fs.h b/include/linux/hfs_fs.h index 3c39139433849..65392fc39d8aa 100644 --- a/include/linux/hfs_fs.h +++ b/include/linux/hfs_fs.h @@ -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); diff --git a/include/linux/hpfs_fs.h b/include/linux/hpfs_fs.h index 2b7926aba4dce..a5028dd94d310 100644 --- a/include/linux/hpfs_fs.h +++ b/include/linux/hpfs_fs.h @@ -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 diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 47fab891482b7..63543da77790d 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -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; diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h index 6f63a54c41719..1eca767b46f6a 100644 --- a/include/linux/minix_fs.h +++ b/include/linux/minix_fs.h @@ -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 *); diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index ce7837f1dd451..adcfb751dda52 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -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 */ diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index b028f984c3487..87dfef8cbfedd 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h @@ -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; diff --git a/include/linux/ntfs_fs.h b/include/linux/ntfs_fs.h index acbfc29393132..7b30dd7b01745 100644 --- a/include/linux/ntfs_fs.h +++ b/include/linux/ntfs_fs.h @@ -1,7 +1,3 @@ #ifndef _LINUX_NTFS_FS_H #define _LINUX_NTFS_FS_H - -int init_ntfs_fs(void); - #endif - diff --git a/include/linux/personality.h b/include/linux/personality.h index 31a42d62c3cb4..7607cf6ff47e8 100644 --- a/include/linux/personality.h +++ b/include/linux/personality.h @@ -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 */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index f5927109adbdb..f92195a3e5661 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -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 *); diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h index 4e68ee5a6b931..ad5ca5543e08e 100644 --- a/include/linux/qnx4_fs.h +++ b/include/linux/qnx4_fs.h @@ -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; diff --git a/include/linux/romfs_fs.h b/include/linux/romfs_fs.h index 844e22f994c6e..8f452cbd4c085 100644 --- a/include/linux/romfs_fs.h +++ b/include/linux/romfs_fs.h @@ -56,7 +56,6 @@ struct romfs_inode { #ifdef __KERNEL__ /* Not much now */ -extern int init_romfs_fs(void); #endif /* __KERNEL__ */ #endif diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h index d11573ca59fb2..5df1ef295b248 100644 --- a/include/linux/smb_fs.h +++ b/include/linux/smb_fs.h @@ -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 *); diff --git a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h index 9e177c3d4b5b7..d9c2557e562ec 100644 --- a/include/linux/sysv_fs.h +++ b/include/linux/sysv_fs.h @@ -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 *); diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h index 47980eaaf7ef0..4f842ac308881 100644 --- a/include/linux/udf_fs.h +++ b/include/linux/udf_fs.h @@ -60,7 +60,6 @@ /* * Function prototypes (all other prototypes included in udfdecl.h) */ -extern int init_udf_fs(void); #endif /* __KERNEL__ */ diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index d7c14cd74d957..631791186172d 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -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 */ diff --git a/include/linux/umsdos_fs.h b/include/linux/umsdos_fs.h index 6f113d28c5a52..8dcb93719cd71 100644 --- a/include/linux/umsdos_fs.h +++ b/include/linux/umsdos_fs.h @@ -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 diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c index 1ee1eee4d9d33..111a3d69c1d99 100644 --- a/kernel/exec_domain.c +++ b/kernel/exec_domain.c @@ -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; } diff --git a/kernel/exit.c b/kernel/exit.c index fcc83f997624b..7c834b8934f6b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -425,8 +425,7 @@ NORET_TYPE void do_exit(long code) 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(); diff --git a/kernel/fork.c b/kernel/fork.c index f30adb90878c2..da4de2c9bbf69 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -748,8 +748,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) 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: diff --git a/mm/filemap.c b/mm/filemap.c index b5febc2e5edc4..4fa56405bc990 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1727,6 +1727,160 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) 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(¤t->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(¤t->mm->mmap_sem); + return error; +} + struct page *read_cache_page(struct address_space *mapping, unsigned long index, int (*filler)(void *,struct page*),