Commit 45f74d65 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.1.81pre1

I just made a pre-2.1.81 available on ftp.kernel.org.
This fixes the known problems of 2.1.80, and also makes the interrupt
routing by default look like it always used to look - everything goes
through the traditional external 8259A-compatible logic.
The code to handle IO-APIC interrupt routing is still there, but as no
interrupts are actually marked as io-apic interrupts you don't see it in
action yet. The advantage of this is that people who want to work on this
have a base that contains all the logic, and that we only need to figure
out how to reliably make all the IRQ routing decisions.

                Linus
parent 07e15ef7
......@@ -465,11 +465,12 @@ S: 26506 Norden
S: Germany
N: Jeremy Fitzhardinge
E: jeremy@sw.oz.au
E: jeremy@zip.com.au
D: Improved mmap and munmap handling
D: General mm minor tidyups
S: 99 Albermarle Street
S: Newtown 2042
S: 67 Surrey St.
S: Darlinghurst, Sydney
S: NSW 2010
S: Australia
N: Ralf Flaxa
......@@ -705,6 +706,7 @@ S: United Kingdom
N: Ron Holt
E: ron@caldera.com
W: http://www.holt.org/
P: 1024/1FD44539 DF 4B EB 9F 5B 68 38 9A 40 E3 FB 71 D1 C8 0B 56
D: Kernel development
D: Minor kernel modifications to support Wabi and Wine
S: Caldera, Inc.
......@@ -820,9 +822,11 @@ S: Germany
N: Ian Kluft
E: ikluft@thunder.sbay.org
D: Smail binary packages for Slackware and Debian
S: 2200 Monroe Street #1509
S: Santa Clara, California 95050-3452
W: http://www.kluft.com/~ikluft/
D: NET-1 beta testing & minor patches, original Smail binary packages for
D: Slackware and Debian, vote-taker for 2nd comp.os.linux reorganization
S: PO Box 611311
S: San Jose, CA 95161-1311
S: USA
N: Alain L. Knaff
......@@ -977,6 +981,14 @@ S: 33 Ridgefield Cr
S: Nepean, Ontario
S: Canada K2H 6S3
N: Jamie Lokier
E: jamie@imbolc.ucc.ie
D: Reboot-through-BIOS for broken 486 motherboards
S: 26 Oatlands Road
S: Oxford
S: OX2 0ET
S: United Kingdom
N: Warner Losh
E: imp@village.org
D: Linux/MIPS Deskstation support, Provided OI/OB for Linux
......@@ -1146,6 +1158,7 @@ S: USA
N: Rick Miller
E: rdmiller@execpc.com
W: http://www.execpc.com/~rdmiller/
D: Original Linux Device Registrar (Major/minor numbers)
D: au-play, bwBASIC
S: S78 W16203 Woods Road
......@@ -1309,8 +1322,12 @@ E: Frederic.Potter@masi.ibp.fr
D: Some PCI kernel support
N: Stefan Probst
E: snprobst@immd4.informatik.uni-erlangen.de
D: The Linux Support Team Erlangen
E: sp@caldera.de
D: The Linux Support Team Erlangen, 1993-97
S: Caldera (Deutschland) GmbH
S: Lazarettstrasse 8
S: 91054 Erlangen
S: Germany
N: Daniel Quinlan
E: quinlan@pathname.com
......@@ -1652,6 +1669,14 @@ S: Obere Heerbergstrasse 17
S: 97078 Wuerzburg
S: Germany
N: Greg Ungerer
E: gerg@stallion.com
D: Author of Stallion multiport serial drivers
S: Stallion Technologies
S: 33 Woodstock Rd
S: Toowong, QLD. 4066
S: Australia
N: Jeffrey A. Uphoff
E: juphoff@nrao.edu
E: jeff.uphoff@linux.org
......
Smbfs is a filesystem that implements the SMB protocol, which is the
protocol used by Windows for Workgroups, Windows 95 and Windows NT.
Smbfs was inspired by samba, the program written by Andrew Tridgell
Smbfs was inspired by Samba, the program written by Andrew Tridgell
that turns any unix host into a file server for DOS or Windows clients.
See ftp://nimbus.anu.edu.au/pub/tridge/samba/ for this interesting
program suite and much more information on SMB, NetBIOS over TCP/IP,
and explanations for concepts like netbios name or share.
To use smbfs, you need to install the Samba package (Samba-1.9.17p1 or
later), and you need the special mount program from the smbfs package
(smbfs-2.1.0 or later), found on
To use smbfs, you must first install the Samba package (Samba-1.9.18p1 or
later). This package includes the special smbmount utility needed to mount
smbfs volumes. Refer to the smbmount(8) and smbmnt(8) manpages for the
details regarding smbfs mounts.
ftp://ftp.gwdg.de/pub/linux/misc/smbfs/dontuse
After downloading the smbfs package, apply the patch to the smbclient
program and recompile. Smbfs can then be mounted from the smbclient
command line, as for example:
smb: \>mount /mnt/tmp -f 755
For convenience, you may wish to package the command in a script like this:
#!/bin/sh
echo "mount /mnt/tmp -f 755" | smbclient //server/c$ -U administrator%
The smbmount utility reads the Samba smb.conf config file for some of its
options, and at least one of these is important for smbfs operation. You
should enable the TCP_NODELAY socket option, or else directory listings
will be dramatically slower (under Win NT at least).
Mount-Time Options
Windows 95 has several bugs that affect SMB operations, and smbfs includes
......@@ -37,11 +30,12 @@ to the file mode argument of the mount command for the Win 95 servers.
Option Value Effect
Identify Win 95 Server 1 Enables bug fixes
Use Core Attributes 2 Speeds up directory scans, only mtime
Use Dir Attributes 4 Alternate way to get file attributes
To apply the options, sum the values and prepend it to the file mode. For
example, to use both options with file mode 755, you would prepend 3 to 755:
example, to use options 1 and 2 with file mode 755, you would specify 3755:
cnt>mount /mnt/tmp -f 3755
mount /mnt/tmp -f 3755
Smbfs will print a message at mount time confirming the selected options.
Note that _only_ Windows 95 servers require special treatment; using the
......
......@@ -343,14 +343,17 @@ endif
clean: archclean
rm -f kernel/ksyms.lst include/linux/compile.h
rm -f `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' -print`
rm -f `find . -type f -name 'core' -print`
rm -f `find . -name '.*.flags' -print`
rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' -print`
rm -f core `find . -type f -name 'core' -print`
rm -f core `find . -name '.*.flags' -print`
rm -f core `find . -size 0`
rm -f vmlinux System.map
rm -f .tmp*
rm -f drivers/char/consolemap_deftbl.c drivers/char/conmakehash
rm -f drivers/sound/bin2hex drivers/sound/hex2hex
rm -f `find modules/ -type f -print`
if [ -d modules ]; then \
rm -f core `find modules/ -type f -print`; \
fi
rm -f submenu*
mrproper: clean
......
......@@ -120,15 +120,16 @@ static int irq_owner [NR_IRQS] = { NO_PROC_ID, };
#ifndef __SMP__
static const unsigned int io_apic_irqs = 0;
#else
/*
* the timer interrupt is not connected to the IO-APIC on all boards
* (mine is such ;), and since it is not performance critical anyway,
* we route it through the INTA pin and win lots of design simplicity.
* Ditto the obsolete EISA dma chaining irq. All other interrupts are
* routed through the IO-APIC, distributed amongst all CPUs, dependent
* on irq traffic and CPU load.
*/
const unsigned int io_apic_irqs = ~((1<<0)|(1<<2)|(1<<13));
/*
* Default to all normal IRQ's _not_ using the IO APIC.
*
* To get IO-APIC interrupts you should either:
* - turn some of them into IO-APIC interrupts at runtime
* with some magic system call interface.
* - explicitly use irq 16-19 depending on which PCI irq
* line your PCI controller uses.
*/
unsigned int io_apic_irqs = 0xFF0000;
#endif
static inline int ack_irq(int irq)
......@@ -179,14 +180,16 @@ static inline int ack_irq(int irq)
void set_8259A_irq_mask(int irq)
{
if (irq >= 16) {
printk ("HUH #3 (%d)?\n", irq);
return;
}
if (irq & 8) {
outb(cached_A1,0xA1);
} else {
outb(cached_21,0x21);
/*
* (it might happen that we see IRQ>15 on a UP box, with SMP
* emulation)
*/
if (irq < 16) {
if (irq & 8) {
outb(cached_A1,0xA1);
} else {
outb(cached_21,0x21);
}
}
}
......@@ -356,12 +359,13 @@ int get_irq_list(char *buf)
continue;
p += sprintf(p, "%3d: ",i);
#ifndef __SMP__
p += sprintf(p, "%10u ", kstat.interrupts[0][i]);
p += sprintf(p, "%10u ", kstat_irqs(i));
#else
for (j=0; j<smp_num_cpus; j++)
p += sprintf(p, "%10u ",
kstat.interrupts[cpu_logical_map[j]][i]);
kstat.irqs[cpu_logical_map(j)][i]);
#endif
if (IO_APIC_IRQ(i))
p += sprintf(p, " IO-APIC ");
else
......@@ -596,15 +600,13 @@ static void handle_IRQ_event(int irq, struct pt_regs * regs)
while (test_bit(0,&global_irq_lock)) mb();
#endif
kstat.interrupts[cpu][irq]++;
kstat.irqs[cpu][irq]++;
status = 0;
action = *(irq + irq_action);
if (action) {
#if 0
if (!(action->flags & SA_INTERRUPT))
__sti();
#endif
do {
status |= action->flags;
......@@ -897,7 +899,7 @@ unsigned long probe_irq_on (void)
/*
* save current irq counts
*/
memcpy(probe_irqs,kstat.interrupts,NR_CPUS*NR_IRQS*sizeof(int));
memcpy(probe_irqs,kstat.irqs,NR_CPUS*NR_IRQS*sizeof(int));
/*
* first, enable any unassigned irqs
......@@ -922,7 +924,7 @@ unsigned long probe_irq_on (void)
*/
for (i=0; i<NR_IRQS; i++)
for (j=0; j<NR_CPUS; j++)
if (kstat.interrupts[j][i] != probe_irqs[j][i])
if (kstat.irqs[j][i] != probe_irqs[j][i])
irqs &= ~(i<<1);
return irqs;
......@@ -935,7 +937,7 @@ int probe_irq_off (unsigned long irqs)
for (i=0; i<NR_IRQS; i++) {
int sum = 0;
for (j=0; j<NR_CPUS; j++) {
sum += kstat.interrupts[j][i];
sum += kstat.irqs[j][i];
sum -= probe_irqs[j][i];
}
if (sum && (irqs & (i<<1))) {
......
......@@ -19,7 +19,12 @@ void ack_APIC_irq (void);
void setup_IO_APIC (void);
void init_IO_APIC_traps(void);
extern const unsigned int io_apic_irqs;
#ifdef __SMP__
extern unsigned int io_apic_irqs;
#else
extern const unsigned int io_apic_irqs;
#endif
#define IO_APIC_IRQ(x) ((1<<x) & io_apic_irqs)
#define MAX_IRQ_SOURCES 128
......
......@@ -115,7 +115,7 @@ unsigned long cpu_present_map = 0; /* Bitmask of existing CPU's */
int smp_num_cpus = 1; /* Total count of live CPU's */
int smp_threads_ready=0; /* Set when the idlers are all forked */
volatile int cpu_number_map[NR_CPUS]; /* which CPU maps to which logical number */
volatile int cpu_logical_map[NR_CPUS]; /* which logical number maps to which CPU */
volatile int __cpu_logical_map[NR_CPUS]; /* which logical number maps to which CPU */
volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; /* We always use 0 the rest is ready for parallel delivery */
volatile unsigned long smp_invalidate_needed; /* Used for the invalidate map that's also checked in the spinlock */
volatile unsigned long kstack_ptr; /* Stack vector for booting CPU's */
......@@ -526,7 +526,7 @@ __initfunc(int smp_scan_config(unsigned long base, unsigned long length))
* set some other information about it.
*/
nlong = boot_cpu_id<<24; /* Dummy 'self' for bootup */
cpu_logical_map[0] = boot_cpu_id;
__cpu_logical_map[0] = boot_cpu_id;
global_irq_holder = boot_cpu_id;
current->processor = boot_cpu_id;
......@@ -717,7 +717,7 @@ __initfunc(static void do_boot_cpu(int i))
panic("No idle process for CPU %d", i);
idle->processor = i;
cpu_logical_map[cpucount] = i;
__cpu_logical_map[cpucount] = i;
cpu_number_map[i] = cpucount;
/* start_eip had better be page-aligned! */
......@@ -861,7 +861,7 @@ __initfunc(static void do_boot_cpu(int i))
/* number CPUs logically, starting from 1 (BSP is 0) */
#if 0
cpu_number_map[i] = cpucount;
cpu_logical_map[cpucount] = i;
__cpu_logical_map[cpucount] = i;
#endif
printk("OK.\n");
printk("CPU%d: ", i);
......@@ -927,6 +927,7 @@ __initfunc(void smp_boot_cpus(void))
if (!smp_found_config)
{
printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
io_apic_irqs = 0;
return;
}
......@@ -1087,6 +1088,12 @@ __initfunc(void smp_boot_cpus(void))
if(smp_b_stepping)
printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
SMP_PRINTK(("Boot done.\n"));
/*
* Here we can be sure that there is an IO-APIC in the system, lets
* go and set it up:
*/
setup_IO_APIC();
}
/*
......
......@@ -25,8 +25,8 @@
*/
/*****************************************************************************/
#include <linux/hfmodem.h>
/* This is compiled with HOSTCC - do not include any <linux/foo.h> headers. */
#include <math.h>
#include <stdio.h>
......
......@@ -603,7 +603,7 @@ static void do_fn(unsigned char value, char up_flag)
static void do_pad(unsigned char value, char up_flag)
{
static const char *pad_chars = "0123456789+-*/\015,.?()";
static const char *app_map = "pqrstuvwxylSRQMnn?PQ";
static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
if (up_flag)
return; /* no action, if this is a key release */
......
......@@ -2338,15 +2338,11 @@ static boolean BusLogic_TestInterrupts(BusLogic_HostAdapter_T *HostAdapter)
Issue the Test Command Complete Interrupt commands.
*/
InitialInterruptCount = 0;
for (i=0; i<NR_CPUS; i++)
InitialInterruptCount += kstat.interrupts[i][HostAdapter->IRQ_Channel];
InitialInterruptCount = kstat_irqs(HostAdapter->IRQ_Channel);
for (i = 0; i < TestCount; i++)
BusLogic_Command(HostAdapter, BusLogic_TestCommandCompleteInterrupt,
NULL, 0, NULL, 0);
FinalInterruptCount = 0;
for (i=0; i<NR_CPUS; i++)
FinalInterruptCount += kstat.interrupts[i][HostAdapter->IRQ_Channel];
FinalInterruptCount = kstat_irqs(HostAdapter->IRQ_Channel);
/*
Verify that BusLogic_InterruptHandler was called at least TestCount
times. Shared IRQ Channels could cause more than TestCount interrupts to
......
......@@ -12,9 +12,9 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/locks.h>
......@@ -24,6 +24,8 @@
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/minix_fs.h>
static void minix_delete_inode(struct inode *inode)
{
inode->i_size = 0;
......@@ -62,12 +64,13 @@ void minix_put_super(struct super_block *sb)
sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
}
sb->s_dev = 0;
for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
brelse(sb->u.minix_sb.s_imap[i]);
for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++)
brelse(sb->u.minix_sb.s_zmap[i]);
brelse (sb->u.minix_sb.s_sbh);
kfree(sb->u.minix_sb.s_imap);
sb->s_dev = 0;
unlock_super(sb);
MOD_DEC_USE_COUNT;
return;
......@@ -161,30 +164,29 @@ static const char * minix_checkroot(struct super_block *s, struct inode *dir)
return errmsg;
}
struct super_block *minix_read_super(struct super_block *s,void *data,
struct super_block *minix_read_super(struct super_block *s, void *data,
int silent)
{
struct buffer_head *bh;
struct buffer_head **map;
struct minix_super_block *ms;
int i, block;
kdev_t dev = s->s_dev;
const char * errmsg;
struct inode *root_inode;
/* N.B. These should be compile-time tests */
if (32 != sizeof (struct minix_inode))
panic("bad V1 i-node size");
if (64 != sizeof(struct minix2_inode))
panic("bad V2 i-node size");
MOD_INC_USE_COUNT;
lock_super(s);
set_blocksize(dev, BLOCK_SIZE);
if (!(bh = bread(dev,1,BLOCK_SIZE))) {
s->s_dev = 0;
unlock_super(s);
printk("MINIX-fs: unable to read superblock\n");
MOD_DEC_USE_COUNT;
return NULL;
}
if (!(bh = bread(dev,1,BLOCK_SIZE)))
goto out_bad_sb;
ms = (struct minix_super_block *) bh->b_data;
s->u.minix_sb.s_ms = ms;
s->u.minix_sb.s_sbh = bh;
......@@ -192,6 +194,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->u.minix_sb.s_ninodes = ms->s_ninodes;
s->u.minix_sb.s_nzones = ms->s_nzones;
s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks;
s->u.minix_sb.s_zmap_blocks = ms->s_zmap_blocks;
s->u.minix_sb.s_firstdatazone = ms->s_firstdatazone;
......@@ -200,103 +203,74 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
s->s_magic = ms->s_magic;
if (s->s_magic == MINIX_SUPER_MAGIC) {
s->u.minix_sb.s_version = MINIX_V1;
s->u.minix_sb.s_nzones = ms->s_nzones;
s->u.minix_sb.s_dirsize = 16;
s->u.minix_sb.s_namelen = 14;
} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
s->u.minix_sb.s_version = MINIX_V1;
s->u.minix_sb.s_nzones = ms->s_nzones;
s->u.minix_sb.s_dirsize = 32;
s->u.minix_sb.s_namelen = 30;
} else if (s->s_magic == MINIX2_SUPER_MAGIC) {
s->u.minix_sb.s_version = MINIX_V2;
s->u.minix_sb.s_nzones = ms->s_zones;
s->u.minix_sb.s_dirsize = 16;
s->u.minix_sb.s_namelen = 14;
} else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
s->u.minix_sb.s_version = MINIX_V2;
s->u.minix_sb.s_nzones = ms->s_zones;
s->u.minix_sb.s_dirsize = 32;
s->u.minix_sb.s_namelen = 30;
} else {
s->s_dev = 0;
unlock_super(s);
brelse(bh);
if (!silent)
printk("VFS: Can't find a minix or minix V2 filesystem on dev "
"%s.\n", kdevname(dev));
MOD_DEC_USE_COUNT;
return NULL;
}
for (i=0;i < MINIX_I_MAP_SLOTS;i++)
s->u.minix_sb.s_imap[i] = NULL;
for (i=0;i < MINIX_Z_MAP_SLOTS;i++)
s->u.minix_sb.s_zmap[i] = NULL;
if (s->u.minix_sb.s_zmap_blocks > MINIX_Z_MAP_SLOTS) {
s->s_dev = 0;
unlock_super (s);
brelse (bh);
if (!silent)
printk ("MINIX-fs: filesystem too big\n");
MOD_DEC_USE_COUNT;
return NULL;
}
} else
goto out_no_fs;
if (s->u.minix_sb.s_zmap_blocks > MINIX_Z_MAP_SLOTS)
goto out_too_big;
/*
* Allocate the buffer map to keep the superblock small.
*/
i = (MINIX_I_MAP_SLOTS + MINIX_Z_MAP_SLOTS) * sizeof(bh);
map = kmalloc(i, GFP_KERNEL);
if (!map)
goto out_no_map;
memset(map, 0, i);
s->u.minix_sb.s_imap = &map[0];
s->u.minix_sb.s_zmap = &map[MINIX_I_MAP_SLOTS];
block=2;
for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
if ((s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
block++;
else
break;
for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++)
if ((s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
block++;
else
break;
if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) {
for(i=0;i<MINIX_I_MAP_SLOTS;i++)
brelse(s->u.minix_sb.s_imap[i]);
for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
brelse(s->u.minix_sb.s_zmap[i]);
s->s_dev = 0;
unlock_super(s);
brelse(bh);
printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
MOD_DEC_USE_COUNT;
return NULL;
for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++) {
if (!(s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)))
goto out_no_bitmap;
block++;
}
for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++) {
if (!(s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)))
goto out_no_bitmap;
block++;
}
if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks)
goto out_no_bitmap;
minix_set_bit(0,s->u.minix_sb.s_imap[0]->b_data);
minix_set_bit(0,s->u.minix_sb.s_zmap[0]->b_data);
unlock_super(s);
/* set up enough so that it can read an inode */
s->s_dev = dev;
s->s_op = &minix_sops;
root_inode = iget(s,MINIX_ROOT_INO);
s->s_root = d_alloc_root(root_inode, NULL);
if (!s->s_root) {
s->s_dev = 0;
brelse(bh);
if (!silent)
printk("MINIX-fs: get root inode failed\n");
MOD_DEC_USE_COUNT;
return NULL;
}
root_inode = iget(s, MINIX_ROOT_INO);
if (!root_inode)
goto out_no_root;
/*
* Check the fs before we get the root dentry ...
*/
errmsg = minix_checkroot(s, root_inode);
if (errmsg) {
if (!silent)
printk("MINIX-fs: %s\n", errmsg);
d_delete(s->s_root); /* XXX Is this enough? */
s->s_dev = 0;
brelse (bh);
MOD_DEC_USE_COUNT;
return NULL;
}
if (errmsg)
goto out_bad_root;
s->s_root = d_alloc_root(root_inode, NULL);
if (!s->s_root)
goto out_iput;
if (!(s->s_flags & MS_RDONLY)) {
ms->s_state &= ~MINIX_VALID_FS;
mark_buffer_dirty(bh, 1);
s->s_dirt = 1;
}
unlock_super(s);
if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
printk ("MINIX-fs: mounting unchecked file system, "
"running fsck is recommended.\n");
......@@ -304,6 +278,54 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
printk ("MINIX-fs: mounting file system with errors, "
"running fsck is recommended.\n");
return s;
out_bad_root:
if (!silent)
printk("MINIX-fs: %s\n", errmsg);
out_iput:
iput(root_inode);
goto out_freemap;
out_no_root:
if (!silent)
printk("MINIX-fs: get root inode failed\n");
goto out_freemap;
out_no_bitmap:
printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
out_freemap:
for(i=0;i<MINIX_I_MAP_SLOTS;i++)
brelse(s->u.minix_sb.s_imap[i]);
for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
brelse(s->u.minix_sb.s_zmap[i]);
kfree(s->u.minix_sb.s_imap);
goto out_release;
out_no_map:
if (!silent)
printk ("MINIX-fs: can't allocate map\n");
goto out_release;
out_too_big:
if (!silent)
printk ("MINIX-fs: filesystem too big\n");
goto out_release;
out_no_fs:
if (!silent)
printk("VFS: Can't find a minix or minix V2 filesystem on dev "
"%s.\n", kdevname(dev));
out_release:
brelse(bh);
goto out_unlock;
out_bad_sb:
printk("MINIX-fs: unable to read superblock\n");
out_unlock:
s->s_dev = 0;
unlock_super(s);
MOD_DEC_USE_COUNT;
return NULL;
}
int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
......
......@@ -221,20 +221,14 @@ static int get_loadavg(char * buffer)
static int get_kstat(char * buffer)
{
int i, j, len;
int i, len;
unsigned sum = 0;
extern unsigned long total_forks;
unsigned long ticks;
ticks = jiffies * smp_num_cpus;
#ifndef __SMP__
for (i = 0 ; i < NR_IRQS ; i++)
sum += kstat.interrupts[0][i];
#else
for (j = 0 ; j < smp_num_cpus ; j++)
for (i = 0 ; i < NR_IRQS ; i++)
sum += kstat.interrupts[cpu_logical_map[j]][i];
#endif
sum += kstat_irqs(i);
#ifdef __SMP__
len = sprintf(buffer,
......@@ -246,12 +240,12 @@ static int get_kstat(char * buffer)
for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(buffer + len, "cpu%d %u %u %u %lu\n",
i,
kstat.per_cpu_user[cpu_logical_map[i]],
kstat.per_cpu_nice[cpu_logical_map[i]],
kstat.per_cpu_system[cpu_logical_map[i]],
jiffies - ( kstat.per_cpu_user[cpu_logical_map[i]] \
+ kstat.per_cpu_nice[cpu_logical_map[i]] \
+ kstat.per_cpu_system[cpu_logical_map[i]]));
kstat.per_cpu_user[cpu_logical_map(i)],
kstat.per_cpu_nice[cpu_logical_map(i)],
kstat.per_cpu_system[cpu_logical_map(i)],
jiffies - ( kstat.per_cpu_user[cpu_logical_map(i)] \
+ kstat.per_cpu_nice[cpu_logical_map(i)] \
+ kstat.per_cpu_system[cpu_logical_map(i)]));
len += sprintf(buffer + len,
"disk %u %u %u %u\n"
"disk_rio %u %u %u %u\n"
......@@ -292,17 +286,8 @@ static int get_kstat(char * buffer)
kstat.pswpin,
kstat.pswpout,
sum);
for (i = 0 ; i < NR_IRQS ; i++) {
#ifndef __SMP__
len += sprintf(buffer + len, " %u", kstat.interrupts[0][i]);
#else
int sum=0;
for (j = 0 ; j < smp_num_cpus ; j++)
sum += kstat.interrupts[cpu_logical_map[j]][i];
len += sprintf(buffer + len, " %u", sum);
#endif
}
for (i = 0 ; i < NR_IRQS ; i++)
len += sprintf(buffer + len, " %u", kstat_irqs(i));
len += sprintf(buffer + len,
"\nctxt %u\n"
"btime %lu\n"
......@@ -1147,8 +1132,8 @@ static int get_pidcpu(int pid, char * buffer)
for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(buffer + len, "cpu%d %lu %lu\n",
i,
tsk->per_cpu_utime[cpu_logical_map[i]],
tsk->per_cpu_stime[cpu_logical_map[i]]);
tsk->per_cpu_utime[cpu_logical_map(i)],
tsk->per_cpu_stime[cpu_logical_map(i)]);
return len;
}
......
......@@ -351,8 +351,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, error);
inode = smb_iget(dir->i_sb, &finfo);
if (inode)
{
/* cache the dentry pointer */
inode->u.smbfs_i.dentry = dentry;
add_entry:
dentry->d_op = &smbfs_dentry_operations;
d_add(dentry, inode);
......@@ -372,8 +370,8 @@ smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
{
struct smb_sb_info *server = server_from_dentry(dentry);
struct inode *inode;
struct smb_fattr fattr;
int error;
struct smb_fattr fattr;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_instantiate: file %s/%s, fileid=%u\n",
......@@ -395,8 +393,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, fileid);
inode->u.smbfs_i.access = SMB_O_RDWR;
inode->u.smbfs_i.open = server->generation;
}
/* cache the dentry pointer */
inode->u.smbfs_i.dentry = dentry;
d_instantiate(dentry, inode);
out:
return error;
......
......@@ -54,10 +54,9 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
static int
smb_readpage_sync(struct dentry *dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
char *buffer = (char *) page_address(page);
unsigned long offset = page->offset;
int rsize = smb_get_rsize(SMB_SERVER(inode));
int rsize = smb_get_rsize(server_from_dentry(dentry));
int count = PAGE_SIZE;
int result;
......@@ -81,14 +80,14 @@ dentry->d_parent->d_name.name, dentry->d_name.name, result);
if (count < rsize)
rsize = count;
result = smb_proc_read(inode, offset, rsize, buffer);
result = smb_proc_read(dentry, offset, rsize, buffer);
if (result < 0)
goto io_error;
count -= result;
offset += result;
buffer += result;
inode->i_atime = CURRENT_TIME;
dentry->d_inode->i_atime = CURRENT_TIME;
if (result < rsize)
break;
} while (count);
......@@ -129,7 +128,7 @@ smb_writepage_sync(struct dentry *dentry, struct page *page,
{
struct inode *inode = dentry->d_inode;
u8 *buffer = (u8 *) page_address(page) + offset;
int wsize = smb_get_wsize(SMB_SERVER(inode));
int wsize = smb_get_wsize(server_from_dentry(dentry));
int result, written = 0;
offset += page->offset;
......@@ -142,7 +141,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
if (count < wsize)
wsize = count;
result = smb_proc_write(inode, offset, wsize, buffer);
result = smb_proc_write(dentry, offset, wsize, buffer);
if (result < 0)
goto io_error;
/* N.B. what if result < wsize?? */
......
......@@ -180,6 +180,59 @@ printk("smb_invalidate_inodes\n");
invalidate_inodes(SB_of(server));
}
/*
* This is called to update the inode attributes after
* we've made changes to a file or directory.
*/
static int
smb_refresh_inode(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
int error;
struct smb_fattr fattr;
error = smb_proc_getattr(dentry, &fattr);
if (!error)
{
smb_renew_times(dentry);
/*
* Check whether the type part of the mode changed,
* and don't update the attributes if it did.
*/
if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT))
smb_set_inode_attr(inode, &fattr);
else
{
/*
* Big trouble! The inode has become a new object,
* so any operations attempted on it are invalid.
*
* To limit damage, mark the inode as bad so that
* subsequent lookup validations will fail.
*/
#ifdef SMBFS_PARANOIA
printk("smb_refresh_inode: %s/%s changed mode, %07o to %07o\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_mode, fattr.f_mode);
#endif
fattr.f_mode = inode->i_mode; /* save mode */
make_bad_inode(inode);
inode->i_mode = fattr.f_mode; /* restore mode */
/*
* No need to worry about unhashing the dentry: the
* lookup validation will see that the inode is bad.
* But we do want to invalidate the caches ...
*/
if (!S_ISDIR(inode->i_mode))
invalidate_inode_pages(inode);
else
smb_invalid_dir_cache(inode);
error = -EIO;
}
}
return error;
}
/*
* This is called when we want to check whether the inode
* has changed on the server. If it has changed, we must
......@@ -220,7 +273,7 @@ jiffies, inode->u.smbfs_i.oldmtime);
* (Note: a size change should have a different mtime.)
*/
last_time = inode->i_mtime;
error = smb_refresh_inode(inode);
error = smb_refresh_inode(dentry);
if (error || inode->i_mtime != last_time)
{
#ifdef SMBFS_DEBUG_VERBOSE
......@@ -238,99 +291,15 @@ dentry->d_parent->d_name.name, dentry->d_name.name,
}
/*
* This is called to update the inode attributes after
* we've made changes to a file or directory.
*/
int
smb_refresh_inode(struct inode *inode)
{
struct dentry * dentry = inode->u.smbfs_i.dentry;
struct smb_fattr fattr;
int error;
pr_debug("smb_refresh_inode\n");
if (!dentry)
{
printk("smb_refresh_inode: no dentry, can't refresh\n");
error = -EIO;
goto out;
}
error = smb_proc_getattr(dentry, &fattr);
if (!error)
{
smb_renew_times(dentry);
/*
* Check whether the type part of the mode changed,
* and don't update the attributes if it did.
*/
if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT))
smb_set_inode_attr(inode, &fattr);
else
{
/*
* Big trouble! The inode has become a new object,
* so any operations attempted on it are invalid.
*
* To limit damage, mark the inode as bad so that
* subsequent lookup validations will fail.
*/
#ifdef SMBFS_PARANOIA
printk("smb_refresh_inode: %s/%s changed mode, %07o to %07o\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_mode, fattr.f_mode);
#endif
fattr.f_mode = inode->i_mode; /* save mode */
make_bad_inode(inode);
inode->i_mode = fattr.f_mode; /* restore mode */
/*
* No need to worry about unhashing the dentry: the
* lookup validation will see that the inode is bad.
* But we do want to invalidate the caches ...
*/
if (!S_ISDIR(inode->i_mode))
invalidate_inode_pages(inode);
else
smb_invalid_dir_cache(inode);
error = -EIO;
}
}
out:
return error;
}
/*
* This routine is called for every iput().
* This routine is called for every iput(). We clear i_nlink
* on the last use to force a call to delete_inode.
*/
static void
smb_put_inode(struct inode *ino)
{
pr_debug("smb_put_inode: count = %d\n", ino->i_count);
if (ino->i_count > 1) {
struct dentry * dentry;
/*
* Check whether the dentry still holds this inode.
* This looks scary, but should work ... if this is
* the last use, d_inode == NULL or d_count == 0.
*/
dentry = (struct dentry *) ino->u.smbfs_i.dentry;
if (dentry && (dentry->d_inode != ino || dentry->d_count == 0))
{
ino->u.smbfs_i.dentry = NULL;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_put_inode: cleared dentry for %s/%s (%ld), count=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, ino->i_ino, ino->i_count);
#endif
}
} else {
/*
* Last use ... clear i_nlink to force
* smb_delete_inode to be called.
*/
if (ino->i_count == 1)
ino->i_nlink = 0;
}
}
/*
......@@ -379,7 +348,6 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
{
struct smb_mount_data *mnt;
struct inode *root_inode;
struct dentry *dentry;
struct smb_fattr root;
MOD_INC_USE_COUNT;
......@@ -435,6 +403,8 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
printk("SMBFS: Win 95 bug fixes enabled\n");
if (mnt->version & SMB_FIX_OLDATTR)
printk("SMBFS: Using core getattr (Win 95 speedup)\n");
else if (mnt->version & SMB_FIX_DIRATTR)
printk("SMBFS: Using dir ff getattr\n");
/*
* Keep the super block locked while we get the root inode.
......@@ -444,11 +414,9 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
if (!root_inode)
goto out_no_root;
dentry = d_alloc_root(root_inode, NULL);
if (!dentry)
sb->s_root = d_alloc_root(root_inode, NULL);
if (!sb->s_root)
goto out_no_root;
root_inode->u.smbfs_i.dentry = dentry;
sb->s_root = dentry;
unlock_super(sb);
return sb;
......@@ -465,7 +433,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
unlock_super(sb);
goto out_fail;
out_wrong_data:
printk("smb_read_super: need mount version %d\n", SMB_MOUNT_VERSION);
printk(KERN_ERR "SMBFS: need mount version %d\n", SMB_MOUNT_VERSION);
goto out_fail;
out_no_data:
printk("smb_read_super: missing data argument\n");
......@@ -609,7 +577,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, fattr.f_mode,attr->ia_mode);
out:
if (refresh)
smb_refresh_inode(inode);
smb_refresh_inode(dentry);
return error;
}
......
......@@ -531,7 +531,8 @@ server->conn_pid);
if (server->state == CONN_VALID)
{
#ifdef SMBFS_PARANOIA
printk("smb_retry: new connection pid=%d\n", server->conn_pid);
printk("smb_retry: new pid=%d, generation=%d\n",
server->conn_pid, server->generation);
#endif
result = 1;
}
......@@ -643,25 +644,17 @@ printk("smb_newconn: fd=%d, pid=%d\n", opt->fd, current->pid);
}
server->conn_pid = current->pid;
#ifdef SMBFS_PARANOIA
if (server->sock_file)
printk("smb_newconn: old socket not closed!\n");
#endif
filp->f_count += 1;
server->sock_file = filp;
smb_catch_keepalive(server);
server->opt = *opt;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_newconn: protocol=%d, max_xmit=%d\n",
server->opt.protocol, server->opt.max_xmit);
#endif
server->generation += 1;
server->state = CONN_VALID;
#ifdef SMBFS_PARANOIA
printk("smb_newconn: state valid, pid=%d\n", server->conn_pid);
#endif
error = 0;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_newconn: protocol=%d, max_xmit=%d, pid=%d\n",
server->opt.protocol, server->opt.max_xmit, server->conn_pid);
#endif
out:
wake_up_interruptible(&server->wait);
......@@ -987,9 +980,9 @@ smb_close_fileid(struct dentry *dentry, __u16 fileid)
file-id would not be valid after a reconnection. */
int
smb_proc_read(struct inode *ino, off_t offset, int count, char *data)
smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data)
{
struct smb_sb_info *server = SMB_SERVER(ino);
struct smb_sb_info *server = server_from_dentry(dentry);
__u16 returned_count, data_len;
char *buf;
int result;
......@@ -997,7 +990,7 @@ smb_proc_read(struct inode *ino, off_t offset, int count, char *data)
smb_lock_server(server);
smb_setup_header(server, SMBread, 5, 0);
buf = server->packet;
WSET(buf, smb_vwv0, ino->u.smbfs_i.fileid);
WSET(buf, smb_vwv0, dentry->d_inode->u.smbfs_i.fileid);
WSET(buf, smb_vwv1, count);
DSET(buf, smb_vwv2, offset);
WSET(buf, smb_vwv4, 0);
......@@ -1022,29 +1015,27 @@ smb_proc_read(struct inode *ino, off_t offset, int count, char *data)
out:
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_proc_read: file %s/%s, count=%d, result=%d\n",
((struct dentry *) ino->u.smbfs_i.dentry)->d_parent->d_name.name,
((struct dentry *) ino->u.smbfs_i.dentry)->d_name.name, count, result);
dentry->d_parent->d_name.name, dentry->d_name.name, count, result);
#endif
smb_unlock_server(server);
return result;
}
int
smb_proc_write(struct inode *ino, off_t offset, int count, const char *data)
smb_proc_write(struct dentry *dentry, off_t offset, int count, const char *data)
{
struct smb_sb_info *server = SMB_SERVER(ino);
struct smb_sb_info *server = server_from_dentry(dentry);
int result;
__u8 *p;
smb_lock_server(server);
#if SMBFS_DEBUG_VERBOSE
printk("smb_proc_write: file %s/%s, count=%d@%ld, packet_size=%d\n",
((struct dentry *)ino->u.smbfs_i.dentry)->d_parent->d_name.name,
((struct dentry *)ino->u.smbfs_i.dentry)->d_name.name,
dentry->d_parent->d_name.name, dentry->d_name.name,
count, offset, server->packet_size);
#endif
smb_lock_server(server);
p = smb_setup_header(server, SMBwrite, 5, count + 3);
WSET(server->packet, smb_vwv0, ino->u.smbfs_i.fileid);
WSET(server->packet, smb_vwv0, dentry->d_inode->u.smbfs_i.fileid);
WSET(server->packet, smb_vwv1, count);
DSET(server->packet, smb_vwv2, offset);
WSET(server->packet, smb_vwv4, 0);
......@@ -1544,9 +1535,10 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
* Check whether to change the info level. There appears to be
* a bug in Win NT 4.0's handling of info level 1, whereby it
* truncates the directory scan for certain patterns of files.
* Hence we use level 259 for NT. (And Win 95 as well ...)
* Hence we use level 259 for NT.
*/
if (server->opt.protocol >= SMB_PROTOCOL_NT1)
if (server->opt.protocol >= SMB_PROTOCOL_NT1 &&
!(server->mnt->version & SMB_FIX_WIN95))
info_level = 259;
smb_lock_server(server);
......@@ -1639,8 +1631,8 @@ printk("smb_proc_readdir_long: error=%d, breaking\n", result);
if (server->rcls != 0)
{
#ifdef SMBFS_PARANOIA
printk("smb_proc_readdir_long: rcls=%d, err=%d, breaking\n",
server->rcls, server->err);
printk("smb_proc_readdir_long: name=%s, entries=%d, rcls=%d, err=%d\n",
mask, entries, server->rcls, server->err);
#endif
entries = -smb_errno(server);
break;
......@@ -1749,6 +1741,94 @@ smb_proc_readdir(struct dentry *dir, int fpos, void *cachep)
return smb_proc_readdir_short(server, dir, fpos, cachep);
}
/*
* This version uses the trans2 TRANSACT2_FINDFIRST message
* to get the attribute data.
* Note: called with the server locked.
*
* Bugs Noted:
*/
static int
smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
struct smb_fattr *fattr)
{
char *param = server->temp_buf, *mask = param + 12;
__u16 date, time;
unsigned char *resp_data = NULL;
unsigned char *resp_param = NULL;
int resp_data_len = 0;
int resp_param_len = 0;
int mask_len, result;
retry:
mask_len = smb_encode_path(server, mask, dentry, NULL) - mask;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_proc_getattr_ff: name=%s, len=%d\n", mask, mask_len);
#endif
WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
WSET(param, 2, 1); /* max count */
WSET(param, 4, 1); /* close after this call */
WSET(param, 6, 1); /* info_level */
DSET(param, 8, 0);
result = smb_trans2_request(server, TRANSACT2_FINDFIRST,
0, NULL, 12 + mask_len + 1, param,
&resp_data_len, &resp_data,
&resp_param_len, &resp_param);
if (result < 0)
{
if (smb_retry(server))
goto retry;
goto out;
}
if (server->rcls != 0)
{
result = -smb_errno(server);
#ifdef SMBFS_PARANOIA
if (result != -ENOENT)
printk("smb_proc_getattr_ff: error for %s, rcls=%d, err=%d\n",
mask, server->rcls, server->err);
#endif
goto out;
}
/* Make sure we got enough data ... */
result = -EINVAL;
if (resp_data_len < 22 || WVAL(resp_param, 2) != 1)
{
#ifdef SMBFS_PARANOIA
printk("smb_proc_getattr_ff: bad result for %s, len=%d, count=%d\n",
mask, resp_data_len, WVAL(resp_param, 2));
#endif
goto out;
}
/*
* Decode the response into the fattr ...
*/
date = WVAL(resp_data, 0);
time = WVAL(resp_data, 2);
fattr->f_ctime = date_dos2unix(date, time);
date = WVAL(resp_data, 4);
time = WVAL(resp_data, 6);
fattr->f_atime = date_dos2unix(date, time);
date = WVAL(resp_data, 8);
time = WVAL(resp_data, 10);
fattr->f_mtime = date_dos2unix(date, time);
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_proc_getattr_ff: name=%s, date=%x, time=%x, mtime=%ld\n",
mask, date, time, fattr->f_mtime);
#endif
fattr->f_size = DVAL(resp_data, 12);
/* ULONG allocation size */
fattr->attr = WVAL(resp_data, 20);
result = 0;
out:
return result;
}
/*
* Note: called with the server locked.
*/
......@@ -1883,11 +1963,17 @@ smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
* Win 95 is painfully slow at returning trans2 getattr info,
* so we provide the SMB_FIX_OLDATTR option switch.
*/
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 &&
!(server->mnt->version & SMB_FIX_OLDATTR))
result = smb_proc_getattr_trans2(server, dir, fattr);
else
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) {
if (server->mnt->version & SMB_FIX_OLDATTR)
goto core_attr;
if (server->mnt->version & SMB_FIX_DIRATTR)
result = smb_proc_getattr_ff(server, dir, fattr);
else
result = smb_proc_getattr_trans2(server, dir, fattr);
} else {
core_attr:
result = smb_proc_getattr_core(server, dir, fattr);
}
smb_finish_dirent(server, fattr);
......
......@@ -95,28 +95,37 @@ struct vfsmount *lookup_vfsmnt(kdev_t dev)
/* NOTREACHED */
}
struct vfsmount *add_vfsmnt(kdev_t dev, const char *dev_name, const char *dir_name)
static struct vfsmount *add_vfsmnt(struct super_block *sb,
const char *dev_name, const char *dir_name)
{
struct vfsmount *lptr;
char *tmp;
char *tmp, *name;
lptr = (struct vfsmount *)kmalloc(sizeof(struct vfsmount), GFP_KERNEL);
if (!lptr)
return NULL;
if (!lptr)
goto out;
memset(lptr, 0, sizeof(struct vfsmount));
lptr->mnt_dev = dev;
lptr->mnt_sb = sb;
lptr->mnt_dev = sb->s_dev;
lptr->mnt_flags = sb->s_flags;
sema_init(&lptr->mnt_sem, 1);
/* N.B. Is it really OK to have a vfsmount without names? */
if (dev_name && !IS_ERR(tmp = getname(dev_name))) {
if ((lptr->mnt_devname =
(char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
strcpy(lptr->mnt_devname, tmp);
name = (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL);
if (name) {
strcpy(name, tmp);
lptr->mnt_devname = name;
}
putname(tmp);
}
if (dir_name && !IS_ERR(tmp = getname(dir_name))) {
if ((lptr->mnt_dirname =
(char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
strcpy(lptr->mnt_dirname, tmp);
name = (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL);
if (name) {
strcpy(name, tmp);
lptr->mnt_dirname = name;
}
putname(tmp);
}
......@@ -126,10 +135,11 @@ struct vfsmount *add_vfsmnt(kdev_t dev, const char *dev_name, const char *dir_na
vfsmnttail->mnt_next = lptr;
vfsmnttail = lptr;
}
return (lptr);
out:
return lptr;
}
void remove_vfsmnt(kdev_t dev)
static void remove_vfsmnt(kdev_t dev)
{
struct vfsmount *lptr, *tofree;
......@@ -496,6 +506,23 @@ asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
return err;
}
/*
* Find a super_block with no device assigned.
*/
static struct super_block *get_empty_super(void)
{
struct super_block *s = 0+super_blocks;
for (; s < NR_SUPER+super_blocks; s++) {
if (s->s_dev)
continue;
if (!s->s_lock)
return s;
printk("VFS: empty superblock %p locked!\n", s);
}
return NULL;
}
static struct super_block * read_super(kdev_t dev,const char *name,int flags,
void *data, int silent)
{
......@@ -503,44 +530,39 @@ static struct super_block * read_super(kdev_t dev,const char *name,int flags,
struct file_system_type *type;
if (!dev)
goto out_fail;
goto out_null;
check_disk_change(dev);
s = get_super(dev);
if (s)
return s;
goto out;
type = get_fs_type(name);
if (!type) {
printk("VFS: on device %s: get_fs_type(%s) failed\n",
kdevname(dev), name);
goto out_fail;
}
for (s = 0+super_blocks ;; s++) {
if (s >= NR_SUPER+super_blocks)
goto out_fail;
if (s->s_dev)
continue;
if (s->s_lock) {
printk("VFS: empty superblock %p locked!\n", s);
continue;
}
break;
goto out;
}
s = get_empty_super();
if (!s)
goto out;
s->s_dev = dev;
s->s_flags = flags;
s->s_dirt = 0;
/* N.B. Should lock superblock now ... */
if (!type->read_super(s,data, silent))
goto fail;
if (!type->read_super(s, data, silent))
goto out_fail;
s->s_dev = dev; /* N.B. why do this again?? */
s->s_rd_only = 0;
s->s_type = type;
out:
return s;
/* N.B. s_dev should be cleared in type->read_super */
fail:
s->s_dev = 0;
out_fail:
return NULL;
s->s_dev = 0;
out_null:
s = NULL;
goto out;
}
/*
......@@ -603,17 +625,16 @@ static void d_mount(struct dentry *covered, struct dentry *dentry)
dentry->d_covers = covered;
}
static int do_umount(kdev_t dev,int unmount_root)
static int do_umount(kdev_t dev, int unmount_root)
{
struct super_block * sb;
int retval;
retval = -ENOENT;
sb = get_super(dev);
if (!sb)
return -ENOENT;
if (!sb || !sb->s_root)
goto out;
if (!sb->s_root)
return -ENOENT;
/*
* Before checking whether the filesystem is still busy,
* make sure the kernel doesn't hold any quotafiles open
......@@ -659,7 +680,6 @@ static int do_umount(kdev_t dev,int unmount_root)
sb->s_op->put_super(sb);
}
remove_vfsmnt(dev);
retval = 0;
out:
return retval;
}
......@@ -781,7 +801,7 @@ int fs_may_mount(kdev_t dev)
int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const char * type, int flags, void * data)
{
struct dentry * dir_d = NULL;
struct dentry * dir_d;
struct super_block * sb;
struct vfsmount *vfsmnt;
int error;
......@@ -806,15 +826,13 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const cha
goto dput_and_out;
/*
* Check whether to read the super block
* Note: If the superblock already exists,
* read_super just does a get_super().
*/
sb = get_super(dev);
if (!sb || !sb->s_root) {
error = -EINVAL;
sb = read_super(dev,type,flags,data,0);
if (!sb)
goto dput_and_out;
}
error = -EINVAL;
sb = read_super(dev, type, flags, data, 0);
if (!sb)
goto dput_and_out;
/*
* We may have slept while reading the super block,
......@@ -825,20 +843,19 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const cha
goto dput_and_out;
error = -ENOMEM;
vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
if (vfsmnt) {
vfsmnt->mnt_sb = sb;
vfsmnt->mnt_flags = flags;
d_mount(dir_d, sb->s_root);
error = 0;
goto out; /* we don't dput(dir) - see umount */
}
vfsmnt = add_vfsmnt(sb, dev_name, dir_name);
if (!vfsmnt)
goto dput_and_out;
d_mount(dir_d, sb->s_root);
error = 0; /* we don't dput(dir_d) - see umount */
dput_and_out:
dput(dir_d);
out:
up(&mount_sem);
return error;
dput_and_out:
dput(dir_d);
goto out;
}
......@@ -1063,14 +1080,11 @@ __initfunc(static void do_mount_root(void))
if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
ROOT_DEV = 0;
if ((fs_type = get_fs_type("nfs"))) {
if ((vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/"))) {
sb = &super_blocks[0];
while (sb->s_dev) sb++;
vfsmnt->mnt_sb = sb;
sb->s_dev = get_unnamed_dev();
sb->s_flags = root_mountflags & ~MS_RDONLY;
sb = get_empty_super(); /* "can't fail" */
sb->s_dev = get_unnamed_dev();
sb->s_flags = root_mountflags & ~MS_RDONLY;
vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
if (vfsmnt) {
if (nfs_root_mount(sb) >= 0) {
sb->s_rd_only = 0;
sb->s_dirt = 0;
......@@ -1081,9 +1095,10 @@ __initfunc(static void do_mount_root(void))
printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
return;
}
sb->s_dev = 0;
put_unnamed_dev(sb->s_dev);
remove_vfsmnt(sb->s_dev);
}
put_unnamed_dev(sb->s_dev);
sb->s_dev = 0;
}
if (!ROOT_DEV) {
printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
......@@ -1136,12 +1151,10 @@ __initfunc(static void do_mount_root(void))
printk ("VFS: Mounted root (%s filesystem)%s.\n",
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/");
if (!vfsmnt)
panic("VFS: add_vfsmnt failed for root fs");
vfsmnt->mnt_sb = sb;
vfsmnt->mnt_flags = root_mountflags;
return;
vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
if (vfsmnt)
return;
panic("VFS: add_vfsmnt failed for root fs");
}
}
panic("VFS: Unable to mount root fs on %s",
......@@ -1225,10 +1238,8 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
return error;
}
remove_vfsmnt(old_root_dev);
vfsmnt = add_vfsmnt(old_root_dev,"/dev/root.old",put_old);
vfsmnt = add_vfsmnt(old_root->d_sb, "/dev/root.old", put_old);
if (vfsmnt) {
vfsmnt->mnt_sb = old_root->d_inode->i_sb;
vfsmnt->mnt_flags = vfsmnt->mnt_sb->s_flags;
d_mount(dir_d,old_root);
return 0;
}
......
......@@ -159,7 +159,6 @@ extern unsigned char *apic_reg;
extern unsigned char boot_cpu_id;
extern unsigned long cpu_present_map;
extern volatile int cpu_number_map[NR_CPUS];
extern volatile int cpu_logical_map[NR_CPUS];
extern volatile unsigned long smp_invalidate_needed;
extern void smp_flush_tlb(void);
extern volatile unsigned long kernel_flag, kernel_counter;
......@@ -171,6 +170,11 @@ extern unsigned long ipi_count;
extern void smp_invalidate_rcv(void); /* Process an NMI */
extern void smp_local_timer_interrupt(struct pt_regs * regs);
extern void setup_APIC_clock (void);
extern volatile int __cpu_logical_map[NR_CPUS];
extern inline int cpu_logical_map(int cpu)
{
return __cpu_logical_map[cpu];
}
/*
......@@ -235,5 +239,12 @@ extern __inline int hard_smp_processor_id(void)
#define SMP_FROM_INT 1
#define SMP_FROM_SYSCALL 2
#else
#ifndef ASSEMBLY
extern inline int cpu_logical_map(int cpu)
{
return cpu;
}
#endif
#endif
#endif
......@@ -2,6 +2,7 @@
#define _LINUX_KERNEL_STAT_H
#include <asm/irq.h>
#include <asm/smp.h>
#include <linux/smp.h>
#include <linux/tasks.h>
......@@ -25,7 +26,7 @@ struct kernel_stat {
unsigned int dk_drive_wblk[DK_NDRIVE];
unsigned int pgpgin, pgpgout;
unsigned int pswpin, pswpout;
unsigned int interrupts[NR_CPUS][NR_IRQS];
unsigned int irqs[NR_CPUS][NR_IRQS];
unsigned int ipackets, opackets;
unsigned int ierrors, oerrors;
unsigned int collisions;
......@@ -34,4 +35,17 @@ struct kernel_stat {
extern struct kernel_stat kstat;
/*
* Number of interrupts per specific IRQ source, since bootup
*/
extern inline int kstat_irqs (int irq)
{
int i, sum=0;
for (i = 0 ; i < smp_num_cpus ; i++)
sum += kstat.irqs[cpu_logical_map(i)][irq];
return sum;
}
#endif /* _LINUX_KERNEL_STAT_H */
......@@ -12,10 +12,10 @@ struct minix_sb_info {
unsigned long s_firstdatazone;
unsigned long s_log_zone_size;
unsigned long s_max_size;
struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[64];
unsigned long s_dirsize;
unsigned long s_namelen;
struct buffer_head ** s_imap;
struct buffer_head ** s_zmap;
struct buffer_head * s_sbh;
struct minix_super_block * s_ms;
unsigned short s_mount_state;
......
......@@ -76,6 +76,7 @@ smb_vfree(void *obj)
*/
#define SMB_FIX_WIN95 0x0001 /* Win 95 server */
#define SMB_FIX_OLDATTR 0x0002 /* Use core getattr (Win 95 speedup) */
#define SMB_FIX_DIRATTR 0x0004 /* Use find_first for getattr */
/* linux/fs/smbfs/mmap.c */
int smb_mmap(struct file *, struct vm_area_struct *);
......@@ -95,7 +96,6 @@ struct super_block *smb_read_super(struct super_block *, void *, int);
void smb_get_inode_attr(struct inode *, struct smb_fattr *);
void smb_invalidate_inodes(struct smb_sb_info *);
int smb_revalidate_inode(struct dentry *);
int smb_refresh_inode(struct inode *);
int smb_notify_change(struct dentry *, struct iattr *);
unsigned long smb_invent_inos(unsigned long);
struct inode *smb_iget(struct super_block *, struct smb_fattr *);
......@@ -112,8 +112,8 @@ int smb_close(struct inode *);
void smb_close_dentry(struct dentry *);
int smb_close_fileid(struct dentry *, __u16);
int smb_open(struct dentry *, int);
int smb_proc_read(struct inode *, off_t, int, char *);
int smb_proc_write(struct inode *, off_t, int, const char *);
int smb_proc_read(struct dentry *, off_t, int, char *);
int smb_proc_write(struct dentry *, off_t, int, const char *);
int smb_proc_create(struct dentry *, __u16, time_t, __u16 *);
int smb_proc_mv(struct dentry *, struct dentry *);
int smb_proc_mkdir(struct dentry *);
......
......@@ -21,15 +21,14 @@ struct smb_inode_info {
* file handles are local to a connection. A file is open if
* (open == generation).
*/
unsigned int open;
unsigned int open; /* open generation */
__u16 fileid; /* What id to handle a file with? */
__u16 attr; /* Attribute fields, DOS value */
__u16 access; /* Access bits. */
__u16 access; /* Access mode */
__u16 cache_valid; /* dircache valid? */
unsigned long oldmtime; /* last time refreshed */
unsigned long closed; /* timestamp when closed */
void * dentry; /* The dentry we were opened with */
};
#endif
......
......@@ -61,5 +61,6 @@ extern volatile int smp_msg_id;
#define smp_message_pass(t,m,d,w)
#define smp_threads_ready 1
#define kernel_lock()
#endif
#endif
......@@ -927,8 +927,6 @@ int cpu_idle(void *unused)
#else
extern void setup_IO_APIC(void);
/*
* Multiprocessor idle thread is in arch/...
*/
......@@ -1051,7 +1049,6 @@ __initfunc(asmlinkage void start_kernel(void))
printk("POSIX conformance testing by UNIFIX\n");
#ifdef __SMP__
smp_init();
setup_IO_APIC();
#endif
#ifdef CONFIG_SYSCTL
sysctl_init();
......
......@@ -437,7 +437,6 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t
*/
int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
{
int i;
int nr;
int error = -ENOMEM;
struct task_struct *p;
......@@ -483,11 +482,14 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
p->times.tms_utime = p->times.tms_stime = 0;
p->times.tms_cutime = p->times.tms_cstime = 0;
#ifdef __SMP__
p->has_cpu = 0;
p->processor = NO_PROC_ID;
/* ?? should we just memset this ?? */
for(i = 0; i < smp_num_cpus; i++)
p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
{
int i;
p->has_cpu = 0;
p->processor = NO_PROC_ID;
/* ?? should we just memset this ?? */
for(i = 0; i < smp_num_cpus; i++)
p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
}
#endif
p->lock_depth = 0;
p->start_time = jiffies;
......
......@@ -392,7 +392,9 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
/* END OF OBSOLETE FUNCTIONS */
/*
* Note: requires bh_atomic locking.
*/
int arp_bind_neighbour(struct dst_entry *dst)
{
struct device *dev = dst->dev;
......@@ -734,11 +736,9 @@ int arp_req_set(struct arpreq *r, struct device * dev)
start_bh_atomic();
neigh = __neigh_lookup(&arp_tbl, &ip, dev, 1);
if (neigh) {
unsigned state = 0;
if (r->arp_flags&ATF_PERM)
unsigned state = NUD_STALE;
if (r->arp_flags & ATF_PERM)
state = NUD_PERMANENT;
else
state = NUD_STALE;
err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?
r->arp_ha.sa_data : NULL, state, 1, 0);
neigh_release(neigh);
......@@ -764,16 +764,21 @@ static unsigned arp_state_to_flags(struct neighbour *neigh)
static int arp_req_get(struct arpreq *r, struct device *dev)
{
u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
struct neighbour *neigh;
int err = -ENXIO;
start_bh_atomic();
neigh = __neigh_lookup(&arp_tbl, &ip, dev, 0);
if (neigh) {
memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
r->arp_ha.sa_family = dev->type;
strncpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
r->arp_flags = arp_state_to_flags(neigh);
neigh_release(neigh);
return 0;
err = 0;
}
return -ENXIO;
end_bh_atomic();
return err;
}
int arp_req_delete(struct arpreq *r, struct device * dev)
......@@ -802,7 +807,7 @@ int arp_req_delete(struct arpreq *r, struct device * dev)
err = -ENXIO;
start_bh_atomic();
neigh = neigh_lookup(&arp_tbl, &ip, dev);
neigh = __neigh_lookup(&arp_tbl, &ip, dev, 0);
if (neigh) {
err = neigh_update(neigh, NULL, NUD_FAILED, 1, 0);
neigh_release(neigh);
......@@ -856,6 +861,11 @@ int arp_ioctl(unsigned int cmd, void *arg)
err = -EINVAL;
if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type)
goto out;
} else if (cmd != SIOCSARP) {
/* dev has not been set ... */
printk(KERN_ERR "arp_ioctl: invalid, null device\n");
err = -EINVAL;
goto out;
}
switch(cmd) {
......@@ -863,6 +873,7 @@ int arp_ioctl(unsigned int cmd, void *arg)
err = arp_req_delete(&r, dev);
break;
case SIOCSARP:
/* This checks for dev == NULL */
err = arp_req_set(&r, dev);
break;
case SIOCGARP:
......
......@@ -614,7 +614,7 @@ unsigned int tcp_poll(struct socket *sock, poll_table *wait)
mask |= POLLIN | POLLRDNORM;
#if 1 /* This needs benchmarking and real world tests */
space = sk->dst_cache->pmtu + 128;
space = (sk->dst_cache ? sk->dst_cache->pmtu : sk->mss) + 128;
if (space < 2048) /* XXX */
space = 2048;
#else /* 2.0 way */
......@@ -663,7 +663,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return put_user(amount, (int *)arg);
}
default:
return(-EINVAL);
return(-ENOIOCTLCMD);
};
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment