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
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
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.
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
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
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
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
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
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
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
#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)
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);
+ }
}
}
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
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;
/*
* 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
*/
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;
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))) {
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
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 */
* 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;
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! */
/* 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);
if (!smp_found_config)
{
printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
+ io_apic_irqs = 0;
return;
}
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();
}
/*
*/
/*****************************************************************************/
-
-#include <linux/hfmodem.h>
+
+/* This is compiled with HOSTCC - do not include any <linux/foo.h> headers. */
#include <math.h>
#include <stdio.h>
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 */
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
#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>
#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;
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;
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;
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;
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");
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)
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,
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"
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"
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;
}
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);
{
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",
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;
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;
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);
{
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;
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?? */
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
* (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
}
/*
- * 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;
- }
}
/*
{
struct smb_mount_data *mnt;
struct inode *root_inode;
- struct dentry *dentry;
struct smb_fattr root;
MOD_INC_USE_COUNT;
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.
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;
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");
out:
if (refresh)
- smb_refresh_inode(inode);
+ smb_refresh_inode(dentry);
return error;
}
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;
}
}
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);
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;
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);
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);
* 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);
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;
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.
*/
* 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);
/* 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);
}
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;
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)
{
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;
}
/*
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
sb->s_op->put_super(sb);
}
remove_vfsmnt(dev);
- retval = 0;
out:
return retval;
}
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;
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,
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;
}
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;
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");
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",
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;
}
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;
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];
+}
/*
#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
#define _LINUX_KERNEL_STAT_H
#include <asm/irq.h>
+#include <asm/smp.h>
#include <linux/smp.h>
#include <linux/tasks.h>
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;
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 */
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;
*/
#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 *);
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 *);
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 *);
* 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
#define smp_message_pass(t,m,d,w)
#define smp_threads_ready 1
#define kernel_lock()
+
#endif
#endif
#else
-extern void setup_IO_APIC(void);
-
/*
* Multiprocessor idle thread is in arch/...
*/
printk("POSIX conformance testing by UNIFIX\n");
#ifdef __SMP__
smp_init();
- setup_IO_APIC();
#endif
#ifdef CONFIG_SYSCTL
sysctl_init();
*/
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;
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;
/* END OF OBSOLETE FUNCTIONS */
-
+/*
+ * Note: requires bh_atomic locking.
+ */
int arp_bind_neighbour(struct dst_entry *dst)
{
struct device *dev = dst->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);
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)
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);
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) {
err = arp_req_delete(&r, dev);
break;
case SIOCSARP:
+ /* This checks for dev == NULL */
err = arp_req_set(&r, dev);
break;
case SIOCGARP:
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 */
return put_user(amount, (int *)arg);
}
default:
- return(-EINVAL);
+ return(-ENOIOCTLCMD);
};
}