diff -u --recursive --new-file v2.0.30/linux/CREDITS linux/CREDITS --- v2.0.30/linux/CREDITS Tue Apr 8 09:04:28 1997 +++ linux/CREDITS Sun Aug 3 15:38:39 1997 @@ -1125,9 +1125,9 @@ S: Germany N: William E. Roadcap -E: roadcapw@cfw.com +E: roadcapw@titus.org W: http://www.cfw.com/~roadcapw -D: Author of menu based configuration tool, Menuconfig. +D: Author of ncurses based configuration tool, Menuconfig. S: 1407 Broad Street S: Waynesboro, Virginia 22980 S: USA diff -u --recursive --new-file v2.0.30/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.0.30/linux/Documentation/Configure.help Tue Apr 8 08:47:45 1997 +++ linux/Documentation/Configure.help Sun Aug 3 15:17:45 1997 @@ -2417,19 +2417,18 @@ AT&T WaveLAN & DEC RoamAbout DS support CONFIG_WAVELAN - These are cards for wireless ethernet-like networking. Supported are - AT&T GIS and NCR WaveLAN cards. If you want to use a card of this - type under Linux, say Y and read the Ethernet-HOWTO, available via - ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Some - more specific information is contained in - drivers/net/README.wavelan. This driver is also available as a - module ( = code which can be inserted in and removed from the - running kernel whenever you want). If you want to compile it as a - module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS) + is a Radio LAN (wireless ethernet-like) at 900 MHz and 2.4 GHz. + This driver support the ISA version of the Wavelan. A driver for + the pcmcia hardware is available in David Hinds's pcmcia package. + This driver is fairly stable and may be compiled as a module + (wavelan.o). It implements many nice feature and the Wireless + Extensions (you must get the Wireless tools from the net). + For documentation, refer to : + o the wavelan man page, wireless tools man pages + o wavelan.p.h and the source code + o Ethernet-HOWTO, Multiple-Ethernet-mini-HOWTO, Module-HOWTO + o More documentation to come when I will have the time :-) HP PCLAN+ (27247B and 27252A) support CONFIG_HPLAN_PLUS diff -u --recursive --new-file v2.0.30/linux/Documentation/locks.txt linux/Documentation/locks.txt --- v2.0.30/linux/Documentation/locks.txt Wed May 15 01:22:04 1996 +++ linux/Documentation/locks.txt Sun Aug 3 13:59:07 1997 @@ -2,37 +2,30 @@ Andy Walker - 15 May 1996 + 12 May 1997 -What's New? ------------ +1. What's New? +-------------- -Flock Emulation Warnings ------------------------- -Many people will have noticed the ugly messages that the file locking -code started generating with the release of kernel version 1.3.95. The -messages look something like this: +1.1 Broken Flock Emulation +-------------------------- - fcntl_setlk() called by process XX with broken flock() emulation +The old flock(2) emulation in the kernel was swapped for proper BSD +compatible flock(2) support in the 1.3.x series of kernels. With the +release of the 2.1.x kernel series, support for the old emulation has +been totally removed, so that we don't need to carry this baggage +forever. -This is a warning for people using older C libraries that those libraries -are still calling the pre 1.3.x flock() emulation routines, instead of -the real flock() system call. The old routines are quite badly broken, -especially with respect to parent-child lock sharing, and can give bad -results if, for example, sendmail attempts to use them. +This should not cause problems for anybody, since everybody using a +2.1.x kernel should have updated their C library to a suitable version +anyway (see the file "linux/Documentation/Changes".) -Fixed versions of the C libraries have been on public release for many -months. The latest versions are 5.2.18 or 5.3.12 for ELF, and I believe -somebody made a 4.7.6 release for people using a.out systems. +1.2 Allow Mixed Locks Again +--------------------------- -In 1.3.96 Linus decided to be lenient on the stragglers and changed the -warning message so that the kernel will only complain five times and -then shut up. That should make life more bearable even for people who, -for some reason, don't want to upgrade. - -Sendmail Problems ------------------ +1.2.1 Typical Problems - Sendmail +--------------------------------- Because sendmail was unable to use the old flock() emulation, many sendmail installations use fcntl() instead of flock(). This is true of Slackware 3.0 for example. This gave rise to some other subtle problems if sendmail was @@ -42,23 +35,50 @@ over time, or under a very heavy mail load, would eventually cause the kernel to lock solid with deadlocked processes. -Disallow Mixed Locks --------------------- -I have chosen the rather cruel solution of disallowing mixed locking styles -on a given file at a given time. Attempts to lock a file with flock() when -fcntl() locks exist, or vice versa, return with an error status of EBUSY. -This seemed to be the only way to avoid all possible deadlock conditions, -as flock() locks do not strictly have one owner process and so can't be -checked for deadlocking in the usual manner. - -The process that created a lock with flock() might have forked multiple -children and exited. Previously the parent process would have been marked -as the owner of the lock, but deadlocks could just have easily occurred in -one or more of the children, which we would not have been able to identify -and avoid. - -Some programs may break (again, groan). In particular the aforementioned -sendmail may have problems running in 'newaliases' mode. It will no longer -deadlock though. Recompile sendmail to use flock() and your troubles will -be over. +1.2.2 The Solution +------------------ +The solution I have chosen, after much experimentation and discussion, +is to make flock() and fcntl() locks oblivious to each other. Both can +exists, and neither will have any effect on the other. + +I wanted the two lock styles to be cooperative, but there were so many +race and deadlock conditions that the current solution was the only +practical one. It puts us in the same position as, for example, SunOS +4.1.x and serveral other commercial Unices. The only OS's that support +cooperative flock()/fcntl() are those that emulate flock() using +fcntl(), with all the problems that implies. + + +1.3 Mandatory Locking As A Mount Option +--------------------------------------- + +Mandatory locking, as described in 'Documentation/mandatory.txt' was prior +to this release a general configuration option that was valid for all +mounted filesystems. This had a number of inherent dangers, not the least +of which was the ability to freeze an NFS server by asking it to read a +file for which a mandatory lock existed. + +From this release of the kernel, mandatory locking can be turned on and off +on a per-filesystem basis, using the mount options 'mand' and 'nomand'. +The default is to disallow mandatory locking. The intention is that +mandatory locking only be enabled on a local filesystem as the specific need +arises. + +Until an updated version of mount(8) becomes available you may have to apply +this patch to the mount sources (based on the version distributed with Rick +Faiths util-linux-2.5 package): + +*** mount.c.orig Sat Jun 8 09:14:31 1996 +--- mount.c Sat Jun 8 09:13:02 1996 +*************** +*** 100,105 **** +--- 100,107 ---- + { "noauto", 0, MS_NOAUTO }, /* Can only be mounted explicitly */ + { "user", 0, MS_USER }, /* Allow ordinary user to mount */ + { "nouser", 1, MS_USER }, /* Forbid ordinary user to mount */ ++ { "mand", 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */ ++ { "nomand", 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */ + /* add new options here */ + #ifdef MS_NOSUB + { "sub", 1, MS_NOSUB }, /* allow submounts */ diff -u --recursive --new-file v2.0.30/linux/Documentation/mandatory.txt linux/Documentation/mandatory.txt --- v2.0.30/linux/Documentation/mandatory.txt Tue Apr 16 00:27:10 1996 +++ linux/Documentation/mandatory.txt Sun Aug 3 13:59:07 1997 @@ -5,8 +5,8 @@ 15 April 1996 -What is mandatory locking? ---------------------------- +1. What is mandatory locking? +------------------------------ Mandatory locking is kernel enforced file locking, as opposed to the more usual cooperative file locking used to guarantee sequential access to files among @@ -44,8 +44,8 @@ borrowing the fcntl() locking scheme from System V. The mandatory locking scheme is defined by the System V Interface Definition (SVID) Version 3. -Marking a file for mandatory locking ------------------------------------- +2. Marking a file for mandatory locking +--------------------------------------- A file is marked as a candidate for mandatory by setting the group-id bit in its file mode but removing the group-execute bit. This is an otherwise @@ -58,8 +58,8 @@ refrain from clearing this bit. Similarly the kernel has been modified not to run mandatory lock candidates with setgid privileges. -Available implementations -------------------------- +3. Available implementations +---------------------------- I have considered the implementations of mandatory locking available with SunOS 4.1.x, Solaris 2.x and HP-UX 9.x. @@ -93,8 +93,8 @@ below are just as valid as any others, so long as the main points seem to agree. -Semantics ---------- +4. Semantics +------------ 1. Mandatory locks can only be applied via the fcntl()/lockf() locking interface - in other words the System V/POSIX interface. BSD style @@ -124,8 +124,8 @@ that has any mandatory locks in effect will be rejected with the error status EAGAIN. -Which system calls are affected? --------------------------------- +5. Which system calls are affected? +----------------------------------- Those which modify a file's contents, not just the inode. That gives read(), write(), readv(), writev(), open(), creat(), mmap(), truncate() and @@ -142,8 +142,8 @@ checking in my eagerness to get this code out the door. Please let me know, or better still fix the system calls yourself and submit a patch to me or Linus. -Warning! --------- +6. Warning! +----------- Not even root can override a mandatory lock, so runaway process can wreak havoc if they lock crucial files. The way around it is to change the file diff -u --recursive --new-file v2.0.30/linux/MAINTAINERS linux/MAINTAINERS --- v2.0.30/linux/MAINTAINERS Tue Apr 8 08:47:45 1997 +++ linux/MAINTAINERS Sun Aug 3 15:38:39 1997 @@ -164,6 +164,12 @@ L: linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu S: Maintained +FILE LOCKING (flock() and fcntl()/lockf()) +P: Andy Walker +M: andy@lysaker.kvaerner.no +L: linux-kernel@vger.rutgers.edu +S: Maintained + FRAME RELAY DLCI/FRAD (Sangoma drivers too) P: Mike McLagan M: mike.mclagan@linux.org @@ -318,7 +324,7 @@ MENUCONFIG: P: William Roadcap -M: roadcapw@cfw.com +M: roadcapw@titus.org L: linux-kernel@vger.rutgers.edu S: Maintained diff -u --recursive --new-file v2.0.30/linux/Makefile linux/Makefile --- v2.0.30/linux/Makefile Mon Mar 17 14:58:22 1997 +++ linux/Makefile Sun Aug 3 15:40:59 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 0 -SUBLEVEL = 30 +SUBLEVEL = 31 ARCH = i386 diff -u --recursive --new-file v2.0.30/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.0.30/linux/arch/alpha/defconfig Tue Oct 29 17:42:40 1996 +++ linux/arch/alpha/defconfig Sun Aug 3 13:59:07 1997 @@ -179,7 +179,6 @@ # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_LOCK_MANDATORY is not set # CONFIG_MINIX_FS is not set # CONFIG_EXT_FS is not set CONFIG_EXT2_FS=y diff -u --recursive --new-file v2.0.30/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.0.30/linux/arch/alpha/kernel/osf_sys.c Tue Aug 20 23:18:07 1996 +++ linux/arch/alpha/kernel/osf_sys.c Sun Aug 3 10:58:38 1997 @@ -714,29 +714,25 @@ osf_getsysinfo (unsigned long op, void * buffer, unsigned long nbytes, int * start, void *arg) { - extern unsigned long rdfpcr (void); - unsigned long fpcw; - - switch (op) { - case 45: /* GSI_IEEE_FP_CONTROL */ - /* build and return current fp control word: */ - fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK; - fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK; - put_user(fpcw, (unsigned long *) buffer); - return 0; - - case 46: /* GSI_IEEE_STATE_AT_SIGNAL */ - /* - * Not sure anybody will ever use this weird stuff. These - * ops can be used (under OSF/1) to set the fpcr that should - * be used when a signal handler starts executing. - */ - break; - - default: - break; - } - return -EOPNOTSUPP; + switch (op) { + case 45: /* GSI_IEEE_FP_CONTROL */ + /* Return current sw control & status bits. */ + put_user(current->tss.flags & IEEE_SW_MASK, + (unsigned long *)buffer); + return 0; + + case 46: /* GSI_IEEE_STATE_AT_SIGNAL */ + /* + * Not sure anybody will ever use this weird stuff. These + * ops can be used (under OSF/1) to set the fpcr that should + * be used when a signal handler starts executing. + */ + break; + + default: + break; + } + return -EOPNOTSUPP; } @@ -744,25 +740,43 @@ osf_setsysinfo (unsigned long op, void * buffer, unsigned long nbytes, int * start, void *arg) { - unsigned long fpcw; - - switch (op) { - case 14: /* SSI_IEEE_FP_CONTROL */ - /* update trap enable bits: */ - fpcw = get_user((unsigned long *) buffer); - current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK; - current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK); - return 0; - - case 15: /* SSI_IEEE_STATE_AT_SIGNAL */ - case 16: /* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */ - /* - * Not sure anybody will ever use this weird stuff. These - * ops can be used (under OSF/1) to set the fpcr that should - * be used when a signal handler starts executing. - */ - default: - break; - } - return -EOPNOTSUPP; + switch (op) { + case 14: { /* SSI_IEEE_FP_CONTROL */ + unsigned long sw, fpcw; + + /* + * Alpha Architecture Handbook 4.7.7.3: + * To be fully IEEE compiant, we must track the current IEEE + * exception state in software, because spurrious bits can be + * set in the trap shadow of a software-complete insn. + */ + + /* Update software trap enable bits. */ + sw = get_user((unsigned long *) buffer) & IEEE_SW_MASK; + current->tss.flags &= ~IEEE_SW_MASK; + current->tss.flags |= sw & IEEE_SW_MASK; + + /* Update the real fpcr. For exceptions that are disabled, + but that we have seen, turn off exceptions in h/w. + Otherwise leave them enabled so that we can update our + software status mask. */ + fpcw = rdfpcr() & (~FPCR_MASK | FPCR_DYN_MASK); + fpcw |= ieee_sw_to_fpcr(sw | ((~sw & IEEE_STATUS_MASK) >> 16)); + wrfpcr(fpcw); + return 0; + } + + case 15: /* SSI_IEEE_STATE_AT_SIGNAL */ + case 16: /* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */ + /* + * Not sure anybody will ever use this weird stuff. These + * ops can be used (under OSF/1) to set the fpcr that should + * be used when a signal handler starts executing. + */ + break; + + default: + break; + } + return -EOPNOTSUPP; } diff -u --recursive --new-file v2.0.30/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c --- v2.0.30/linux/arch/alpha/math-emu/fp-emul.c Thu Apr 11 23:49:30 1996 +++ linux/arch/alpha/math-emu/fp-emul.c Sun Aug 3 10:58:38 1997 @@ -298,19 +298,29 @@ * * - Set the appropriate bits in the FPCR * - If the specified exception is enabled in the FPCR, - * return. The caller (mxr_signal_handler) will dispatch + * return. The caller (entArith) will dispatch * the appropriate signal to the translated program. + * + * In addition, properly track the exception state in software + * as described in Alpha Architecture Handbook 4.7.7.3. */ if (res) { - fpcr |= FPCR_SUM | res; - wrfpcr(fpcr); - if (((res & FPCR_INV) && (fpcw & IEEE_TRAP_ENABLE_INV)) || - ((res & FPCR_DZE) && (fpcw & IEEE_TRAP_ENABLE_DZE)) || - ((res & FPCR_OVF) && (fpcw & IEEE_TRAP_ENABLE_OVF)) || - ((res & FPCR_UNF) && (fpcw & IEEE_TRAP_ENABLE_UNF)) || - ((res & FPCR_INE) && (fpcw & IEEE_TRAP_ENABLE_INE))) + /* record exceptions in software control word. */ + fpcw |= res >> 35; + current->tss.flags = fpcw; + + /* update hardware control register, disabling hardware + exceptions for disabled software exceptions for which + we have a status. (no, really.) */ + fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); + fpcr |= ieee_sw_to_fpcr(fpcw | (~fpcw & IEEE_STATUS_MASK)>>16); + wrfpcr(fpcr); + + /* Do we generate a signal? */ + if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) return 0; } + /* * Whoo-kay... we got this far, and we're not generating a signal * to the translated program. All that remains is to write the diff -u --recursive --new-file v2.0.30/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.0.30/linux/arch/i386/defconfig Tue Oct 29 17:42:40 1996 +++ linux/arch/i386/defconfig Sun Aug 3 13:59:07 1997 @@ -129,7 +129,6 @@ # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_LOCK_MANDATORY is not set CONFIG_MINIX_FS=y # CONFIG_EXT_FS is not set CONFIG_EXT2_FS=y diff -u --recursive --new-file v2.0.30/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.0.30/linux/arch/i386/kernel/bios32.c Tue Apr 8 08:47:45 1997 +++ linux/arch/i386/kernel/bios32.c Sun Aug 3 14:08:04 1997 @@ -736,7 +736,7 @@ outb (0x00, 0xCFB); outb (0x00, 0xCF8); outb (0x00, 0xCFA); - if (inb (0xCF8) == 0x00 && inb (0xCFC) == 0x00) { + if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) { restore_flags(flags); printk("pcibios_init: Using configuration type 2\n"); return &pci_direct_conf2; diff -u --recursive --new-file v2.0.30/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.0.30/linux/drivers/isdn/isdn_common.c Tue Nov 12 22:36:19 1996 +++ linux/drivers/isdn/isdn_common.c Sun Aug 3 15:22:52 1997 @@ -1694,6 +1694,7 @@ q->next = p->next; else dev->infochain = (infostruct *) (p->next); + kfree(p); return; } q = p; diff -u --recursive --new-file v2.0.30/linux/drivers/net/new_tunnel.c linux/drivers/net/new_tunnel.c --- v2.0.30/linux/drivers/net/new_tunnel.c Tue Apr 8 08:47:46 1997 +++ linux/drivers/net/new_tunnel.c Sun Aug 3 14:02:34 1997 @@ -267,6 +267,7 @@ /* Tack on our header */ new_skb->h.iph = (struct iphdr *) skb_push(new_skb, tunnel_hlen); + new_skb->mac.raw = new_skb->ip_hdr; /* Free the old packet, we no longer need it */ dev_kfree_skb(skb, FREE_WRITE); diff -u --recursive --new-file v2.0.30/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v2.0.30/linux/drivers/net/wavelan.c Thu Mar 6 10:03:51 1997 +++ linux/drivers/net/wavelan.c Sun Aug 3 15:17:45 1997 @@ -112,7 +112,7 @@ * Read from card's Host Adaptor Status Register. */ static inline u_short -hasr_read(u_short ioaddr) +hasr_read(u_long ioaddr) { return(inw(HASR(ioaddr))); } /* hasr_read */ @@ -122,7 +122,7 @@ * Write to card's Host Adapter Command Register. */ static inline void -hacr_write(u_short ioaddr, +hacr_write(u_long ioaddr, u_short hacr) { outw(hacr, HACR(ioaddr)); @@ -134,7 +134,7 @@ * those times when it is needed. */ static inline void -hacr_write_slow(u_short ioaddr, +hacr_write_slow(u_long ioaddr, u_short hacr) { hacr_write(ioaddr, hacr); @@ -147,7 +147,7 @@ * Set the channel attention bit. */ static inline void -set_chan_attn(u_short ioaddr, +set_chan_attn(u_long ioaddr, u_short hacr) { hacr_write(ioaddr, hacr | HACR_CA); @@ -158,7 +158,7 @@ * Reset, and then set host adaptor into default mode. */ static inline void -wv_hacr_reset(u_short ioaddr) +wv_hacr_reset(u_long ioaddr) { hacr_write_slow(ioaddr, HACR_RESET); hacr_write(ioaddr, HACR_DEFAULT); @@ -169,7 +169,7 @@ * Set the i/o transfer over the ISA bus to 8 bits mode */ static inline void -wv_16_off(u_short ioaddr, +wv_16_off(u_long ioaddr, u_short hacr) { hacr &= ~HACR_16BITS; @@ -181,7 +181,7 @@ * Set the i/o transfer over the ISA bus to 8 bits mode */ static inline void -wv_16_on(u_short ioaddr, +wv_16_on(u_long ioaddr, u_short hacr) { hacr |= HACR_16BITS; @@ -196,7 +196,7 @@ wv_ints_off(device * dev) { net_local * lp = (net_local *)dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_long x; x = wv_splhi(); @@ -215,7 +215,7 @@ wv_ints_on(device * dev) { net_local * lp = (net_local *)dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_long x; x = wv_splhi(); @@ -239,7 +239,7 @@ * Read bytes from the PSA. */ static void -psa_read(u_short ioaddr, +psa_read(u_long ioaddr, u_short hacr, int o, /* offset in PSA */ u_char * b, /* buffer to fill */ @@ -262,7 +262,7 @@ * Write the Paramter Storage Area to the WaveLAN card's memory */ static void -psa_write(u_short ioaddr, +psa_write(u_long ioaddr, u_short hacr, int o, /* Offset in psa */ u_char * b, /* Buffer in memory */ @@ -329,7 +329,7 @@ * Write 1 byte to the MMC. */ static inline void -mmc_out(u_short ioaddr, +mmc_out(u_long ioaddr, u_short o, u_char d) { @@ -347,7 +347,7 @@ * We start by the end because it is the way it should be ! */ static inline void -mmc_write(u_short ioaddr, +mmc_write(u_long ioaddr, u_char o, u_char * b, int n) @@ -365,7 +365,7 @@ * Optimised version for 1 byte, avoid using memory... */ static inline u_char -mmc_in(u_short ioaddr, +mmc_in(u_long ioaddr, u_short o) { while(inw(HASR(ioaddr)) & HASR_MMC_BUSY) @@ -386,7 +386,7 @@ * We start by the end because it is the way it should be ! */ static inline void -mmc_read(u_short ioaddr, +mmc_read(u_long ioaddr, u_char o, u_char * b, int n) @@ -400,11 +400,27 @@ /*------------------------------------------------------------------*/ /* + * Get the type of encryption available... + */ +static inline int +mmc_encr(u_long ioaddr) /* i/o port of the card */ +{ + int temp; + + temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail)); + if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES)) + return 0; + else + return temp; +} + +/*------------------------------------------------------------------*/ +/* * Wait for the frequency EEprom to complete a command... * I hope this one will be optimally inlined... */ static inline void -fee_wait(u_short ioaddr, /* i/o port of the card */ +fee_wait(u_long ioaddr, /* i/o port of the card */ int delay, /* Base delay to wait for */ int number) /* Number of time to wait */ { @@ -420,7 +436,7 @@ * Read bytes from the Frequency EEprom (frequency select cards). */ static void -fee_read(u_short ioaddr, /* i/o port of the card */ +fee_read(u_long ioaddr, /* i/o port of the card */ u_short o, /* destination offset */ u_short * b, /* data buffer */ int n) /* number of registers */ @@ -445,6 +461,8 @@ } } +#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ + /*------------------------------------------------------------------*/ /* * Write bytes from the Frequency EEprom (frequency select cards). @@ -453,7 +471,7 @@ * Jean II */ static void -fee_write(u_short ioaddr, /* i/o port of the card */ +fee_write(u_long ioaddr, /* i/o port of the card */ u_short o, /* destination offset */ u_short * b, /* data buffer */ int n) /* number of registers */ @@ -528,6 +546,7 @@ fee_wait(ioaddr, 10, 100); #endif /* EEPROM_IS_PROTECTED */ } +#endif /* WIRELESS_EXT */ /************************ I82586 SUBROUTINES *************************/ /* @@ -540,7 +559,7 @@ * Why inlining this function make it fail ??? */ static /*inline*/ void -obram_read(u_short ioaddr, +obram_read(u_long ioaddr, u_short o, u_char * b, int n) @@ -554,7 +573,7 @@ * Write bytes to the on-board RAM. */ static inline void -obram_write(u_short ioaddr, +obram_write(u_long ioaddr, u_short o, u_char * b, int n) @@ -571,7 +590,7 @@ wv_ack(device * dev) { net_local * lp = (net_local *)dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_short scb_cs; int i; @@ -614,7 +633,7 @@ const char * str) { net_local * lp = (net_local *)dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_short scb_cmd; ach_t cb; int i; @@ -660,7 +679,7 @@ */ static inline int wv_config_complete(device * dev, - u_short ioaddr, + u_long ioaddr, net_local * lp) { unsigned short mcs_addr; @@ -722,7 +741,7 @@ */ static int wv_complete(device * dev, - u_short ioaddr, + u_long ioaddr, net_local * lp) { int nreaped = 0; @@ -992,7 +1011,7 @@ static void wv_mmc_show(device * dev) { - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; net_local * lp = (net_local *)dev->priv; mmr_t m; @@ -1077,7 +1096,7 @@ * Print the last block of the i82586 memory */ static void -wv_scb_show(unsigned short ioaddr) +wv_scb_show(u_long ioaddr) { scb_t scb; @@ -1162,7 +1181,7 @@ int i, u_short p) { - unsigned short ioaddr; + u_long ioaddr; ac_tx_t actx; ioaddr = dev->base_addr; @@ -1529,7 +1548,7 @@ * (called in wavelan_ioctl) */ static inline int -wv_set_frequency(u_short ioaddr, /* i/o port of the card */ +wv_set_frequency(u_long ioaddr, /* i/o port of the card */ iw_freq * frequency) { const int BAND_NUM = 10; /* Number of bands */ @@ -1550,7 +1569,7 @@ } /* Setting by channel (same as wfreqsel) */ - /* Warning : each channel is 11MHz wide, so some of the channels + /* Warning : each channel is 22MHz wide, so some of the channels * will interfere... */ if((frequency->e == 0) && (frequency->m >= 0) && (frequency->m < BAND_NUM)) @@ -1729,7 +1748,7 @@ * Give the list of available frequencies */ static inline int -wv_frequency_list(u_short ioaddr, /* i/o port of the card */ +wv_frequency_list(u_long ioaddr, /* i/o port of the card */ iw_freq * list, /* List of frequency to fill */ int max) /* Maximum number of frequencies */ { @@ -1826,7 +1845,7 @@ struct ifreq * rq, /* Data passed */ int cmd) /* Ioctl number */ { - unsigned short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; net_local * lp = (net_local *)dev->priv; /* lp is not unused */ struct iwreq * wrq = (struct iwreq *) rq; psa_t psa; @@ -1866,9 +1885,7 @@ m.w.mmw_netw_id_h = (wrq->u.nwid.nwid & 0xFF00) >> 8; mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2); - m.w.mmw_loopt_sel = 0x00; - mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m, - (unsigned char *)&m.w.mmw_loopt_sel, 1); + mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00); } else { @@ -1878,10 +1895,8 @@ (char *)&psa.psa_nwid_select - (char *)&psa, (unsigned char *)&psa.psa_nwid_select, 1); - /* Disable nwid in the mmc (no check) */ - m.w.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID; - mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m, - (unsigned char *)&m.w.mmw_loopt_sel, 1); + /* Disable nwid in the mmc (no filtering) */ + mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID); } break; @@ -1950,6 +1965,82 @@ wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F; break; + case SIOCSIWENCODE: + /* Set encryption key */ + if(!mmc_encr(ioaddr)) + { + ret = -EOPNOTSUPP; + break; + } + + if(wrq->u.encoding.method) + { /* enable encryption */ + int i; + long long key = wrq->u.encoding.code; + + for(i = 7; i >= 0; i--) + { + psa.psa_encryption_key[i] = key & 0xFF; + key >>= 8; + } + psa.psa_encryption_select = 1; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_encryption_select - (char *) &psa, + (unsigned char *) &psa.psa_encryption_select, 8+1); + + mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), + MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE); + mmc_write(ioaddr, mmwoff(0, mmw_encr_key), + (unsigned char *) &psa.psa_encryption_key, 8); + } + else + { /* disable encryption */ + psa.psa_encryption_select = 0; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_encryption_select - (char *) &psa, + (unsigned char *) &psa.psa_encryption_select, 1); + + mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0); + } + break; + + case SIOCGIWENCODE: + /* Read the encryption key */ + if(!mmc_encr(ioaddr)) + { + ret = -EOPNOTSUPP; + break; + } + + /* only super-user can see encryption key */ + if(!suser()) + { + ret = -EPERM; + break; + } + else + { + int i; + long long key = 0; + + psa_read(ioaddr, lp->hacr, + (char *) &psa.psa_encryption_select - (char *) &psa, + (unsigned char *) &psa.psa_encryption_select, 1+8); + for(i = 0; i < 8; i++) + { + key <<= 8; + key += psa.psa_encryption_key[i]; + } + wrq->u.encoding.code = key; + + /* encryption is enabled */ + if(psa.psa_encryption_select) + wrq->u.encoding.method = mmc_encr(ioaddr); + else + wrq->u.encoding.method = 0; + } + break; + case SIOCGIWRANGE: /* Basic checking... */ if(wrq->u.data.pointer != (caddr_t) 0) @@ -2207,7 +2298,7 @@ static iw_stats * wavelan_get_wireless_stats(device * dev) { - unsigned short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; net_local * lp = (net_local *) dev->priv; mmr_t m; iw_stats * wstats; @@ -2281,7 +2372,7 @@ int sksize) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; struct sk_buff * skb; #ifdef DEBUG_RX_TRACE @@ -2369,7 +2460,7 @@ static inline void wv_receive(device * dev) { - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; net_local * lp = (net_local *)dev->priv; int nreaped = 0; @@ -2555,7 +2646,7 @@ short length) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; unsigned short txblock; unsigned short txpred; unsigned short tx_addr; @@ -2760,7 +2851,7 @@ static inline int wv_mmc_init(device * dev) { - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; net_local * lp = (net_local *)dev->priv; psa_t psa; mmw_t m; @@ -2789,6 +2880,9 @@ /* As NWID is not set : no NWID checking */ psa.psa_nwid_select = 0; + /* Disable encryption */ + psa.psa_encryption_select = 0; + /* Set to standard values * 0x04 for AT, * 0x01 for MCA, @@ -2806,7 +2900,7 @@ #ifdef USE_PSA_CONFIG /* Write the psa */ psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, - (unsigned char *)psa.psa_nwid, 3); + (unsigned char *)psa.psa_nwid, 4); psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, (unsigned char *)&psa.psa_thr_pre_set, 1); psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, @@ -2828,6 +2922,14 @@ else m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID; + memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, + sizeof(m.mmw_encr_key)); + + if(psa.psa_encryption_select) + m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE; + else + m.mmw_encr_enable = 0; + m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F; m.mmw_quality_thr = psa.psa_quality_thr & 0x0F; @@ -2919,7 +3021,7 @@ wv_ru_start(device * dev) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_short scb_cs; fd_t fd; rbd_t rbd; @@ -3013,7 +3115,7 @@ wv_cu_start(device * dev) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; int i; u_short txblock; u_short first_nop; @@ -3114,7 +3216,7 @@ wv_82586_start(device * dev) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; scp_t scp; /* system configuration pointer */ iscp_t iscp; /* intermediate scp */ scb_t scb; /* system control block */ @@ -3244,7 +3346,7 @@ wv_82586_config(device * dev) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; unsigned short txblock; unsigned short txpred; unsigned short tx_addr; @@ -3440,7 +3542,7 @@ wv_82586_stop(device * dev) { net_local * lp = (net_local *) dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_short scb_cmd; #ifdef DEBUG_CONFIG_TRACE @@ -3475,7 +3577,7 @@ wv_hw_reset(device * dev) { net_local * lp = (net_local *)dev->priv; - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name, @@ -3520,7 +3622,7 @@ * (called in wavelan_probe() and init_module()) */ static int -wv_check_ioaddr(u_short ioaddr, +wv_check_ioaddr(u_long ioaddr, u_char * mac) { int i; /* Loop counter */ @@ -3567,7 +3669,7 @@ struct pt_regs * regs) { device * dev; - u_short ioaddr; + u_long ioaddr; net_local * lp; u_short hasr; u_short status; @@ -3714,7 +3816,7 @@ { device * dev; net_local * lp; - unsigned short ioaddr; + u_long ioaddr; unsigned long x; unsigned int nreaped; @@ -3909,7 +4011,7 @@ static int wavelan_config(device * dev) { - u_short ioaddr = dev->base_addr; + u_long ioaddr = dev->base_addr; u_char irq_mask; int irq; net_local * lp; diff -u --recursive --new-file v2.0.30/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h --- v2.0.30/linux/drivers/net/wavelan.p.h Thu Mar 6 10:03:51 1997 +++ linux/drivers/net/wavelan.p.h Sun Aug 3 15:17:45 1997 @@ -35,6 +35,12 @@ /* ------------------------ SPECIFIC NOTES ------------------------ */ /* + * wavelan.o is darn too big + * ------------------------- + * That's true ! There is a very simple way to reduce the driver + * object by 33% (yes !). Comment out the following line : + * #include + * * MAC address and hardware detection : * ---------------------------------- * The detection code of the wavelan chech that the first 3 @@ -80,14 +86,12 @@ * caracteristics of the hardware in a standard way and support for * applications for taking advantage of it (like Mobile IP). * - * By default, these wireless extensions are disabled, because they - * need a patch to the Linux Kernel. This simple patch may be found - * with the driver + some utilities to access those wireless - * extensions (iwconfig...). Hopefully, those wireless extensions will - * make their way in the kernel someday. + * You will need to enable the CONFIG_NET_RADIO define in the kernel + * configuration to enable the wireless extensions (this is the one + * giving access to the radio network device choice). * - * You also will need to enable the CONFIG_NET_RADIO in the kernel - * configuration to enable the wireless extensions. + * It might also be a good idea as well to fetch the wireless tools to + * configure the device and play a bit. */ /* ---------------------------- FILES ---------------------------- */ @@ -161,6 +165,7 @@ * Ajay Bakre (bakre@paul.rutgers.edu), * Donald Becker (becker@cesdis.gsfc.nasa.gov), * Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com), + * Brent Elphick , * Anders Klemets (klemets@it.kth.se), * Vladimir V. Kolpakov (w@stier.koenig.ru), * Marc Meertens (Marc.Meertens@Utrecht.NCR.com), @@ -185,6 +190,7 @@ * John Rosenberg (johnr@cs.usyd.edu.au), * George Rossi (george@phm.gov.au), * Arthur Scott (arthur@cs.usyd.edu.au), + * Stanislav Sinyagin * Peter Storey, * for their assistance and advice. * @@ -260,9 +266,13 @@ * - Remove extern kerword for wavelan_probe() * - Level threshold is now a standard wireless extension (version 4 !) * + * Changes made for release in 2.1.36 : + * ---------------------------------- + * - Encryption setting from Brent Elphick (thanks a lot !) + * - 'ioaddr' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin) + * * Wishes & dreams : * --------------- - * - Encryption stuff * - Roaming */ @@ -345,7 +355,7 @@ /************************ CONSTANTS & MACROS ************************/ #ifdef DEBUG_VERSION_SHOW -static const char *version = "wavelan.c : v15 (wireless extensions) 12/2/97\n"; +static const char *version = "wavelan.c : v16 (wireless extensions) 17/4/97\n"; #endif /* Watchdog temporisation */ @@ -442,69 +452,65 @@ wv_psa_to_irq(u_char); /* ------------------- HOST ADAPTER SUBROUTINES ------------------- */ static inline u_short /* data */ - hasr_read(u_short); /* Read the host interface : base address */ + hasr_read(u_long); /* Read the host interface : base address */ static inline void - hacr_write(u_short, /* Write to host interface : base address */ + hacr_write(u_long, /* Write to host interface : base address */ u_short), /* data */ - hacr_write_slow(u_short, + hacr_write_slow(u_long, u_short), - set_chan_attn(u_short, /* ioaddr */ + set_chan_attn(u_long, /* ioaddr */ u_short), /* hacr */ - wv_hacr_reset(u_short), /* ioaddr */ - wv_16_off(u_short, /* ioaddr */ + wv_hacr_reset(u_long), /* ioaddr */ + wv_16_off(u_long, /* ioaddr */ u_short), /* hacr */ - wv_16_on(u_short, /* ioaddr */ + wv_16_on(u_long, /* ioaddr */ u_short), /* hacr */ wv_ints_off(device *), wv_ints_on(device *); /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ static void - psa_read(u_short, /* Read the Parameter Storage Area */ + psa_read(u_long, /* Read the Parameter Storage Area */ u_short, /* hacr */ int, /* offset in PSA */ u_char *, /* buffer to fill */ int), /* size to read */ - psa_write(u_short, /* Write to the PSA */ + psa_write(u_long, /* Write to the PSA */ u_short, /* hacr */ int, /* Offset in psa */ u_char *, /* Buffer in memory */ int); /* Length of buffer */ static inline void - mmc_out(u_short, /* Write 1 byte to the Modem Manag Control */ + mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */ u_short, u_char), - mmc_write(u_short, /* Write n bytes to the MMC */ + mmc_write(u_long, /* Write n bytes to the MMC */ u_char, u_char *, int); static inline u_char /* Read 1 byte from the MMC */ - mmc_in(u_short, + mmc_in(u_long, u_short); static inline void - mmc_read(u_short, /* Read n bytes from the MMC */ + mmc_read(u_long, /* Read n bytes from the MMC */ u_char, u_char *, int), - fee_wait(u_short, /* Wait for frequency EEprom : base address */ + fee_wait(u_long, /* Wait for frequency EEprom : base address */ int, /* Base delay to wait for */ int); /* Number of time to wait */ static void - fee_read(u_short, /* Read the frequency EEprom : base address */ + fee_read(u_long, /* Read the frequency EEprom : base address */ u_short, /* destination offset */ u_short *, /* data buffer */ - int), /* number of registers */ - fee_write(u_short, /* Write to frequency EEprom : base address */ - u_short, /* destination offset */ - u_short *, /* data buffer */ - int); /* number of registers */ + int); /* number of registers */ /* ---------------------- I82586 SUBROUTINES ----------------------- */ static /*inline*/ void - obram_read(u_short, /* ioaddr */ + obram_read(u_long, /* ioaddr */ u_short, /* o */ u_char *, /* b */ int); /* n */ static inline void - obram_write(u_short, /* ioaddr */ + obram_write(u_long, /* ioaddr */ u_short, /* o */ u_char *, /* b */ int); /* n */ @@ -514,11 +520,11 @@ wv_synchronous_cmd(device *, const char *), wv_config_complete(device *, - u_short, + u_long, net_local *); static int wv_complete(device *, - u_short, + u_long, net_local *); static inline void wv_82586_reconfig(device *); @@ -560,7 +566,7 @@ wv_82586_stop(device *); static int wv_hw_reset(device *), /* Reset the wavelan hardware */ - wv_check_ioaddr(u_short, /* ioaddr */ + wv_check_ioaddr(u_long, /* ioaddr */ u_char *); /* mac address (read) */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ static void diff -u --recursive --new-file v2.0.30/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.0.30/linux/drivers/sound/sb_common.c Wed Sep 11 07:57:14 1996 +++ linux/drivers/sound/sb_common.c Sun Aug 3 15:25:08 1997 @@ -583,6 +583,20 @@ * Detect the device */ + cli(); /* Some ESS1688 cards need this */ + inb (devc->base + 0x9); + inb (devc->base + 0x9); + inb (devc->base + 0x9); + inb (devc->base + 0xb); + inb (devc->base + 0x9); + inb (devc->base + 0xb); + inb (devc->base + 0x9); + inb (devc->base + 0x9); + inb (devc->base + 0xb); + inb (devc->base + 0x9); + inb (devc->base); + sti(); + if (sb_dsp_reset (devc)) dsp_get_vers (devc); else diff -u --recursive --new-file v2.0.30/linux/fs/Config.in linux/fs/Config.in --- v2.0.30/linux/fs/Config.in Sun Dec 1 05:58:05 1996 +++ linux/fs/Config.in Sun Aug 3 13:59:07 1997 @@ -5,7 +5,6 @@ comment 'Filesystems' bool 'Quota support' CONFIG_QUOTA -bool 'Mandatory lock support' CONFIG_LOCK_MANDATORY tristate 'Minix fs support' CONFIG_MINIX_FS tristate 'Extended fs support' CONFIG_EXT_FS tristate 'Second extended fs support' CONFIG_EXT2_FS diff -u --recursive --new-file v2.0.30/linux/fs/dquot.c linux/fs/dquot.c --- v2.0.30/linux/fs/dquot.c Sun May 12 21:36:19 1996 +++ linux/fs/dquot.c Sun Aug 3 15:31:34 1997 @@ -19,6 +19,8 @@ * * Fixes: Dmitry Gorodchanin , 11 Feb 96 * removed race conditions in dqput(), dqget() and iput(). + * Nick Kralevich , 21 Jul 97 + * Fixed a condition where user and group quotas could get mixed up. * * (C) Copyright 1994, 1995 Marco van Wieringen * @@ -549,12 +551,14 @@ repeat: dquot = *(hash(dev, id, type)); while (dquot) { - if (dquot->dq_dev != dev || dquot->dq_id != id) { + if (dquot->dq_dev != dev || dquot->dq_id != id || + dquot->dq_type != type) { dquot = dquot->dq_hash_next; continue; } wait_on_dquot(dquot); - if (dquot->dq_dev != dev || dquot->dq_id != id) + if (dquot->dq_dev != dev || dquot->dq_id != id || + dquot->dq_type != type) goto repeat; if (!dquot->dq_count) nr_free_dquots--; diff -u --recursive --new-file v2.0.30/linux/fs/locks.c linux/fs/locks.c --- v2.0.30/linux/fs/locks.c Fri Sep 20 07:00:35 1996 +++ linux/fs/locks.c Sun Aug 3 13:59:07 1997 @@ -28,22 +28,22 @@ * dynamically with kmalloc()/kfree(). * Andy Walker (andy@lysaker.kvaerner.no), February 21, 1995 * - * Implemented two lock personalities - F_FLOCK and F_POSIX. + * Implemented two lock personalities - FL_FLOCK and FL_POSIX. * - * F_POSIX locks are created with calls to fcntl() and lockf() through the + * FL_POSIX locks are created with calls to fcntl() and lockf() through the * fcntl() system call. They have the semantics described above. * - * F_FLOCK locks are created with calls to flock(), through the flock() + * FL_FLOCK locks are created with calls to flock(), through the flock() * system call, which is new. Old C libraries implement flock() via fcntl() * and will continue to use the old, broken implementation. * - * F_FLOCK locks follow the 4.4 BSD flock() semantics. They are associated + * FL_FLOCK locks follow the 4.4 BSD flock() semantics. They are associated * with a file pointer (filp). As a result they can be shared by a parent * process and its children after a fork(). They are removed when the last * file descriptor referring to the file pointer is closed (unless explicitly * unlocked). * - * F_FLOCK locks never deadlock, an existing lock is always removed before + * FL_FLOCK locks never deadlock, an existing lock is always removed before * upgrading from shared to exclusive (or vice versa). When this happens * any processes blocked by the current lock are woken up and allowed to * run before the new lock is applied. @@ -76,22 +76,32 @@ * flock() and fcntl(). * Andy Walker (andy@lysaker.kvaerner.no), April 29, 1996. * - * Allow only one type of locking scheme (F_POSIX or F_FLOCK) to be in use - * for a given file at a time. Changed the CONFIG_MANDATORY_OPTION scheme to + * Allow only one type of locking scheme (FL_POSIX or FL_FLOCK) to be in use + * for a given file at a time. Changed the CONFIG_LOCK_MANDATORY scheme to * guarantee sensible behaviour in the case where file system modules might * be compiled with different options than the kernel itself. * Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996. * - * Added a couple of missing wake_up() calls. + * Added a couple of missing wake_up() calls. Thanks to Thomas Meckel + * (Thomas.Meckel@mni.fh-giessen.de) for spotting this. * Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996. * - * TODO: Do not honour mandatory locks on remote file systems. This matches - * the SVR4 semantics and neatly sidesteps a pile of awkward issues that - * would otherwise have to be addressed. + * Changed FL_POSIX locks to use the block list in the same way as FL_FLOCK + * locks. Changed process synchronisation to avoid dereferencing locks that + * have already been freed. + * Andy Walker (andy@lysaker.kvaerner.no), Sep 21, 1996. + * + * Made the block list a circular list to minimise searching in the list. + * Andy Walker (andy@lysaker.kvaerner.no), Sep 25, 1996. + * + * Made mandatory locking a mount option. Default is not to allow mandatory + * locking. + * Andy Walker (andy@lysaker.kvaerner.no), Oct 04, 1996. + * + * Fixed /proc/locks interface so that we can't overrun the buffer we are handed. + * Andy Walker (andy@lysaker.kvaerner.no), May 12, 1997. */ -#include - #include #include #include @@ -118,76 +128,115 @@ unsigned int wait); static int posix_locks_deadlock(struct task_struct *my_task, struct task_struct *blocked_task); -static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2); -static void posix_remove_locks(struct file_lock **before, struct task_struct *task); -static void flock_remove_locks(struct file_lock **before, struct file *filp); static struct file_lock *locks_alloc_lock(struct file_lock *fl); static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl); -static void locks_delete_lock(struct file_lock **fl, unsigned int wait); -static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx); +static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait); +static char *lock_get_status(struct file_lock *fl, int id, char *pfx); + +static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter); +static void locks_delete_block(struct file_lock *blocker, struct file_lock *waiter); +static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait); static struct file_lock *file_lock_table = NULL; -static struct file_lock *unused_file_locks = NULL; -/* - * Free lock not inserted in any queue - * - * Careful! We can't just "kfree()" it: there may be other processes - * that have yet to remove themselves from the wait queues. Thus the - * internal memory management. +/* Free lock not inserted in any queue. */ static inline void locks_free_lock(struct file_lock *fl) { - struct file_lock *next = unused_file_locks; - unused_file_locks = fl; - fl->fl_next = next; -} - -/* Add lock fl to the blocked list pointed to by block. - * We search to the end of the existing list and insert the the new - * struct. This ensures processes will be woken up in the order they - * blocked. - * NOTE: nowhere does the documentation insist that processes be woken - * up in this order, but it seems like the reasonable thing to do. - * If the blocked list gets long then this search could get expensive, - * in which case we could consider waking the processes up in reverse - * order, or making the blocked list a doubly linked circular list. - * - * This functions are called only from one place (flock_lock_file) - * so they are inlined now. -- Dmitry Gorodchanin 02/09/96. - */ - -static inline void locks_insert_block(struct file_lock *bfl, - struct file_lock *fl) + if (waitqueue_active(&fl->fl_wait)) + panic("Aarggh: attempting to free lock with active wait queue - shoot Andy"); + + if (fl->fl_nextblock != NULL || fl->fl_prevblock != NULL) + panic("Aarggh: attempting to free lock with active block list - shoot Andy"); + + kfree(fl); + return; +} + +/* Check if two locks overlap each other. + */ +static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2) { - while (bfl->fl_block != NULL) { - bfl = bfl->fl_block; - } + return ((fl1->fl_end >= fl2->fl_start) && + (fl2->fl_end >= fl1->fl_start)); +} - bfl->fl_block = fl; - fl->fl_block = NULL; +/* Insert waiter into blocker's block list. + * We use a circular list so that processes can be easily woken up in + * the order they blocked. The documentation doesn't require this but + * it seems seems like the reasonable thing to do. + */ +static void locks_insert_block(struct file_lock *blocker, + struct file_lock *waiter) +{ + struct file_lock *prevblock; + + if (blocker->fl_prevblock == NULL) + /* No previous waiters - list is empty */ + prevblock = blocker; + else + /* Previous waiters exist - add to end of list */ + prevblock = blocker->fl_prevblock; + + prevblock->fl_nextblock = waiter; + blocker->fl_prevblock = waiter; + waiter->fl_nextblock = blocker; + waiter->fl_prevblock = prevblock; return; } -static inline void locks_delete_block(struct file_lock *bfl, - struct file_lock *fl) +/* Remove waiter from blocker's block list. + * When blocker ends up pointing to itself then the list is empty. + */ +static void locks_delete_block(struct file_lock *blocker, + struct file_lock *waiter) { - struct file_lock *tfl; + struct file_lock *nextblock; + struct file_lock *prevblock; - while ((tfl = bfl->fl_block) != NULL) { - if (tfl == fl) { - bfl->fl_block = fl->fl_block; - fl->fl_block = NULL; - return; - } - bfl = tfl; + nextblock = waiter->fl_nextblock; + prevblock = waiter->fl_prevblock; + + if (nextblock == NULL) + return; + + nextblock->fl_prevblock = prevblock; + prevblock->fl_nextblock = nextblock; + + waiter->fl_prevblock = waiter->fl_nextblock = NULL; + if (blocker->fl_nextblock == blocker) + /* No more locks on blocker's blocked list */ + blocker->fl_prevblock = blocker->fl_nextblock = NULL; + return; +} + +/* Wake up processes blocked waiting for blocker. + * If told to wait then schedule the processes until the block list + * is empty, otherwise empty the block list ourselves. + */ +static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait) +{ + struct file_lock *waiter; + + while ((waiter = blocker->fl_nextblock) != NULL) { + wake_up(&waiter->fl_wait); + if (wait) + /* Let the blocked process remove waiter from the + * block list when it gets scheduled. + */ + schedule(); + else + /* Remove waiter from the block list, because by the + * time it wakes up blocker won't exist any more. + */ + locks_delete_block(blocker, waiter); } return; } -/* flock() system call entry point. Apply a FLOCK style lock to +/* flock() system call entry point. Apply a FL_FLOCK style lock to * an open file descriptor. */ asmlinkage int sys_flock(unsigned int fd, unsigned int cmd) @@ -203,8 +252,8 @@ if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) return (-EBADF); - - return (flock_lock_file(filp, &file_lock, cmd & LOCK_UN ? 0 : cmd & LOCK_NB ? 0 : 1)); + + return (flock_lock_file(filp, &file_lock, (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1)); } /* Report the first existing lock that would conflict with l. @@ -224,26 +273,24 @@ return (error); memcpy_fromfs(&flock, l, sizeof(flock)); - if ((flock.l_type == F_UNLCK) || (flock.l_type == F_EXLCK) || - (flock.l_type == F_SHLCK)) + if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) return (-EINVAL); if (!filp->f_inode || !posix_make_lock(filp, &file_lock, &flock)) return (-EINVAL); - if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & F_POSIX)) { - while (fl != NULL) { - if (posix_locks_conflict(&file_lock, fl)) { - flock.l_pid = fl->fl_owner->pid; - flock.l_start = fl->fl_start; - flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : - fl->fl_end - fl->fl_start + 1; - flock.l_whence = 0; - flock.l_type = fl->fl_type; - memcpy_tofs(l, &flock, sizeof(flock)); - return (0); - } - fl = fl->fl_next; + for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) { + if (!(fl->fl_flags & FL_POSIX)) + continue; + if (posix_locks_conflict(&file_lock, fl)) { + flock.l_pid = fl->fl_owner->pid; + flock.l_start = fl->fl_start; + flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : + fl->fl_end - fl->fl_start + 1; + flock.l_whence = 0; + flock.l_type = fl->fl_type; + memcpy_tofs(l, &flock, sizeof(flock)); + return (0); } } @@ -254,8 +301,6 @@ /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). - * It also emulates flock() in a pretty broken way for older C - * libraries. */ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) { @@ -265,8 +310,7 @@ struct flock flock; struct inode *inode; - /* - * Get arguments and validate them ... + /* Get arguments and validate them ... */ if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd])) @@ -279,11 +323,12 @@ if (!(inode = filp->f_inode)) return (-EINVAL); -#ifdef CONFIG_LOCK_MANDATORY /* Don't allow mandatory locks on files that may be memory mapped * and shared. */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && inode->i_mmap) { + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && + inode->i_mmap) { struct vm_area_struct *vma = inode->i_mmap; do { if (vma->vm_flags & VM_MAYSHARE) @@ -291,42 +336,29 @@ vma = vma->vm_next_share; } while (vma != inode->i_mmap); } -#endif memcpy_fromfs(&flock, l, sizeof(flock)); if (!posix_make_lock(filp, &file_lock, &flock)) return (-EINVAL); switch (flock.l_type) { - case F_RDLCK : + case F_RDLCK: if (!(filp->f_mode & 1)) return (-EBADF); break; - case F_WRLCK : + case F_WRLCK: if (!(filp->f_mode & 2)) return (-EBADF); break; - case F_SHLCK : - case F_EXLCK : -#if 1 -/* warn a bit for now, but don't overdo it */ -{ - static int count = 0; - if (!count) { - count=1; + case F_UNLCK: + break; + case F_SHLCK: + case F_EXLCK: printk(KERN_WARNING - "fcntl_setlk() called by process %d (%s) with broken flock() emulation\n", + "fcntl_setlk(): process %d (%s) requested broken flock() emulation\n", current->pid, current->comm); - } -} -#endif - if (!(filp->f_mode & 3)) - return (-EBADF); - break; - case F_UNLCK : - break; default: - return -EINVAL; + return (-EINVAL); } return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW)); @@ -337,41 +369,18 @@ void locks_remove_locks(struct task_struct *task, struct file *filp) { struct file_lock *fl; + struct file_lock **before; /* For POSIX locks we free all locks on this file for the given task. * For FLOCK we only free locks on this *open* file if it is the last * close on that file. */ - if ((fl = filp->f_inode->i_flock) != NULL) { - if (fl->fl_flags & F_POSIX) - posix_remove_locks(&filp->f_inode->i_flock, task); - else - flock_remove_locks(&filp->f_inode->i_flock, filp); - } - - return; -} - -static void posix_remove_locks(struct file_lock **before, struct task_struct *task) -{ - struct file_lock *fl; - - while ((fl = *before) != NULL) { - if (fl->fl_owner == task) - locks_delete_lock(before, 0); - else - before = &fl->fl_next; - } - - return; -} - -static void flock_remove_locks(struct file_lock **before, struct file *filp) -{ - struct file_lock *fl; + before = &filp->f_inode->i_flock; while ((fl = *before) != NULL) { - if ((fl->fl_file == filp) && (filp->f_count == 1)) + if (((fl->fl_flags & FL_POSIX) && (fl->fl_owner == task)) || + ((fl->fl_flags & FL_FLOCK) && (fl->fl_file == filp) && + (filp->f_count == 1))) locks_delete_lock(before, 0); else before = &fl->fl_next; @@ -382,46 +391,40 @@ int locks_verify_locked(struct inode *inode) { -#ifdef CONFIG_LOCK_MANDATORY /* Candidates for mandatory locking have the setgid bit set * but no group execute bit - an otherwise meaningless combination. */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return (locks_mandatory_locked(inode)); -#endif return (0); } int locks_verify_area(int read_write, struct inode *inode, struct file *filp, unsigned int offset, unsigned int count) { -#ifdef CONFIG_LOCK_MANDATORY /* Candidates for mandatory locking have the setgid bit set * but no group execute bit - an otherwise meaningless combination. */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return (locks_mandatory_area(read_write, inode, filp, offset, count)); -#endif return (0); } int locks_mandatory_locked(struct inode *inode) { -#ifdef CONFIG_LOCK_MANDATORY struct file_lock *fl; /* Search the lock list for this inode for any POSIX locks. */ - if ((fl = inode->i_flock) && (fl->fl_flags & F_FLOCK)) - return (0); - - while (fl != NULL) { + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + if (!(fl->fl_flags & FL_POSIX)) + continue; if (fl->fl_owner != current) return (-EAGAIN); - fl = fl->fl_next; } -#endif return (0); } @@ -429,51 +432,50 @@ struct file *filp, unsigned int offset, unsigned int count) { -#ifdef CONFIG_LOCK_MANDATORY struct file_lock *fl; + struct file_lock tfl; + + memset(&tfl, 0, sizeof(tfl)); + + tfl.fl_file = filp; + tfl.fl_flags = FL_POSIX | FL_ACCESS; + tfl.fl_owner = current; + tfl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; + tfl.fl_start = offset; + tfl.fl_end = offset + count - 1; repeat: - /* Check that there are locks, and that they're not F_FLOCK locks. - */ - if ((fl = inode->i_flock) && (fl->fl_flags & F_FLOCK)) - return (0); - - /* - * Search the lock list for this inode for locks that conflict with + /* Search the lock list for this inode for locks that conflict with * the proposed read/write. */ - while (fl != NULL) { - if (fl->fl_owner == current || - fl->fl_end < offset || fl->fl_start >= offset + count) - goto next_lock; - - /* - * Block for writes against a "read" lock, + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + if (!(fl->fl_flags & FL_POSIX)) + continue; + /* Block for writes against a "read" lock, * and both reads and writes against a "write" lock. */ - if ((read_write == FLOCK_VERIFY_WRITE) || - (fl->fl_type == F_WRLCK)) { + if (posix_locks_conflict(fl, &tfl)) { if (filp && (filp->f_flags & O_NONBLOCK)) return (-EAGAIN); if (current->signal & ~current->blocked) return (-ERESTARTSYS); if (posix_locks_deadlock(current, fl->fl_owner)) return (-EDEADLK); - interruptible_sleep_on(&fl->fl_wait); + + locks_insert_block(fl, &tfl); + interruptible_sleep_on(&tfl.fl_wait); + locks_delete_block(fl, &tfl); + if (current->signal & ~current->blocked) return (-ERESTARTSYS); - /* - * If we've been sleeping someone might have + /* If we've been sleeping someone might have * changed the permissions behind our back. */ if ((inode->i_mode & (S_ISGID | S_IXGRP)) != S_ISGID) break; goto repeat; } - next_lock: - fl = fl->fl_next; } -#endif return (0); } @@ -485,37 +487,31 @@ { off_t start; - fl->fl_flags = F_POSIX; + memset(fl, 0, sizeof(*fl)); + + fl->fl_flags = FL_POSIX; switch (l->l_type) { - case F_RDLCK : - case F_WRLCK : - case F_UNLCK : + case F_RDLCK: + case F_WRLCK: + case F_UNLCK: fl->fl_type = l->l_type; break; - case F_SHLCK : - fl->fl_type = F_RDLCK; - fl->fl_flags |= F_BROKEN; - break; - case F_EXLCK : - fl->fl_type = F_WRLCK; - fl->fl_flags |= F_BROKEN; - break; - default : + default: return (0); } switch (l->l_whence) { - case 0 : /*SEEK_SET*/ + case 0: /*SEEK_SET*/ start = 0; break; - case 1 : /*SEEK_CUR*/ + case 1: /*SEEK_CUR*/ start = filp->f_pos; break; - case 2 : /*SEEK_END*/ + case 2: /*SEEK_END*/ start = filp->f_inode->i_size; break; - default : + default: return (0); } @@ -527,8 +523,7 @@ fl->fl_file = filp; fl->fl_owner = current; - fl->fl_wait = NULL; /* just for cleanliness */ - + return (1); } @@ -538,29 +533,30 @@ static int flock_make_lock(struct file *filp, struct file_lock *fl, unsigned int cmd) { + memset(fl, 0, sizeof(*fl)); + if (!filp->f_inode) /* just in case */ return (0); switch (cmd & ~LOCK_NB) { - case LOCK_SH : + case LOCK_SH: fl->fl_type = F_RDLCK; break; - case LOCK_EX : + case LOCK_EX: fl->fl_type = F_WRLCK; break; - case LOCK_UN : + case LOCK_UN: fl->fl_type = F_UNLCK; break; - default : + default: return (0); } - fl->fl_flags = F_FLOCK; + fl->fl_flags = FL_FLOCK; fl->fl_start = 0; fl->fl_end = OFFSET_MAX; fl->fl_file = filp; fl->fl_owner = NULL; - fl->fl_wait = NULL; /* just for cleanliness */ return (1); } @@ -573,7 +569,8 @@ /* POSIX locks owned by the same process do not conflict with * each other. */ - if (caller_fl->fl_owner == sys_fl->fl_owner) + if (!(sys_fl->fl_flags & FL_POSIX) || + (caller_fl->fl_owner == sys_fl->fl_owner)) return (0); return (locks_conflict(caller_fl, sys_fl)); @@ -587,7 +584,8 @@ /* FLOCK locks referring to the same filp do not conflict with * each other. */ - if (caller_fl->fl_file == sys_fl->fl_file) + if (!(sys_fl->fl_flags & FL_FLOCK) || + (caller_fl->fl_file == sys_fl->fl_file)) return (0); return (locks_conflict(caller_fl, sys_fl)); @@ -602,10 +600,10 @@ return (0); switch (caller_fl->fl_type) { - case F_RDLCK : + case F_RDLCK: return (sys_fl->fl_type == F_WRLCK); - case F_WRLCK : + case F_WRLCK: return (1); default: @@ -616,14 +614,6 @@ return (0); /* This should never happen */ } -/* Check if two locks overlap each other. - */ -static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2) -{ - return ((fl1->fl_end >= fl2->fl_start) && - (fl2->fl_end >= fl1->fl_start)); -} - /* This function tests for deadlock condition before putting a process to * sleep. The detection scheme is no longer recursive. Recursive was neat, * but dangerous - we risked stack corruption if the lock data was bad, or @@ -637,34 +627,31 @@ static int posix_locks_deadlock(struct task_struct *my_task, struct task_struct *blocked_task) { - struct wait_queue *dlock_wait; struct file_lock *fl; + struct file_lock *bfl; next_task: if (my_task == blocked_task) return (1); for (fl = file_lock_table; fl != NULL; fl = fl->fl_nextlink) { - struct wait_queue *head; - if (fl->fl_owner == NULL || fl->fl_wait == NULL) + if (fl->fl_owner == NULL || fl->fl_nextblock == NULL) continue; - head = WAIT_QUEUE_HEAD(&fl->fl_wait); - dlock_wait = fl->fl_wait; - while (dlock_wait != head) { - if (dlock_wait->task == blocked_task) { + for (bfl = fl->fl_nextblock; bfl != fl; bfl = bfl->fl_nextblock) { + if (bfl->fl_owner == blocked_task) { if (fl->fl_owner == my_task) { return (1); } blocked_task = fl->fl_owner; goto next_task; } - dlock_wait = dlock_wait->next; } } return (0); } -/* Try to create a FLOCK lock on filp. We always insert new locks at - * the head of the list. +/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks at + * the head of the list, but that's secret knowledge known only to the next + * two functions. */ static int flock_lock_file(struct file *filp, struct file_lock *caller, unsigned int wait) @@ -675,11 +662,7 @@ int change = 0; before = &filp->f_inode->i_flock; - - if ((fl = *before) && (fl->fl_flags & F_POSIX)) - return (-EBUSY); - - while ((fl = *before) != NULL) { + while (((fl = *before) != NULL) && (fl->fl_flags & FL_FLOCK)) { if (caller->fl_file == fl->fl_file) { if (caller->fl_type == fl->fl_type) return (0); @@ -698,51 +681,42 @@ if ((new_fl = locks_alloc_lock(caller)) == NULL) return (-ENOLCK); repeat: - if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & F_POSIX)) { - locks_free_lock(new_fl); - return (-EBUSY); - } - - while (fl != NULL) { - if (flock_locks_conflict(new_fl, fl)) { - if (!wait) { - locks_free_lock(new_fl); - return (-EAGAIN); - } - if (current->signal & ~current->blocked) { - /* Note: new_fl is not in any queue at this - * point, so we must use locks_free_lock() - * instead of locks_delete_lock() - * Dmitry Gorodchanin 09/02/96. - */ - locks_free_lock(new_fl); - return (-ERESTARTSYS); - } - locks_insert_block(fl, new_fl); - interruptible_sleep_on(&new_fl->fl_wait); - wake_up(&new_fl->fl_wait); - if (current->signal & ~current->blocked) { - /* If we are here, than we were awakened - * by a signal, so new_fl is still in the - * block queue of fl. We need to remove - * new_fl and then free it. - * Dmitry Gorodchanin 09/02/96. - */ - locks_delete_block(fl, new_fl); - locks_free_lock(new_fl); - return (-ERESTARTSYS); - } - goto repeat; + for (fl = filp->f_inode->i_flock; (fl != NULL) && (fl->fl_flags & FL_FLOCK); + fl = fl->fl_next) { + if (!flock_locks_conflict(new_fl, fl)) + continue; + if (!wait) { + locks_free_lock(new_fl); + return (-EAGAIN); } - fl = fl->fl_next; + if (current->signal & ~current->blocked) { + /* Note: new_fl is not in any queue at this + * point, so we must use locks_free_lock() + * instead of locks_delete_lock() + * Dmitry Gorodchanin 09/02/96. + */ + locks_free_lock(new_fl); + return (-ERESTARTSYS); + } + locks_insert_block(fl, new_fl); + interruptible_sleep_on(&new_fl->fl_wait); + locks_delete_block(fl, new_fl); + if (current->signal & ~current->blocked) { + /* Awakened by a signal. Free the new + * lock and return an error. + */ + locks_free_lock(new_fl); + return (-ERESTARTSYS); + } + goto repeat; } locks_insert_lock(&filp->f_inode->i_flock, new_fl); return (0); } /* Add a POSIX style lock to a file. - * We merge adjacent locks whenever possible. POSIX locks come after FLOCK - * locks in the list and are sorted by owner task, then by starting address + * We merge adjacent locks whenever possible. POSIX locks are sorted by owner + * task, then by starting address * * Kai Petzke writes: * To make freeing a lock much faster, we keep a pointer to the lock before the @@ -762,39 +736,39 @@ struct file_lock **before; int added = 0; -repeat: - if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & F_FLOCK)) - return (-EBUSY); - if (caller->fl_type != F_UNLCK) { - while (fl != NULL) { - if (posix_locks_conflict(caller, fl)) { - if (!wait) - return (-EAGAIN); - if (current->signal & ~current->blocked) - return (-ERESTARTSYS); - if (posix_locks_deadlock(caller->fl_owner, fl->fl_owner)) - return (-EDEADLK); - interruptible_sleep_on(&fl->fl_wait); - if (current->signal & ~current->blocked) - return (-ERESTARTSYS); - goto repeat; - } - fl = fl->fl_next; + repeat: + for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) { + if (!(fl->fl_flags & FL_POSIX)) + continue; + if (!posix_locks_conflict(caller, fl)) + continue; + if (!wait) + return (-EAGAIN); + if (current->signal & ~current->blocked) + return (-ERESTARTSYS); + if (posix_locks_deadlock(caller->fl_owner, fl->fl_owner)) + return (-EDEADLK); + locks_insert_block(fl, caller); + interruptible_sleep_on(&caller->fl_wait); + locks_delete_block(fl, caller); + if (current->signal & ~current->blocked) + return (-ERESTARTSYS); + goto repeat; } } - /* - * Find the first old lock with the same owner as the new lock. + + /* Find the first old lock with the same owner as the new lock. */ before = &filp->f_inode->i_flock; - /* First skip FLOCK locks and locks owned by other processes. + /* First skip locks owned by other processes. */ - while ((fl = *before) && (caller->fl_owner != fl->fl_owner)) { + while ((fl = *before) && (!(fl->fl_flags & FL_POSIX) || + (caller->fl_owner != fl->fl_owner))) { before = &fl->fl_next; } - /* Process locks with this owner. */ @@ -862,7 +836,7 @@ * as the change in lock type might satisfy * their needs. */ - wake_up(&fl->fl_wait); + locks_wake_up_blocks(fl, 0); fl->fl_start = caller->fl_start; fl->fl_end = caller->fl_end; fl->fl_type = caller->fl_type; @@ -897,52 +871,43 @@ locks_insert_lock(before, left); } right->fl_start = caller->fl_end + 1; - wake_up(&right->fl_wait); + locks_wake_up_blocks(right, 0); } if (left) { left->fl_end = caller->fl_start - 1; - wake_up(&left->fl_wait); + locks_wake_up_blocks(left, 0); } return (0); } -/* Allocate memory for a new lock and initialize its fields from - * fl. The lock is not inserted into any lists until locks_insert_lock() - * or locks_insert_block() are called. +/* Allocate new lock. + * Initialize its fields from fl. The lock is not inserted into any + * lists until locks_insert_lock() or locks_insert_block() are called. */ - static struct file_lock *locks_alloc_lock(struct file_lock *fl) { - struct file_lock *retval; + struct file_lock *tmp; - retval = unused_file_locks; - if (retval) { - unused_file_locks = retval->fl_next; - goto init_file_lock; - } - retval = (struct file_lock *) - kmalloc(sizeof(struct file_lock), GFP_ATOMIC); - if (retval) { - retval->fl_wait = NULL; -init_file_lock: - retval->fl_next = NULL; - retval->fl_nextlink = NULL; - retval->fl_prevlink = NULL; - retval->fl_block = NULL; - retval->fl_owner = fl->fl_owner; - retval->fl_file = fl->fl_file; - retval->fl_flags = fl->fl_flags; - retval->fl_type = fl->fl_type; - retval->fl_start = fl->fl_start; - retval->fl_end = fl->fl_end; - } - return retval; + /* Okay, let's make a new file_lock structure... */ + if ((tmp = (struct file_lock *)kmalloc(sizeof(struct file_lock), + GFP_ATOMIC)) == NULL) + return (tmp); + + memset(tmp, 0, sizeof(*tmp)); + + tmp->fl_flags = fl->fl_flags; + tmp->fl_owner = fl->fl_owner; + tmp->fl_file = fl->fl_file; + tmp->fl_type = fl->fl_type; + tmp->fl_start = fl->fl_start; + tmp->fl_end = fl->fl_end; + + return (tmp); } /* Insert file lock fl into an inode's lock list at the position indicated * by pos. At the same time add the lock to the global file lock list. */ - static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) { fl->fl_nextlink = file_lock_table; @@ -957,63 +922,52 @@ } /* Delete a lock and free it. - * First remove our lock from the lock lists. Then remove all the blocked - * locks from our blocked list, waking up the processes that own them. If - * told to wait, then sleep on each of these lock's wait queues. Each - * blocked process will wake up and immediately wake up its own wait queue - * allowing us to be scheduled again. Lastly, wake up our own wait queue - * before freeing the file_lock structure. + * First remove our lock from the active lock lists. Then call + * locks_wake_up_blocks() to wake up processes that are blocked + * waiting for this lock. Finally free the lock structure. */ - -static void locks_delete_lock(struct file_lock **fl_p, unsigned int wait) +static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) { - struct file_lock *fl; - struct file_lock *pfl; - struct file_lock *nfl; + struct file_lock *thisfl; + struct file_lock *prevfl; + struct file_lock *nextfl; - fl = *fl_p; - *fl_p = fl->fl_next; - pfl = fl->fl_prevlink; - nfl = fl->fl_nextlink; + thisfl = *thisfl_p; + *thisfl_p = thisfl->fl_next; + + prevfl = thisfl->fl_prevlink; + nextfl = thisfl->fl_nextlink; - if (nfl != NULL) - nfl->fl_prevlink = pfl; + if (nextfl != NULL) + nextfl->fl_prevlink = prevfl; - if (pfl != NULL) - pfl->fl_nextlink = nfl; + if (prevfl != NULL) + prevfl->fl_nextlink = nextfl; else - file_lock_table = nfl; + file_lock_table = nextfl; - while ((nfl = fl->fl_block) != NULL) { - fl->fl_block = nfl->fl_block; - nfl->fl_block = NULL; - wake_up(&nfl->fl_wait); - if (wait) - sleep_on(&nfl->fl_wait); - } - - wake_up(&fl->fl_wait); - locks_free_lock(fl); + locks_wake_up_blocks(thisfl, wait); + locks_free_lock(thisfl); return; } -static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx) +static char *lock_get_status(struct file_lock *fl, int id, char *pfx) { - struct wait_queue *wt; + static char temp[129]; + char *p = temp; + struct inode *inode; + + inode = fl->fl_file->f_inode; p += sprintf(p, "%d:%s ", id, pfx); - if (fl->fl_flags & F_POSIX) { -#ifdef CONFIG_LOCK_MANDATORY - p += sprintf(p, "%s %s ", - (fl->fl_flags & F_BROKEN) ? "BROKEN" : "POSIX ", - ((fl->fl_file->f_inode->i_mode & (S_IXGRP | S_ISGID)) - == S_ISGID) ? "MANDATORY" : "ADVISORY "); -#else - p += sprintf(p, "%s ADVISORY ", - (fl->fl_flags & F_BROKEN) ? "BROKEN" : "POSIX "); -#endif + if (fl->fl_flags & FL_POSIX) { + p += sprintf(p, "%6s %s ", + (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", + (IS_MANDLOCK(inode) && + (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ? + "MANDATORY" : "ADVISORY "); } else { p += sprintf(p, "FLOCK ADVISORY "); @@ -1021,36 +975,70 @@ p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); p += sprintf(p, "%d %s:%ld %ld %ld ", fl->fl_owner ? fl->fl_owner->pid : 0, - kdevname(fl->fl_file->f_inode->i_dev), - fl->fl_file->f_inode->i_ino, fl->fl_start, + kdevname(inode->i_dev), inode->i_ino, fl->fl_start, fl->fl_end); - p += sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n%d:%s", - (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, - (long)fl->fl_next, (long)fl->fl_block, id, pfx); - if ((wt = fl->fl_wait) != NULL) { - struct wait_queue *head = WAIT_QUEUE_HEAD(&fl->fl_wait); - while (wt != head) { - p += sprintf(p, " %d", wt->task->pid); - wt = wt->next; + sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n", + (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, + (long)fl->fl_next, (long)fl->fl_nextblock); + return (temp); +} + +static inline int copy_lock_status(char *p, char **q, off_t pos, int len, + off_t offset, int length) +{ + int i; + + i = pos - offset; + if (i > 0) { + if (i >= length) { + i = len + length - i; + memcpy(*q, p, i); + *q += i; + return (0); + } + if (i < len) { + p += len - i; } + else + i = len; + memcpy(*q, p, i); + *q += i; } - p += sprintf(p, "\n"); - return (p); + + return (1); } -int get_locks_status(char *buf) +int get_locks_status(char *buffer, char **start, off_t offset, int length) { struct file_lock *fl; struct file_lock *bfl; char *p; + char *q = buffer; int i; + int len; + off_t pos = 0; - p = buf; for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) { - p = lock_get_status(fl, p, i, ""); - for (bfl = fl; bfl->fl_block != NULL; bfl = bfl->fl_block) - p = lock_get_status(bfl->fl_block, p, i, " ->"); - } - return (p - buf); + p = lock_get_status(fl, i, ""); + len = strlen(p); + pos += len; + if (!copy_lock_status(p, &q, pos, len, offset, length)) + goto done; + if ((bfl = fl->fl_nextblock) == NULL) + continue; + do { + p = lock_get_status(bfl, i, " ->"); + len = strlen(p); + pos += len; + if (!copy_lock_status(p, &q, pos, len, offset, length)) + goto done; + } while ((bfl = bfl->fl_nextblock) != fl); + } +done: + if (q != buffer) + *start = buffer; + return (q - buffer); } + + diff -u --recursive --new-file v2.0.30/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.0.30/linux/fs/proc/array.c Tue Oct 29 17:42:41 1996 +++ linux/fs/proc/array.c Sun Aug 3 13:59:07 1997 @@ -975,7 +975,7 @@ extern int get_pci_list(char*); extern int get_md_status (char *); extern int get_rtc_status (char *); -extern int get_locks_status (char *); +extern int get_locks_status (char *, char **, off_t, int); #ifdef __SMP_PROF__ extern int get_smp_prof_list(char *); #endif @@ -1051,7 +1051,7 @@ return get_rtc_status(page); #endif case PROC_LOCKS: - return get_locks_status(page); + return get_locks_status(page, start, offset, length); } return -EBADF; } diff -u --recursive --new-file v2.0.30/linux/fs/super.c linux/fs/super.c --- v2.0.30/linux/fs/super.c Tue Apr 8 08:47:46 1997 +++ linux/fs/super.c Sun Aug 3 13:59:07 1997 @@ -277,6 +277,7 @@ { MS_NOSUID, ",nosuid" }, { MS_NODEV, ",nodev" }, { MS_SYNCHRONOUS, ",sync" }, + { MS_MANDLOCK, ",mand" }, #ifdef MS_NOSUB /* Can't find this except in mount.c */ { MS_NOSUB, ",nosub" }, #endif diff -u --recursive --new-file v2.0.30/linux/include/asm-alpha/fcntl.h linux/include/asm-alpha/fcntl.h --- v2.0.30/linux/include/asm-alpha/fcntl.h Mon Aug 5 00:13:54 1996 +++ linux/include/asm-alpha/fcntl.h Sun Aug 3 13:59:07 1997 @@ -49,12 +49,6 @@ blocking */ #define LOCK_UN 8 /* remove lock */ -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#define F_BROKEN 4 /* broken flock() emulation */ -#endif /* __KERNEL__ */ - struct flock { short l_type; short l_whence; diff -u --recursive --new-file v2.0.30/linux/include/asm-alpha/fpu.h linux/include/asm-alpha/fpu.h --- v2.0.30/linux/include/asm-alpha/fpu.h Thu Dec 21 22:22:06 1995 +++ linux/include/asm-alpha/fpu.h Sun Aug 3 10:58:38 1997 @@ -57,8 +57,29 @@ IEEE_STATUS_OVF | IEEE_STATUS_UNF | \ IEEE_STATUS_INE) +#define IEEE_SW_MASK (IEEE_TRAP_ENABLE_MASK | IEEE_STATUS_MASK) + #define IEEE_STATUS_TO_EXCSUM_SHIFT 16 #define IEEE_INHERIT (1UL<<63) /* inherit on thread create? */ + +/* + * Convert the software IEEE trap enables and status bits into the + * hardware fpcr format. + */ + +static inline unsigned long +ieee_sw_to_fpcr(unsigned long sw) +{ + unsigned long fpcw; + fpcw = (sw & IEEE_STATUS_MASK) << 35; + fpcw |= sw & IEEE_STATUS_MASK ? FPCR_SUM : 0; + fpcw |= (~sw & (IEEE_TRAP_ENABLE_INV + | IEEE_TRAP_ENABLE_DZE + | IEEE_TRAP_ENABLE_OVF)) << 48; + fpcw |= (~sw & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE)) << 57; + return fpcw; +} + #endif /* __ASM_ALPHA_FPU_H */ diff -u --recursive --new-file v2.0.30/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v2.0.30/linux/include/asm-alpha/processor.h Sun Sep 15 00:34:18 1996 +++ linux/include/asm-alpha/processor.h Sun Aug 3 10:58:38 1997 @@ -43,8 +43,9 @@ /* the fields below are Linux-specific: */ /* - * bit 0: perform syscall argument validation (get/set_fs) - * bit 1..5: IEEE_TRAP_ENABLE bits (see fpu.h) + * bit 0: perform syscall argument validation (get/set_fs) + * bit 1..5: IEEE_TRAP_ENABLE bits (see fpu.h) + * bit 17..21: IEEE_STATUS bits (see fpu.h) */ unsigned long flags; }; diff -u --recursive --new-file v2.0.30/linux/include/asm-i386/fcntl.h linux/include/asm-i386/fcntl.h --- v2.0.30/linux/include/asm-i386/fcntl.h Wed Jul 17 05:10:03 1996 +++ linux/include/asm-i386/fcntl.h Sun Aug 3 13:59:08 1997 @@ -48,12 +48,6 @@ blocking */ #define LOCK_UN 8 /* remove lock */ -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#define F_BROKEN 4 /* broken flock() emulation */ -#endif /* __KERNEL__ */ - struct flock { short l_type; short l_whence; diff -u --recursive --new-file v2.0.30/linux/include/asm-m68k/fcntl.h linux/include/asm-m68k/fcntl.h --- v2.0.30/linux/include/asm-m68k/fcntl.h Tue Apr 30 03:09:45 1996 +++ linux/include/asm-m68k/fcntl.h Sun Aug 3 13:59:08 1997 @@ -48,12 +48,6 @@ blocking */ #define LOCK_UN 8 /* remove lock */ -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#define F_BROKEN 4 /* broken flock() emulation */ -#endif /* __KERNEL__ */ - struct flock { short l_type; short l_whence; diff -u --recursive --new-file v2.0.30/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h --- v2.0.30/linux/include/asm-mips/fcntl.h Tue Apr 30 03:09:45 1996 +++ linux/include/asm-mips/fcntl.h Sun Aug 3 13:59:08 1997 @@ -49,12 +49,6 @@ blocking */ #define LOCK_UN 8 /* remove lock */ -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#define F_BROKEN 4 /* broken flock() emulation */ -#endif /* __KERNEL__ */ - typedef struct flock { short l_type; short l_whence; diff -u --recursive --new-file v2.0.30/linux/include/asm-ppc/fcntl.h linux/include/asm-ppc/fcntl.h --- v2.0.30/linux/include/asm-ppc/fcntl.h Tue Apr 30 03:09:45 1996 +++ linux/include/asm-ppc/fcntl.h Sun Aug 3 13:59:08 1997 @@ -48,12 +48,6 @@ blocking */ #define LOCK_UN 8 /* remove lock */ -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#define F_BROKEN 4 /* broken flock() emulation */ -#endif /* __KERNEL__ */ - struct flock { short l_type; short l_whence; diff -u --recursive --new-file v2.0.30/linux/include/asm-sparc/fcntl.h linux/include/asm-sparc/fcntl.h --- v2.0.30/linux/include/asm-sparc/fcntl.h Tue Apr 30 03:09:45 1996 +++ linux/include/asm-sparc/fcntl.h Sun Aug 3 13:59:08 1997 @@ -48,12 +48,6 @@ blocking */ #define LOCK_UN 8 /* remove lock */ -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#define F_BROKEN 4 /* broken flock() emulation */ -#endif /* __KERNEL__ */ - struct flock { short l_type; short l_whence; diff -u --recursive --new-file v2.0.30/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.0.30/linux/include/linux/fs.h Fri Mar 28 16:08:17 1997 +++ linux/include/linux/fs.h Sun Aug 3 13:59:08 1997 @@ -69,6 +69,7 @@ #define MS_NOEXEC 8 /* Disallow program execution */ #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ +#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ #define S_WRITE 128 /* Write on file/directory/symlink */ #define S_APPEND 256 /* Append-only file */ #define S_IMMUTABLE 512 /* Immutable file */ @@ -76,7 +77,7 @@ /* * Flags that can be altered by MS_REMOUNT */ -#define MS_RMT_MASK (MS_RDONLY) +#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK) /* * Magic mount flag number. Has to be or-ed to the flag values. @@ -97,6 +98,7 @@ #define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV) #define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC) #define IS_SYNC(inode) ((inode)->i_flags & MS_SYNCHRONOUS) +#define IS_MANDLOCK(inode) ((inode)->i_flags & MS_MANDLOCK) #define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) @@ -335,16 +337,22 @@ void *private_data; /* needed for tty driver, and maybe others */ }; +#define FL_POSIX 1 +#define FL_FLOCK 2 +#define FL_BROKEN 4 /* broken flock() emulation */ +#define FL_ACCESS 8 /* for processes suspended by mandatory locking */ + struct file_lock { struct file_lock *fl_next; /* singly linked list for this inode */ struct file_lock *fl_nextlink; /* doubly linked list of all locks */ struct file_lock *fl_prevlink; /* used to simplify lock removal */ - struct file_lock *fl_block; + struct file_lock *fl_nextblock; /* circular list of blocked processes */ + struct file_lock *fl_prevblock; struct task_struct *fl_owner; struct wait_queue *fl_wait; struct file *fl_file; - char fl_flags; - char fl_type; + unsigned char fl_flags; + unsigned char fl_type; off_t fl_start; off_t fl_end; }; @@ -367,27 +375,25 @@ extern inline int locks_verify_locked(struct inode *inode) { -#ifdef CONFIG_LOCK_MANDATORY /* Candidates for mandatory locking have the setgid bit set * but no group execute bit - an otherwise meaningless combination. */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return (locks_mandatory_locked(inode)); -#endif return (0); } extern inline int locks_verify_area(int read_write, struct inode *inode, struct file *filp, unsigned int offset, unsigned int count) { -#ifdef CONFIG_LOCK_MANDATORY /* Candidates for mandatory locking have the setgid bit set * but no group execute bit - an otherwise meaningless combination. */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return (locks_mandatory_area(read_write, inode, filp, offset, count)); -#endif return (0); } diff -u --recursive --new-file v2.0.30/linux/include/linux/wireless.h linux/include/linux/wireless.h --- v2.0.30/linux/include/linux/wireless.h Thu Mar 6 10:03:51 1997 +++ linux/include/linux/wireless.h Sun Aug 3 15:17:45 1997 @@ -63,20 +63,25 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 4 +#define WIRELESS_EXT 5 /* * Changes : * * V2 to V3 * -------- - * Alan Cox start some imcompatibles changes. I've integrated a bit more. + * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity + * + * V4 to V5 + * -------- + * - Missing encoding definitions in range + * - Access points stuff */ /* -------------------------- IOCTL LIST -------------------------- */ @@ -103,11 +108,16 @@ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ +/* Access Point manipulation */ +#define SIOCSIWAP 0x8B14 /* set access point hardware addresses */ +#define SIOCGIWAP 0x8B15 /* get access point hardware addresses */ +#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ + /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 -#define SIOCIWLAST 0x8B13 +#define SIOCIWLAST 0x8B17 /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) @@ -185,6 +195,17 @@ __u32 misc; /* Others cases */ }; +/* + * Encoding information (setting and so on) + * Encoding might be hardware encryption, scrambing or others + */ +struct iw_encoding +{ + __u8 method; /* Algorithm number / key used */ + __u64 code; /* Data/key used for algorithm */ +}; + + /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) @@ -234,13 +255,11 @@ * 0-1000 = channel * > 1000 = frequency in Hz */ - struct /* Encoding stuff */ - { - __u8 method; /* Algorithm number / off */ - __u64 code; /* Data used for algorithm */ - } encoding; + struct iw_encoding encoding; /* Encoding stuff */ - __u32 sensitivity; /* signal level threshold */ + __u32 sensitivity; /* signal level threshold */ + + struct sockaddr ap_addr; /* Access point address */ struct /* For all data bigger than 16 octets */ { @@ -275,16 +294,16 @@ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ - /* Note : this frequency list doesn't need to fit channel numbers */ - /* Encoder stuff */ - /* signal level threshold range */ __u32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ + + /* Encoder stuff */ + struct iw_encoding max_encoding; /* Encoding max range */ }; /* diff -u --recursive --new-file v2.0.30/linux/init/patches/acer-ess1688-support linux/init/patches/acer-ess1688-support --- v2.0.30/linux/init/patches/acer-ess1688-support Wed Dec 31 16:00:00 1969 +++ linux/init/patches/acer-ess1688-support Sun Aug 3 15:25:08 1997 @@ -0,0 +1 @@ +ESS1688 support for Acer-notebooks (Kurt Huwig ) diff -u --recursive --new-file v2.0.30/linux/kernel/sched.c linux/kernel/sched.c --- v2.0.30/linux/kernel/sched.c Tue Apr 8 08:47:47 1997 +++ linux/kernel/sched.c Sun Aug 3 15:17:16 1997 @@ -1460,8 +1460,9 @@ { cli(); move_last_runqueue(current); - sti(); + current->counter = 0; need_resched = 1; + sti(); return 0; } diff -u --recursive --new-file v2.0.30/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.0.30/linux/kernel/sysctl.c Mon Mar 31 13:22:37 1997 +++ linux/kernel/sysctl.c Sun Aug 3 15:24:20 1997 @@ -201,7 +201,7 @@ do { context = 0; error = parse_table(name, nlen, oldval, oldlenp, - newval, newlen, root_table, &context); + newval, newlen, tmp->clt_table, &context); if (context) kfree(context); if (error != -ENOTDIR) diff -u --recursive --new-file v2.0.30/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c --- v2.0.30/linux/net/appletalk/ddp.c Thu Nov 14 05:20:10 1996 +++ linux/net/appletalk/ddp.c Sun Aug 3 15:30:32 1997 @@ -828,7 +828,7 @@ else { limit=ntohs(nr->nr_lastnet); - if(limit-ntohs(nr->nr_firstnet) > 256) + if(limit-ntohs(nr->nr_firstnet) > 4096) { printk(KERN_WARNING "Too many routes/iface.\n"); return -EINVAL; @@ -1144,6 +1144,7 @@ MOD_INC_USE_COUNT; sk->no_check=0; /* Checksums on by default */ + sk->no_check=1; /* Checksums off by default */ sk->allocation=GFP_KERNEL; sk->rcvbuf=SK_RMEM_MAX; sk->sndbuf=SK_WMEM_MAX; @@ -1623,6 +1624,67 @@ return atalk_rcv(skb,dev,pt); } + +/* + * This is slower, and copies the whole data area + */ + +static struct sk_buff *ddp_skb_copy(struct sk_buff *skb, int priority) +{ + struct sk_buff *n; + unsigned long offset; + + /* + * Allocate the copy buffer + */ + + IS_SKB(skb); + + n=alloc_skb(skb->truesize-sizeof(struct sk_buff),priority); + if(n==NULL) + return NULL; + + /* + * Shift between the two data areas in bytes + */ + + offset=n->head-skb->head; + + /* Set the data pointer */ + skb_reserve(n,skb->data-skb->head); + /* Set the tail pointer and length */ + skb_put(n,skb->len); + /* Copy the bytes */ + memcpy(n->head,skb->head,skb->end-skb->head); + n->link3=NULL; + n->list=NULL; + n->sk=NULL; + n->when=skb->when; + n->dev=skb->dev; + n->h.raw=skb->h.raw+offset; + n->mac.raw=skb->mac.raw+offset; + n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); + n->saddr=skb->saddr; + n->daddr=skb->daddr; + n->raddr=skb->raddr; + n->seq=skb->seq; + n->end_seq=skb->end_seq; + n->ack_seq=skb->ack_seq; + n->acked=skb->acked; + memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); + n->used=skb->used; + n->free=1; + n->arp=skb->arp; + n->tries=0; + n->lock=0; + n->users=0; + n->pkt_type=skb->pkt_type; + n->stamp=skb->stamp; + + IS_SKB(n); + return n; +} + static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags) { atalk_socket *sk=(atalk_socket *)sock->data; @@ -1763,16 +1825,27 @@ { if((!(rt->flags&RTF_GATEWAY))&&(!(dev->flags&IFF_LOOPBACK))) { - struct sk_buff *skb2=skb_clone(skb, GFP_KERNEL); - if(skb2) - { - loopback=1; - if(sk->debug) - printk("SK %p: send out(copy).\n", sk); - if(aarp_send_ddp(dev,skb2,&usat->sat_addr, NULL)==-1) - kfree_skb(skb2, FREE_WRITE); - /* else queued/sent above in the aarp queue */ - } + struct sk_buff *skb2; + + /* Make a copy of the skbuf so that the loopback does not trash it + * in the next block. + * Added by Peter Skarpetis, Serendipity Software 24 June 1997 + */ + skb2 = ddp_skb_copy(skb, GFP_ATOMIC); + if (skb2 == NULL) { + printk("ddp.c: cannot allocate skb copy buffer\n"); + return -1; + } + + if(skb2) + { + loopback=1; + if(sk->debug) + printk("SK %p: send out(copy).\n", sk); + if(aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL)==-1) + kfree_skb(skb2, FREE_WRITE); + /* else queued/sent above in the aarp queue */ + } } } diff -u --recursive --new-file v2.0.30/linux/net/ipv4/arp.c linux/net/ipv4/arp.c --- v2.0.30/linux/net/ipv4/arp.c Tue Apr 8 08:47:47 1997 +++ linux/net/ipv4/arp.c Sun Aug 3 15:27:50 1997 @@ -1922,14 +1922,12 @@ /* * net_alias_dev_rcv_sel32 returns main dev if it fails to found other. */ - if (ip_chk_addr(tip) == IS_MYADDR) { - dev = net_alias_dev_rcv_sel32(dev, AF_INET, sip, tip); + dev = net_alias_dev_rcv_sel32(dev, AF_INET, sip, tip); - if (dev->type != ntohs(arp->ar_hrd) || dev->flags & IFF_NOARP) - { - kfree_skb(skb, FREE_READ); - return 0; - } + if (dev->type != ntohs(arp->ar_hrd) || dev->flags & IFF_NOARP) + { + kfree_skb(skb, FREE_READ); + return 0; } } #endif diff -u --recursive --new-file v2.0.30/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.0.30/linux/net/ipv4/icmp.c Tue Apr 8 08:47:47 1997 +++ linux/net/ipv4/icmp.c Sun Aug 3 15:36:43 1997 @@ -831,8 +831,9 @@ NETDEBUG(printk(KERN_INFO "icmp: ICMP redirect ignored. dest = %lX, " "orig gw = %lX, \"new\" gw = %lX, device = %s.\n", ntohl(ip), ntohl(source), ntohl(icmph->un.gateway), dev->name)); + goto flush_it; } -#else +#endif switch(icmph->code & 7) { case ICMP_REDIR_NET: @@ -870,7 +871,7 @@ default: break; } -#endif + /* * Discard the original packet */ diff -u --recursive --new-file v2.0.30/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.0.30/linux/net/ipv4/ip_fragment.c Fri Nov 22 01:58:34 1996 +++ linux/net/ipv4/ip_fragment.c Sun Aug 3 15:22:52 1997 @@ -388,6 +388,8 @@ fp = fp->next; } + skb->pkt_type = qp->fragments->skb->pkt_type; + skb->protocol = qp->fragments->skb->protocol; /* We glued together all fragments, so remove the queue entry. */ ip_free(qp); @@ -567,7 +569,7 @@ else qp->fragments = tmp->next; - if (tfp->next != NULL) + if (tmp->next != NULL) tmp->next->prev = tmp->prev; next=tfp; /* We have killed the original next frame */ diff -u --recursive --new-file v2.0.30/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.0.30/linux/net/ipv4/ip_fw.c Tue Apr 8 08:47:47 1997 +++ linux/net/ipv4/ip_fw.c Sun Aug 3 15:34:35 1997 @@ -1183,7 +1183,7 @@ ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr), (i->fw_vianame)[0] ? i->fw_vianame : "-", ntohl(i->fw_via.s_addr),i->fw_flg); - len+=sprintf(buffer+len,"%u %u %-9lu %-9lu", + len+=sprintf(buffer+len,"%u %u %-10lu %-10lu", i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt); for (p = 0; p < IP_FW_MAX_PORTS; p++) len+=sprintf(buffer+len, " %u", i->fw_pts[p]); diff -u --recursive --new-file v2.0.30/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c --- v2.0.30/linux/net/ipv4/ip_input.c Tue Apr 8 08:47:47 1997 +++ linux/net/ipv4/ip_input.c Sun Aug 3 15:27:19 1997 @@ -303,8 +303,7 @@ #ifdef CONFIG_NET_ALIAS if (iph->daddr != skb->dev->pa_addr && net_alias_has(skb->dev)) { - if (ip_chk_addr(iph->daddr) == IS_MYADDR) - skb->dev = dev = net_alias_dev_rcv_sel32(skb->dev, AF_INET, iph->saddr, iph->daddr); + skb->dev = dev = net_alias_dev_rcv_sel32(skb->dev, AF_INET, iph->saddr, iph->daddr); } #endif diff -u --recursive --new-file v2.0.30/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c --- v2.0.30/linux/net/ipv4/ipip.c Mon May 13 02:15:24 1996 +++ linux/net/ipv4/ipip.c Sun Aug 3 14:02:55 1997 @@ -60,6 +60,7 @@ * Discard the original IP header */ + skb->mac.raw = skb->data; skb_pull(skb, ((struct iphdr *)skb->data)->ihl<<2); /* diff -u --recursive --new-file v2.0.30/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.0.30/linux/net/ipv4/route.c Tue Apr 8 08:47:47 1997 +++ linux/net/ipv4/route.c Sun Aug 3 15:22:52 1997 @@ -203,6 +203,7 @@ fi->fib_prev->fib_next = fi->fib_next; if (fi == fib_info_list) fib_info_list = fi->fib_next; + kfree_s(fi, sizeof(struct fib_info)); } kfree_s(f, sizeof(struct fib_node)); } @@ -1436,6 +1437,8 @@ ip_rt_unlock(); kfree_s(rth, sizeof(struct rtable)); #ifdef CONFIG_KERNELD + if (MULTICAST(daddr)) + return NULL; daddr=ntohl(daddr); sprintf(wanted_route, "%d.%d.%d.%d", (int)(daddr >> 24) & 0xff, (int)(daddr >> 16) & 0xff, diff -u --recursive --new-file v2.0.30/linux/scripts/Configure linux/scripts/Configure --- v2.0.30/linux/scripts/Configure Tue Apr 8 08:47:48 1997 +++ linux/scripts/Configure Sun Aug 3 15:38:39 1997 @@ -14,7 +14,7 @@ # Menuconfig or xconfig, please notify the respective authors so that # those utilities can be updated in parallel. # -# Menuconfig: +# Menuconfig: # xconfig: # **************************************** # @@ -46,6 +46,9 @@ # 090397 Axel Boldt (boldt@math.ucsb.edu) - avoid ? and + in regular # expressions for GNU expr since version 1.15 and up use \? and \+. +# 040697 Larry Augustin (lma@varesearch.com) - integer expr test +# fails with GNU expr 1.12. Re-write to work with new and old expr. + # # Make sure we're really running bash. # @@ -285,13 +288,20 @@ # int processes an integer argument # # int question define default -# +# GNU expr changed handling of ?. In older versions you need ?, +# in newer you need \? +OLD_EXPR=`expr "0" : '0\?'` +if [ $OLD_EXPR -eq 1 ]; then + INT_EXPR='0$\|-\?[1-9][0-9]*$' +else + INT_EXPR='0$\|-?[1-9][0-9]*$' +fi function int () { old=$(eval echo "\${$2}") def=${old:-$3} while :; do readln "$1 ($2) [$def] " "$def" "$old" - if expr "$ans" : '0$\|\(-[1-9]\|[1-9]\)[0-9]*$' > /dev/null; then + if expr "$ans" : $INT_EXPR > /dev/null; then define_int "$2" "$ans" break else diff -u --recursive --new-file v2.0.30/linux/scripts/Menuconfig linux/scripts/Menuconfig --- v2.0.30/linux/scripts/Menuconfig Tue Oct 29 07:38:17 1996 +++ linux/scripts/Menuconfig Sun Aug 3 15:38:39 1997 @@ -19,17 +19,10 @@ # Portions of this script were borrowed from the original Configure # script. # -# Please send comments / questions / bug fixes to roadcapw@cfw.com +# Please send comments / questions / bug fixes to roadcapw@titus.org # #---------------------------------------------------------------------------- - -# -# Change this to TRUE if you prefer all kernel options listed -# in a single menu rather than the standard menu hierarchy. -# -single_menu_mode= - # # Make sure we're really running bash. # @@ -41,7 +34,12 @@ set -h +o posix - +# +# If you prefer all kernel options listed in a single menu rather than +# the standard menu hierarchy, set SINGLE_MENU_MODE to "TRUE" in your +# environment. +# +single_menu_mode="${SINGLE_MENU_MODE:-FALSE}" # @@ -400,7 +398,8 @@ answer="`cat MCdialog.out`" answer="${answer:-$3}" - if expr $answer : '0$\|-?[1-9][0-9]*$' >/dev/null + # Avoid problems with GNU vs POSIX expr semantics. + if expr "$answer" : '0$\|-[1-9][0-9]*$\|[1-9][0-9]*$' >/dev/null then eval $2="$answer" else @@ -433,7 +432,8 @@ answer="${answer:-$3}" answer="${answer##*[x,X]}" - if expr $answer : '[0-9a-fA-F]+$' >/dev/null + # Avoid problems with GNU vs POSIX expr semantics. + if expr "$answer" : '[0-9a-fA-F][0-9a-fA-F]*$' >/dev/null then eval $2="$answer" else @@ -452,7 +452,7 @@ } # -# Handle a on-of-many choice list. +# Handle a one-of-many choice list. # function l_choice () { # @@ -493,7 +493,7 @@ done # - # Now set the boolean value of each option base on + # Now set the boolean value of each option based on # the selection made from the radiolist. # set -- $choices @@ -579,7 +579,7 @@ if ($1 ~ /mainmenu_option|endmenu/) { printf("") >>menu } - else if ($0 ~ /^#|$MAKE|mainmenu_name/) { + else if ($0 ~ /^#|\$MAKE|mainmenu_name/) { printf("") >>menu } else if ($1 == "source") { @@ -655,7 +655,7 @@ Menuconfig has encountered a possible error in one of the kernel's configuration files and is unable to continue. -Please report this to the author . You may also +Please report this to the author . You may also send a problem report to linux-kernel@vger.rutgers.edu or post a message to the linux.dev.kernel news group. @@ -718,7 +718,7 @@ "make clean all" command. If you have verified that your ncurses install is correct, you may email -the author or post a message on the linux.dev.kernel +the author or post a message on the linux.dev.kernel news group for additional assistance. EOM @@ -746,7 +746,7 @@ while true do - ALT_CONFIG="${ALT_CONFIG:-$DEFAULTS}" + ALT_CONFIG="${ALT_CONFIG:-$_CONFIG}" $DIALOG --backtitle "$backtitle" \ --inputbox "\ @@ -812,6 +812,7 @@ while true do + $DIALOG --backtitle "$backtitle" \ --inputbox "\ Enter a filename to which this configuration should be saved \ @@ -858,20 +859,19 @@ rm -f help.out MCdialog.out } + +# +# Load config file into the environment converting all +# "# OPTION is not set" lines to "OPTION=n". # -# Load config options from a file. -# Converts all "# OPTION is not set" lines to "OPTION=n" lines +# The $ARCH defaults are loaded first so "new"/previously +# unconfigured parameters are assigned the proper defaults. # function load_config_file () { - awk ' - /# .* is not set.*/ { printf("%s=n\n", $2) } - ! /# .* is not set.*/ { print } - ' $1 >.tmpconfig - - source ./.tmpconfig - rm -f .tmpconfig + eval "`sed -e 's/# \(.*\) is not set.*/\1=n/' arch/$ARCH/defconfig $1`" } + # # Just what it says. # @@ -1007,8 +1007,8 @@ fi } - DEF_CONFIG="${1:-.config}" - DEF_CONFIG_H="include/linux/autoconf.h" + DEF_CONFIG="${1:-$_CONFIG}" + DEF_CONFIG_H="$AUTOCONF_H" CONFIG=.tmpconfig CONFIG_H=.tmpconfig.h @@ -1025,7 +1025,11 @@ if . $CONFIG_IN >>.menuconfig.log 2>&1 then - if [ "$DEF_CONFIG" = ".config" ] + # + # Skip these steps if we are saving to an + # alternate configuration file. + # + if [ "$DEF_CONFIG" = "$_CONFIG" ] then # # Create the sound driver's config files for cards @@ -1055,12 +1059,14 @@ fi } + # # Remove temporary files # cleanup () { cleanup1 cleanup2 + stty $S_TERMIO } cleanup1 () { @@ -1093,6 +1099,7 @@ ROWS=$((ROWS-4)) COLS=$((COLS-5)) } +S_TERMIO=`stty -g` set_geometry `stty size 2>/dev/null` @@ -1111,7 +1118,7 @@ Press for additional information about this option." inputbox_instructions_int="\ -Please enter a decimal value between 1 and 9999. \ +Please enter a decimal value. \ Fractions will not be accepted. \ Use the key to move from the input field to the buttons below it." @@ -1119,7 +1126,7 @@ Please enter a hexadecimal value. \ Use the key to move from the input field to the buttons below it." -DIALOG="./scripts/lxdialog/lxdialog" +DIALOG="${DIALOG:-./scripts/lxdialog/lxdialog}" kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}" @@ -1131,29 +1138,28 @@ # # Locate default files. # -CONFIG_IN=./config.in -if [ "$1" != "" ] ; then - CONFIG_IN=$1 -fi +DEFAULTS="arch/$ARCH/defconfig" + +CONFIG_IN="${1:-./config.in}" -DEFAULTS=arch/$ARCH/defconfig -if [ -f .config ]; then - DEFAULTS=.config +_CONFIG="${2:-.config}" + +if [ ! -f "$_CONFIG" ]; then + _CONFIG=$DEFAULTS fi -if [ -f $DEFAULTS ] +AUTOCONF_H="${3:-include/linux/autoconf.h}" + +if [ -f $_CONFIG ] then - echo "#" - echo "# Using defaults found in" $DEFAULTS - echo "#" - load_config_file $DEFAULTS + echo + echo "Using defaults found in" $_CONFIG + load_config_file $_CONFIG else - echo "#" - echo "# No defaults found" - echo "#" + echo + echo "No defaults found" fi - # Fresh new log. >.menuconfig.log @@ -1211,8 +1217,9 @@ then save_configuration - + stty $S_TERMIO clear + cat <. +William Roadcap . diff -u --recursive --new-file v2.0.30/linux/scripts/lxdialog/lxdialog.c linux/scripts/lxdialog/lxdialog.c --- v2.0.30/linux/scripts/lxdialog/lxdialog.c Sun Feb 25 01:17:58 1996 +++ linux/scripts/lxdialog/lxdialog.c Sun Aug 3 15:38:39 1997 @@ -119,7 +119,8 @@ if (modePtr->argmax && argc - offset > modePtr->argmax) Usage (argv[0]); - + if (title && strlen(title) > atoi(argv[offset+4])-4) + title[atoi(argv[offset+4])-4] = 0; init_dialog (); retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);