Commit 57afa237 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.100pre2

parent 5892de9e
This diff is collapsed.
MTRR (Memory Type Range Register) control
17 Dec 1997
2 May 1998
Richard Gooch
<rgooch@atnf.csiro.au>
On Intel Pentium Pro systems the Memory Type Range Registers (MTRRs)
may be used to control processor access to memory ranges. This is
most useful when you have a video (VGA) card on the PCI
bus. Enabling write-combining allows PCI write transfers to be
combined into a larger transfer before bursting over the PCI
bus. This can increase performance of image write operations 2.5
times or more.
On Intel Pentium Pro/Pentium II systems the Memory Type Range
Registers (MTRRs) may be used to control processor access to memory
ranges. This is most useful when you have a video (VGA) card on a
PCI or AGP bus. Enabling write-combining allows bus write transfers
to be combined into a larger transfer before bursting over the
PCI/AGP bus. This can increase performance of image write operations
2.5 times or more.
The CONFIG_MTRR option creates a /proc/mtrr file which may be used
to manipulate your MTRRs. Typically the X server should use
......@@ -30,13 +30,40 @@ Reading MTRRs from the shell:
% cat /proc/mtrr
reg00: base=0x00000000 ( 0MB), size= 128MB: write-back, count=1
reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1
reg05: base=0x80000000 (2048MB), size= 4MB: write-combining, count=1
===============================================================================
Creating MTRRs from the shell:
% echo "base=0x80000000 size=0x400000 type=write-combining" >! /proc/mtrr
# echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr
And the result thereof:
% cat /proc/mtrr
reg00: base=0x00000000 ( 0MB), size= 128MB: write-back, count=1
reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1
reg02: base=0xf8000000 (3968MB), size= 4MB: write-combining, count=1
This is for videoram at base address 0xf8000000 and size 4 MBytes. To
find out your base address, you need to look at the output of your X
server, which tells you where the linear framebuffer address is. A
typical line that you may get is:
(--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000
Note that you should only use the value from the X server, as it may
move the framebuffer base address, so the only value you can trust is
that reported by the X server.
To find out the size of your framebuffer (what, you don't actually
know?), the following line will tell you:
(--) S3: videoram: 4096k
That's 4 MBytes, which is 0x400000 bytes (in hexadecimal).
A patch is being written for XFree86 which will make this automatic:
in other words the X server will manipulate /proc/mtrr using the
ioctl() interface, so users won't have to do anything. If you use a
commercial X server, lobby your vendor to add support for MTRRs.
===============================================================================
Removing MTRRs from the shell:
% echo "disable=5" >! /proc/mtrr
% echo "disable=2" >! /proc/mtrr
===============================================================================
Reading MTRRs from a C programme using ioctl()'s:
......@@ -44,7 +71,7 @@ Reading MTRRs from a C programme using ioctl()'s:
Source file for mtrr-show (example programme to show MTRRs using ioctl()'s)
Copyright (C) 1997 Richard Gooch
Copyright (C) 1997-1998 Richard Gooch
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -72,7 +99,7 @@ Reading MTRRs from a C programme using ioctl()'s:
Written by Richard Gooch 17-DEC-1997
Last updated by Richard Gooch 17-DEC-1997
Last updated by Richard Gooch 2-MAY-1998
*/
......@@ -84,7 +111,7 @@ Reading MTRRs from a C programme using ioctl()'s:
#include <sys/ioctl.h>
#include <errno.h>
#define MTRR_NEED_STRINGS
#include <linux/mtrr.h>
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
......@@ -130,7 +157,7 @@ Creating MTRRs from a C programme using ioctl()'s:
Source file for mtrr-add (example programme to add an MTRRs using ioctl())
Copyright (C) 1997 Richard Gooch
Copyright (C) 1997-1998 Richard Gooch
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -158,7 +185,7 @@ Creating MTRRs from a C programme using ioctl()'s:
Written by Richard Gooch 17-DEC-1997
Last updated by Richard Gooch 17-DEC-1997
Last updated by Richard Gooch 2-MAY-1998
*/
......@@ -172,7 +199,7 @@ Creating MTRRs from a C programme using ioctl()'s:
#include <sys/ioctl.h>
#include <errno.h>
#define MTRR_NEED_STRINGS
#include <linux/mtrr.h>
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
......
......@@ -18,6 +18,7 @@ Currently, these files are in /proc/sys/vm:
- bdflush
- buffermem
- freepages
- kswapd
- overcommit_memory
- pagecache
- swapctl
......@@ -112,9 +113,58 @@ freepages:
This file contains the values in the struct freepages. That
struct contains three members: min, low and high.
These variables are currently unused (?), but they're
very likely to be abused for something else in the near
future, so don't yet remove it from the source...
Although the goal of the Linux memory management subsystem
is to avoid fragmentation and make large chunks of free
memory (so that we can hand out DMA buffers and such), there
still are some page-based limits in the system, mainly to
make sure we don't waste too much memory trying to get large
free area's.
The meaning of the numbers is:
freepages.min When the number of free pages in the system
reaches this number, only the kernel can
allocate more memory.
freepages.low If memory is too fragmented, the swapout
daemon is started, except when the number
of free pages is larger than freepages.low.
freepages.high The swapping daemon exits when memory is
sufficiently defragmented, when the number
of free pages reaches freepages.high or when
it has tried the maximum number of times.
==============================================================
kswapd:
Kswapd is the kernel swapout daemon. That is, kswapd is that
piece of the kernel that frees memory when it get's fragmented
or full. Since every system is different, you'll probably want
some control over this piece of the system.
The numbers in this page correspond to the numbers in the
struct pager_daemon {tries_base, tries_min, swap_cluster
}; The tries_base and swap_cluster probably have the
largest influence on system performance.
tries_base The maximum number of pages kswapd tries to
free in one round is calculated from this
number. Usually this number will be divided
by 4 or 8 (see mm/vmscan.c), so it isn't as
big as it looks.
When you need to increase the bandwith to/from
swap, you'll want to increase this number.
tries_min This is the minimum number of times kswapd
tries to free a page each time it is called.
Basically it's just there to make sure that
kswapd frees some pages even when it's being
called with minimum priority.
swap_cluster This is the number of pages kswapd writes in
one turn. You want this large so that kswapd
does it's I/O in large chunks and the disk
doesn't have to seek often, but you don't want
it to be too large since that would flood the
request queue.
==============================================================
......
/*
* bios32.c - Low-Level PCI Access
*
* $Id: bios32.c,v 1.29 1998/04/17 16:31:15 mj Exp $
* $Id: bios32.c,v 1.32 1998/05/02 12:03:05 davem Exp $
*
* Sponsored by
* iX Multiuser Multitasking Magazine
......@@ -66,6 +66,8 @@
* and cleaned it up... Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*
* Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj]
*
* May 1, 1998 : Support for peer host bridges. [mj]
*/
#include <linux/config.h>
......@@ -74,6 +76,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <asm/page.h>
#include <asm/segment.h>
......@@ -832,7 +835,10 @@ __initfunc(static struct pci_access *pci_find_bios(void))
}
/*
* Sort the device list according to PCI BIOS.
* Sort the device list according to PCI BIOS. Nasty hack, but since some
* fool forgot to define the `correct' device order in the PCI BIOS specs
* and we want to be (possibly bug-to-bug ;-]) compatible with older kernels
* which used BIOS ordering, we are bound to do this...
*/
__initfunc(void pcibios_sort(void))
......@@ -924,11 +930,41 @@ __initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx))
}
/*
* Arch-dependent fixups. We need to fix here base addresses, I/O
* and memory enables and IRQ's as the PCI BIOS'es are buggy as hell.
* In case there are peer host bridges, scan bus behind each of them.
* Although several sources claim that the host bridges should have
* header type 1 and be assigned a bus number as for PCI2PCI bridges,
* the reality doesn't pass this test and the bus number is usually
* hard-wired to 1.
*/
__initfunc(void pcibios_fixup_peer_bridges(void))
{
struct pci_dev *dev;
int cnt = 0;
for(dev=pci_root.devices; dev; dev=dev->sibling)
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
DBG("PCI: Host bridge at %02x\n", dev->devfn);
if (cnt) {
struct pci_bus *b = kmalloc(sizeof(struct pci_bus), GFP_KERNEL);
memset(b, 0, sizeof(*b));
b->parent = &pci_root;
b->next = pci_root.next;
pci_root.next = b;
b->self = dev;
b->number = b->secondary = cnt;
b->subordinate = 0xff;
b->subordinate = pci_scan_bus(b);
}
cnt++;
}
}
__initfunc(void pcibios_fixup(void))
/*
* Fix base addresses, I/O and memory enables and IRQ's (mostly work-arounds
* for buggy PCI BIOS'es :-[).
*/
__initfunc(void pcibios_fixup_devices(void))
{
struct pci_dev *dev;
int i, has_io, has_mem;
......@@ -991,6 +1027,16 @@ __initfunc(void pcibios_fixup(void))
if (dev->irq >= NR_IRQS)
dev->irq = 0;
}
}
/*
* Arch-dependent fixups.
*/
__initfunc(void pcibios_fixup(void))
{
pcibios_fixup_peer_bridges();
pcibios_fixup_devices();
#ifdef CONFIG_PCI_BIOS
if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
......
This diff is collapsed.
......@@ -735,7 +735,11 @@ static void do_8259A_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
static void enable_ioapic_irq(unsigned int irq)
{
irq_desc_t *desc = irq_desc + irq;
#if 0
enable_IO_APIC_irq(irq);
#endif
if (desc->events && !desc->ipi) {
ack_APIC_irq();
desc->ipi = 1;
send_IPI(APIC_DEST_SELF, IO_APIC_VECTOR(irq));
}
......@@ -746,6 +750,9 @@ static void enable_ioapic_irq(unsigned int irq)
*/
static void disable_ioapic_irq(unsigned int irq)
{
#if 0
disable_IO_APIC_irq(irq);
#endif
}
static void do_ioapic_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
......@@ -754,13 +761,15 @@ static void do_ioapic_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
spin_lock(&irq_controller_lock);
/* Ack the irq inside the lock! */
ack_APIC_irq();
desc->ipi = 0;
/* If the irq is disabled for whatever reason, just set a flag and return */
/*
* If the irq is disabled for whatever reason, just
* set a flag and return
*/
if (desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)) {
desc->events = 1;
ack_APIC_irq();
spin_unlock(&irq_controller_lock);
return;
}
......@@ -790,6 +799,7 @@ static void do_ioapic_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
spin_unlock(&irq_controller_lock);
no_handler:
ack_APIC_irq();
hardirq_exit(cpu);
release_irqlock(cpu);
}
......
......@@ -104,6 +104,12 @@
Moved register-setting macros into this file.
Moved setup code from init/main.c to i386-specific areas.
v1.18
19980502 Richard Gooch <rgooch@atnf.csiro.au>
Moved MTRR detection outside conditionals in <mtrr_init>.
v1.19
19980502 Richard Gooch <rgooch@atnf.csiro.au>
Documentation improvement: mention Pentium II and AGP.
v1.20
*/
#include <linux/types.h>
#include <linux/errno.h>
......@@ -137,7 +143,7 @@
#include <asm/atomic.h>
#include <linux/smp.h>
#define MTRR_VERSION "1.18 (19980429)"
#define MTRR_VERSION "1.20 (19980502)"
#define TRUE 1
#define FALSE 0
......@@ -801,7 +807,7 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type,
if (ltype != type)
{
spin_unlock (&main_lock);
printk ( "mtrr: type missmatch for %lx,%lx old: %s new: %s\n",
printk ( "mtrr: type mismatch for %lx,%lx old: %s new: %s\n",
base, size, attrib_to_str (ltype), attrib_to_str (type) );
return -EINVAL;
}
......@@ -1193,8 +1199,8 @@ int init_module (void)
__initfunc(int mtrr_init(void))
#endif
{
# if !defined(__SMP__) || defined(MODULE)
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
# if !defined(__SMP__) || defined(MODULE)
printk("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", MTRR_VERSION);
#endif
......
......@@ -297,9 +297,9 @@ void machine_restart(char * __unused)
int i;
for (i=0; i<100; i++) {
kb_wait();
udelay(10);
udelay(50);
outb(0xfe,0x64); /* pulse reset low */
udelay(10);
udelay(50);
}
/* That didn't work - force a triple fault.. */
__asm__ __volatile__("lidt %0": :"m" (no_idt));
......
......@@ -627,20 +627,29 @@ __initfunc(void smp_commence(void))
smp_commenced=1;
}
__initfunc(void enable_local_APIC(void))
{
unsigned long value;
value = apic_read(APIC_SPIV);
value |= (1<<8); /* Enable APIC (bit==1) */
value &= ~(1<<9); /* Enable focus processor (bit==0) */
apic_write(APIC_SPIV,value);
udelay(100); /* B safe */
}
__initfunc(void smp_callin(void))
{
extern void calibrate_delay(void);
int cpuid=GET_APIC_ID(apic_read(APIC_ID));
unsigned long l;
/*
* Activate our APIC
*/
SMP_PRINTK(("CALLIN %d %d\n",hard_smp_processor_id(), smp_processor_id()));
l=apic_read(APIC_SPIV);
l|=(1<<8); /* Enable */
apic_write(APIC_SPIV,l);
enable_local_APIC();
/*
* Set up our APIC timer.
......@@ -1004,15 +1013,7 @@ __initfunc(void smp_boot_cpus(void))
}
#endif
/*
* Enable the local APIC
*/
cfg=apic_read(APIC_SPIV);
cfg|=(1<<8); /* Enable APIC */
apic_write(APIC_SPIV,cfg);
udelay(10);
enable_local_APIC();
/*
* Set up our local APIC timer:
......@@ -1561,7 +1562,7 @@ __initfunc(static unsigned int get_8254_timer_count (void))
* APIC double write bug.
*/
#define APIC_DIVISOR 16
#define APIC_DIVISOR 1
void setup_APIC_timer (unsigned int clocks)
{
......@@ -1585,7 +1586,7 @@ void setup_APIC_timer (unsigned int clocks)
*/
tmp_value = apic_read(APIC_TDCR);
apic_write(APIC_TDCR , (tmp_value & ~APIC_TDR_DIV_1 )
| APIC_TDR_DIV_16);
| APIC_TDR_DIV_1);
tmp_value = apic_read(APIC_TMICT);
apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
......
......@@ -1209,6 +1209,14 @@ static int raid5_make_request (struct md_dev *mddev, int rw, struct buffer_head
sh->pd_idx = pd_idx;
if (sh->phase != PHASE_COMPLETE && sh->phase != PHASE_BEGIN)
PRINTK(("stripe %lu catching the bus!\n", sh->sector));
if (sh->bh_new[dd_idx]) {
printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector);
printk("raid5: bh %p, bh_new %p\n", bh, sh->bh_new[dd_idx]);
lock_stripe(sh);
md_wakeup_thread(raid_conf->thread);
wait_on_stripe(sh);
goto repeat;
}
add_stripe_bh(sh, bh, dd_idx, rw);
md_wakeup_thread(raid_conf->thread);
......
......@@ -37,8 +37,8 @@ static int irq_write_proc(struct file *file, const char *buffer,
int retval = -EINVAL;
int newirq = PARPORT_IRQ_NONE;
struct parport *pp = (struct parport *)data;
struct pardevice *cad = pp->cad;
int oldirq = pp->irq;
unsigned long flags;
/*
* We can have these valid cases:
......@@ -70,36 +70,31 @@ static int irq_write_proc(struct file *file, const char *buffer,
if (oldirq == newirq)
goto out;
spin_lock_irqsave(&port->lock, flags);
if (pp->flags & PARPORT_FLAG_COMA)
goto out_ok;
if (newirq != PARPORT_IRQ_NONE) {
void (*handler)(int, void *, struct pt_regs *);
if (cad && cad->irq_func)
handler = cad->irq_func;
else
handler = parport_null_intr_func;
retval = -EBUSY;
if (pp->cad)
goto out_unlock;
retval = request_irq(newirq, handler,
SA_INTERRUPT,
cad ? cad->name : pp->name,
cad ? cad->private : NULL);
if (newirq != PARPORT_IRQ_NONE) {
retval = request_irq(newirq, parport_null_intr_func,
SA_INTERRUPT, pp->name, NULL);
if (retval)
goto out;
goto out_unlock;
else retval = count;
}
if (oldirq != PARPORT_IRQ_NONE) {
if (cad && cad->irq_func)
free_irq(oldirq, cad->private);
else
if (oldirq != PARPORT_IRQ_NONE)
free_irq(oldirq, NULL);
}
out_ok:
pp->irq = newirq;
out_unlock:
spin_unlock_irqrestore (&pp->lock, flags);
out:
return retval;
}
......
......@@ -308,7 +308,9 @@ int parport_claim(struct pardevice *dev)
}
/* Now we do the change of devices */
spin_lock_irqsave(&port->lock, flags);
port->cad = dev;
spin_unlock_irqrestore(&port->lock, flags);
/* Swap the IRQ handlers. */
if (port->irq != PARPORT_IRQ_NONE) {
......@@ -346,9 +348,8 @@ int parport_claim(struct pardevice *dev)
dev->waitprev = port->waittail;
if (port->waittail)
port->waittail->waitnext = dev;
else {
port->waithead = dev->port->waittail = dev;
}
else
port->waithead = port->waittail = dev;
}
spin_unlock_irqrestore (&port->lock, flags);
}
......
......@@ -8,7 +8,7 @@
* Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
* ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
*
* ==FILEVERSION 980319==
* ==FILEVERSION 980501==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the number above to the
......@@ -107,8 +107,10 @@ typedef struct sk_buff sk_buff;
#define PPP_LQR 0xc025 /* Link Quality Reporting Protocol */
#endif
#ifdef CONFIG_MODULES
static int ppp_register_compressor (struct compressor *cp);
static void ppp_unregister_compressor (struct compressor *cp);
#endif
/*
* Local functions
......@@ -3210,6 +3212,7 @@ static struct compressor *find_compressor (int type)
return (struct compressor *) 0;
}
#ifdef CONFIG_MODULES
static int ppp_register_compressor (struct compressor *cp)
{
struct compressor_link *new;
......@@ -3261,6 +3264,7 @@ static void ppp_unregister_compressor (struct compressor *cp)
}
restore_flags(flags);
}
#endif
/*************************************************************
* Module support routines
......
This diff is collapsed.
/*
* $Id: pci.c,v 1.79 1998/04/17 16:25:24 mj Exp $
* $Id: pci.c,v 1.84 1998/05/02 19:22:06 mj Exp $
*
* PCI Bus Services
*
......@@ -68,11 +68,48 @@ pci_find_class(unsigned int class, struct pci_dev *from)
}
int
pci_read_config_byte(struct pci_dev *dev, u8 where, u8 *val)
{
return pcibios_read_config_byte(dev->bus->number, dev->devfn, where, val);
}
int
pci_read_config_word(struct pci_dev *dev, u8 where, u16 *val)
{
return pcibios_read_config_word(dev->bus->number, dev->devfn, where, val);
}
int
pci_read_config_dword(struct pci_dev *dev, u8 where, u32 *val)
{
return pcibios_read_config_dword(dev->bus->number, dev->devfn, where, val);
}
int
pci_write_config_byte(struct pci_dev *dev, u8 where, u8 val)
{
return pcibios_write_config_byte(dev->bus->number, dev->devfn, where, val);
}
int
pci_write_config_word(struct pci_dev *dev, u8 where, u16 val)
{
return pcibios_write_config_word(dev->bus->number, dev->devfn, where, val);
}
int
pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val)
{
return pcibios_write_config_dword(dev->bus->number, dev->devfn, where, val);
}
void
pci_set_master(struct pci_dev *dev)
{
unsigned short cmd;
unsigned char lat;
u16 cmd;
u8 lat;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (! (cmd & PCI_COMMAND_MASTER)) {
......@@ -89,16 +126,43 @@ pci_set_master(struct pci_dev *dev)
}
}
__initfunc(void pci_read_bases(struct pci_dev *dev, unsigned int howmany))
{
unsigned int reg;
u32 l;
for(reg=0; reg<howmany; reg++) {
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
if (l == 0xffffffff)
continue;
dev->base_address[reg] = l;
if ((l & PCI_MEMORY_RANGE_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
reg++;
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
if (l) {
#if BITS_PER_LONG == 64
dev->base_address[reg-1] |= ((unsigned long) l) << 32;
#else
printk("PCI: Unable to handle 64-bit address for device %02x:%02x\n",
dev->bus->number, dev->devfn);
dev->base_address[reg-1] = 0;
#endif
}
}
}
}
__initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
{
unsigned int devfn, l, max, class;
unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
struct pci_dev *dev;
struct pci_dev *dev, **bus_last;
struct pci_bus *child;
int reg;
DBG("pci_scan_bus for bus %d\n", bus->number);
bus_last = &bus->devices;
max = bus->secondary;
for (devfn = 0; devfn < 0xff; ++devfn) {
if (PCI_FUNC(devfn) && !is_multi) {
......@@ -111,8 +175,8 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l);
/* some broken boards return 0 if a slot is empty: */
if (l == 0xffffffff || l == 0x00000000) {
hdr_type = 0;
if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) {
is_multi = 0;
continue;
}
......@@ -133,11 +197,12 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
class >>= 8; /* upper 3 bytes */
dev->class = class;
class >>= 8;
dev->hdr_type = hdr_type;
switch (hdr_type & 0x7f) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */
if (class >> 8 == PCI_CLASS_BRIDGE_PCI)
if (class == PCI_CLASS_BRIDGE_PCI)
goto bad;
/*
* If the card generates interrupts, read IRQ number
......@@ -151,25 +216,19 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
* read base address registers, again pcibios_fixup() can
* tweak these
*/
for (reg = 0; reg < 6; reg++) {
pcibios_read_config_dword(bus->number, devfn, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
}
pci_read_bases(dev, 6);
pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);
dev->rom_address = (l == 0xffffffff) ? 0 : l;
break;
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */
if (class >> 8 != PCI_CLASS_BRIDGE_PCI)
if (class != PCI_CLASS_BRIDGE_PCI)
goto bad;
for (reg = 0; reg < 2; reg++) {
pcibios_read_config_dword(bus->number, devfn, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
}
pci_read_bases(dev, 2);
pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);
dev->rom_address = (l == 0xffffffff) ? 0 : l;
break;
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */
if (class >> 16 != PCI_BASE_CLASS_BRIDGE)
if (class != PCI_CLASS_BRIDGE_CARDBUS)
goto bad;
for (reg = 0; reg < 2; reg++) {
pcibios_read_config_dword(bus->number, devfn, PCI_CB_MEMORY_BASE_0 + (reg << 3), &l);
......@@ -201,8 +260,8 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
* Now insert it into the list of devices held
* by the parent bus.
*/
dev->sibling = bus->devices;
bus->devices = dev;
*bus_last = dev;
bus_last = &dev->sibling;
#if 0
/*
......@@ -217,7 +276,7 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
/*
* If it's a bridge, scan the bus behind it.
*/
if (class >> 8 == PCI_CLASS_BRIDGE_PCI) {
if (class == PCI_CLASS_BRIDGE_PCI) {
unsigned int buses;
unsigned short cr;
......
/*
* $Id: pcisyms.c,v 1.4 1998/04/17 16:34:19 mj Exp $
* $Id: pcisyms.c,v 1.7 1998/05/02 19:20:06 mj Exp $
*
* PCI Bus Services -- Exported Symbols
*
......@@ -16,6 +16,12 @@ EXPORT_SYMBOL(pcibios_read_config_dword);
EXPORT_SYMBOL(pcibios_write_config_byte);
EXPORT_SYMBOL(pcibios_write_config_word);
EXPORT_SYMBOL(pcibios_write_config_dword);
EXPORT_SYMBOL(pci_read_config_byte);
EXPORT_SYMBOL(pci_read_config_word);
EXPORT_SYMBOL(pci_read_config_dword);
EXPORT_SYMBOL(pci_write_config_byte);
EXPORT_SYMBOL(pci_write_config_word);
EXPORT_SYMBOL(pci_write_config_dword);
EXPORT_SYMBOL(pci_devices);
EXPORT_SYMBOL(pci_root);
EXPORT_SYMBOL(pci_find_class);
......
/*
* $Id: quirks.c,v 1.3 1998/02/06 19:51:42 mj Exp $
* $Id: quirks.c,v 1.5 1998/05/02 19:24:14 mj Exp $
*
* PCI Chipset-Specific Quirks
*
......@@ -7,8 +7,7 @@
*
* This is the right place for all special fixups for on-board
* devices not depending on system architecture -- for example
* bus bridges. The only thing implemented in this release is
* the bridge optimization, but others might appear later.
* bus bridges.
*/
#include <linux/config.h>
......@@ -88,21 +87,19 @@ __initfunc(static void quirk_bridge(struct pci_dev *dev, int pos))
printk(" %s: ", bridge_optimization[i].type);
bmap = &bridge_mapping[pos + i];
if (!bmap->addr) {
printk("Not supported.");
printk("Not supported.\n");
} else {
pcibios_read_config_byte(dev->bus->number, dev->devfn, bmap->addr, &val);
pci_read_config_byte(dev, bmap->addr, &val);
if ((val & bmap->mask) == bmap->value)
printk("%s.", bridge_optimization[i].on);
printk("%s.\n", bridge_optimization[i].on);
else {
printk("%s.", bridge_optimization[i].off);
pcibios_write_config_byte(dev->bus->number, dev->devfn,
printk("%s", bridge_optimization[i].off);
pci_write_config_byte(dev,
bmap->addr,
(val & (0xff - bmap->mask))
+ bmap->value);
printk("Changed! Now %s.", bridge_optimization[i].on);
(val & (0xff - bmap->mask)) + bmap->value);
printk(" -> %s.\n", bridge_optimization[i].on);
}
}
printk("\n");
}
}
......@@ -113,27 +110,18 @@ __initfunc(static void quirk_bridge(struct pci_dev *dev, int pos))
which can cause problems in combination with the 82441FX/PPro MTRRs */
__initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg))
{
struct pci_dev *piix3;
struct pci_dev *d = NULL;
unsigned char dlc;
/* We have to make sure a particular bit is set in the PIIX3
ISA bridge, so we have to go out and find it. */
for (piix3 = pci_devices; ; piix3 = piix3->next) {
if (!piix3)
return;
if (piix3->vendor == PCI_VENDOR_ID_INTEL
&& piix3->device == PCI_DEVICE_ID_INTEL_82371SB_0)
break;
}
pcibios_read_config_byte(piix3->bus->number, piix3->devfn, 0x82, &dlc);
while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
pci_read_config_byte(d, 0x82, &dlc);
if (!(dlc & 1<<1)) {
printk("PIIX3: Enabling Passive Release\n");
dlc |= 1<<1;
pcibios_write_config_byte(piix3->bus->number, piix3->devfn,
0x82, dlc);
pci_write_config_byte(d, 0x82, dlc);
}
}
}
......@@ -141,7 +129,7 @@ __initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg))
typedef void (*quirk_handler)(struct pci_dev *, int);
/*
* Mpping from quirk handler functions to names.
* Mapping from quirk handler functions to names.
*/
struct quirk_name {
......@@ -185,6 +173,7 @@ static struct quirk_info quirk_list[] __initdata = {
{ PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8891A, quirk_bridge, 0x01 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, quirk_bridge, 0x00 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82434, quirk_bridge, 0x00 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82430, quirk_bridge, 0x00 },
#endif
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release, 0x00 },
};
......
......@@ -260,7 +260,7 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
struct request *rq = hwgroup->rq;
idescsi_pc_t *pc = (idescsi_pc_t *) rq->buffer;
int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
u8 *scsi_buf = pc->scsi_cmd->request_buffer;
u8 *scsi_buf;
if (rq->cmd != IDESCSI_PC_RQ) {
ide_end_request (uptodate, hwgroup);
......@@ -282,6 +282,7 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number);
if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) {
printk(", rst = ");
scsi_buf = pc->scsi_cmd->request_buffer;
hexdump(scsi_buf, IDE_MIN(16, pc->scsi_cmd->request_bufflen));
} else printk("\n");
}
......@@ -345,7 +346,18 @@ static void idescsi_pc_intr (ide_drive_t *drive)
if ( temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n");
idescsi_discard_data (drive,bcount);
temp = pc->buffer_size - pc->actually_transferred;
if (temp) {
clear_bit(PC_WRITING, &pc->flags);
if (pc->sg)
idescsi_input_buffers(drive, pc, temp);
else
atapi_input_bytes(drive, pc->current_position, temp);
printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount);
}
pc->actually_transferred += temp;
pc->current_position += temp;
idescsi_discard_data (drive,bcount - temp);
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc));
return;
}
......
......@@ -1605,6 +1605,7 @@ void scsi_bottom_half_handler(void)
if( SCpnt == NULL )
return;
spin_lock_irqsave(&io_request_lock, flags);
atomic_inc(&recursion_depth);
SCnext = SCpnt->bh_next;
......@@ -1696,6 +1697,7 @@ void scsi_bottom_half_handler(void)
} /* for(; SCpnt...) */
atomic_dec(&recursion_depth);
spin_unlock_irqrestore(&io_request_lock, flags);
} /* while(1==1) */
......
......@@ -159,7 +159,7 @@ scsi_delete_timer(Scsi_Cmnd * SCset)
*
* Notes:
*/
void scsi_times_out (Scsi_Cmnd * SCpnt)
static void do_scsi_times_out (Scsi_Cmnd * SCpnt)
{
/*
......@@ -222,6 +222,15 @@ void scsi_times_out (Scsi_Cmnd * SCpnt)
}
}
void scsi_times_out (Scsi_Cmnd * SCpnt)
{
unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags);
do_scsi_times_out(SCpnt);
spin_unlock_irqrestore(&io_request_lock, flags);
}
/*
* Function scsi_block_when_processing_errors
*
......@@ -264,6 +273,9 @@ scsi_block_when_processing_errors(Scsi_Device * SDpnt)
STATIC
void scsi_eh_times_out (Scsi_Cmnd * SCpnt)
{
unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags);
SCpnt->request.rq_status = RQ_SCSI_DONE;
SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
SCpnt->eh_state = SCSI_STATE_TIMEOUT;
......@@ -273,7 +285,8 @@ void scsi_eh_times_out (Scsi_Cmnd * SCpnt)
if (SCpnt->host->eh_action != NULL)
up(SCpnt->host->eh_action);
else
panic("Missing scsi error handler thread");
printk("Missing scsi error handler thread\n");
spin_unlock_irqrestore(&io_request_lock, flags);
}
......@@ -446,6 +459,11 @@ scsi_test_unit_ready(Scsi_Cmnd * SCpnt)
return SCpnt->eh_state;
}
/*
* This would normally need to get the IO request lock,
* but as it doesn't actually touch anything that needs
* to be locked we can avoid the lock here..
*/
STATIC
void scsi_sleep_done (struct semaphore * sem)
{
......
......@@ -65,6 +65,7 @@ EXPORT_SYMBOL(scsi_release_command);
EXPORT_SYMBOL(print_Scsi_Cmnd);
EXPORT_SYMBOL(scsi_block_when_processing_errors);
EXPORT_SYMBOL(scsi_mark_host_reset);
EXPORT_SYMBOL(scsi_ioctl_send_command);
#if defined(CONFIG_SCSI_LOGGING) /* { */
EXPORT_SYMBOL(scsi_logging_level);
#endif
......
......@@ -106,8 +106,8 @@ int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned bufl
break;
case ILLEGAL_REQUEST:
if (!quiet)
printk("sr%d: CDROM (ioctl) reports ILLEGAL REQUEST.\n",
target);
printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL "
"REQUEST.\n", target);
if (SCpnt->sense_buffer[12] == 0x20 &&
SCpnt->sense_buffer[13] == 0x00) {
/* sense: Invalid command operation code */
......@@ -121,7 +121,7 @@ int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned bufl
#endif
break;
default:
printk("sr%d: CDROM (ioctl) error, command: ", target);
printk(KERN_ERR "sr%d: CDROM (ioctl) error, command: ", target);
print_command(sr_cmd);
print_sense("sr", SCpnt);
err = -EIO;
......
......@@ -26,6 +26,7 @@ EXPORT_SYMBOL(num_audiodevs);
EXPORT_SYMBOL(note_to_freq);
EXPORT_SYMBOL(compute_finetune);
EXPORT_SYMBOL(seq_copy_to_input);
EXPORT_SYMBOL(seq_input_event);
EXPORT_SYMBOL(sequencer_init);
EXPORT_SYMBOL(sequencer_timer);
......@@ -61,6 +62,7 @@ EXPORT_SYMBOL(conf_printf2);
EXPORT_SYMBOL(sound_timer_init);
EXPORT_SYMBOL(sound_timer_interrupt);
EXPORT_SYMBOL(sound_timer_syncinterval);
EXPORT_SYMBOL(sound_timer_devs);
/* Locking */
EXPORT_SYMBOL(sound_locker);
......
......@@ -970,7 +970,7 @@ void cleanup_module(void)
if (mss)
unload_ss_ms_sound(&config);
SOUND_LOCK_END;
unload_sscape(&config);
unload_sscape(&mpu_config);
}
#endif
......
......@@ -4,7 +4,7 @@
O_TARGET := coda.o
O_OBJS := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o coda_linux.o\
symlink.o pioctl.o sysctl.o
symlink.o pioctl.o sysctl.o stats.o
M_OBJS := $(O_TARGET)
# If you want debugging output, please uncomment the following line
......
......@@ -32,9 +32,6 @@ static void coda_cache_create(struct inode *inode, int mask);
static struct coda_cache * coda_cache_find(struct inode *inode);
/* Keep various stats */
struct cfsnc_statistics cfsnc_stat;
/* insert a acl-cache entry in sb list */
static void coda_ccinsert(struct coda_cache *el, struct super_block *sb)
{
......@@ -295,41 +292,3 @@ void coda_flag_inode(struct inode *inode, int flag)
int
cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
int len=0;
off_t begin;
/* cfsnc_gather_stats(); */
/* this works as long as we are below 1024 characters! */
len += sprintf(buffer,"Coda minicache statistics\n\n");
len += sprintf(buffer+len, "cfsnc_hits : %d\n", cfsnc_stat.hits);
len += sprintf(buffer+len, "cfsnc_misses : %d\n", cfsnc_stat.misses);
len += sprintf(buffer+len, "cfsnc_enters : %d\n", cfsnc_stat.enters);
len += sprintf(buffer+len, "cfsnc_dbl_enters : %d\n", cfsnc_stat.dbl_enters);
len += sprintf(buffer+len, "cfsnc_long_name_enters : %d\n", cfsnc_stat.long_name_enters);
len += sprintf(buffer+len, "cfsnc_long_name_lookups : %d\n", cfsnc_stat.long_name_lookups);
len += sprintf(buffer+len, "cfsnc_long_remove : %d\n", cfsnc_stat.long_remove);
len += sprintf(buffer+len, "cfsnc_lru_rm : %d\n", cfsnc_stat.lru_rm);
len += sprintf(buffer+len, "cfsnc_zapPfids : %d\n", cfsnc_stat.zapPfids);
len += sprintf(buffer+len, "cfsnc_zapFids : %d\n", cfsnc_stat.zapFids);
len += sprintf(buffer+len, "cfsnc_zapFile : %d\n", cfsnc_stat.zapFile);
len += sprintf(buffer+len, "cfsnc_zapUsers : %d\n", cfsnc_stat.zapUsers);
len += sprintf(buffer+len, "cfsnc_Flushes : %d\n", cfsnc_stat.Flushes);
len += sprintf(buffer+len, "cfsnc_SumLen : %d\n", cfsnc_stat.Sum_bucket_len);
len += sprintf(buffer+len, "cfsnc_Sum2Len : %d\n", cfsnc_stat.Sum2_bucket_len);
len += sprintf(buffer+len, "cfsnc_# 0 len : %d\n", cfsnc_stat.Num_zero_len);
len += sprintf(buffer+len, "cfsnc_MaxLen : %d\n", cfsnc_stat.Max_bucket_len);
len += sprintf(buffer+len, "cfsnc_SearchLen : %d\n", cfsnc_stat.Search_len);
begin = offset;
*start = buffer + begin;
len -= begin;
if(len>length)
len = length;
if (len< 0)
len = 0;
return len;
}
......@@ -7,6 +7,7 @@
* the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
*/
#include <linux/version.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
......
......@@ -23,6 +23,7 @@
#include <linux/coda_psdev.h>
#include <linux/coda_fs_i.h>
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
/* dir inode-ops */
static int coda_create(struct inode *dir, struct dentry *new, int mode);
......@@ -179,6 +180,8 @@ int coda_permission(struct inode *inode, int mask)
int error;
ENTRY;
coda_vfs_stat.permission++;
coda_permission_stat.count++;
if ( mask == 0 ) {
EXIT;
......@@ -187,6 +190,7 @@ int coda_permission(struct inode *inode, int mask)
if ( coda_access_cache == 1 ) {
if ( coda_cache_check(inode, mask) ) {
coda_permission_stat.hit_count++;
return 0;
}
}
......@@ -221,6 +225,8 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode)
struct ViceFid newfid;
struct coda_vattr attrs;
coda_vfs_stat.create++;
CDEBUG(D_INODE, "name: %s, length %d, mode %o\n",name, length, mode);
if (!dir || !S_ISDIR(dir->i_mode)) {
......@@ -274,6 +280,8 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
struct ViceFid newfid;
coda_vfs_stat.mkdir++;
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("coda_mkdir: inode is NULL or not a directory\n");
return -ENOENT;
......@@ -329,6 +337,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
int error;
ENTRY;
coda_vfs_stat.link++;
if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
return -EPERM;
......@@ -373,6 +382,7 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
int error=0;
ENTRY;
coda_vfs_stat.symlink++;
if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
return -EPERM;
......@@ -414,6 +424,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
int len = de->d_name.len;
ENTRY;
coda_vfs_stat.unlink++;
dircnp = ITOC(dir);
CHECK_CNODE(dircnp);
......@@ -446,6 +457,8 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
int len = de->d_name.len;
int error, rehash = 0;
coda_vfs_stat.rmdir++;
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("coda_rmdir: inode is NULL or not a directory\n");
return -ENOENT;
......@@ -502,6 +515,8 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
struct coda_inode_info *new_cnp, *old_cnp;
int error, rehash = 0, update = 1;
ENTRY;
coda_vfs_stat.rename++;
old_cnp = ITOC(old_dir);
CHECK_CNODE(old_cnp);
new_cnp = ITOC(new_dir);
......@@ -565,6 +580,7 @@ int coda_readdir(struct file *file, void *dirent, filldir_t filldir)
struct inode *inode=file->f_dentry->d_inode;
ENTRY;
coda_vfs_stat.readdir++;
if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) {
printk("coda_readdir: inode is NULL or not a directory\n");
......@@ -606,6 +622,7 @@ int coda_open(struct inode *i, struct file *f)
unsigned short coda_flags = coda_flags_to_cflags(flags);
ENTRY;
coda_vfs_stat.open++;
CDEBUG(D_SPECIAL, "OPEN inode number: %ld, flags %o.\n",
f->f_dentry->d_inode->i_ino, flags);
......@@ -659,6 +676,7 @@ int coda_release(struct inode *i, struct file *f)
unsigned short cflags = coda_flags_to_cflags(flags);
ENTRY;
coda_vfs_stat.release++;
cnp =ITOC(i);
CHECK_CNODE(cnp);
......
......@@ -23,6 +23,7 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_psdev.h>
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
/* file operations */
static int coda_readpage(struct file *file, struct page * page);
......@@ -83,6 +84,7 @@ static int coda_readpage(struct file * coda_file, struct page * page)
struct coda_inode_info *cii;
ENTRY;
coda_vfs_stat.readpage++;
cii = ITOC(coda_inode);
......@@ -108,6 +110,8 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
struct coda_inode_info *cii;
int res;
coda_vfs_stat.file_mmap++;
ENTRY;
cii = ITOC(file->f_dentry->d_inode);
cii->c_mmcount++;
......@@ -126,7 +130,9 @@ static ssize_t coda_file_read(struct file *coda_file, char *buff,
struct file cont_file;
struct dentry cont_dentry;
int result = 0;
ENTRY;
coda_vfs_stat.file_read++;
cnp = ITOC(coda_inode);
CHECK_CNODE(cnp);
......@@ -167,6 +173,7 @@ static ssize_t coda_file_write(struct file *coda_file, const char *buff,
int result = 0;
ENTRY;
coda_vfs_stat.file_write++;
cnp = ITOC(coda_inode);
CHECK_CNODE(cnp);
......@@ -205,6 +212,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
struct dentry cont_dentry;
int result = 0;
ENTRY;
coda_vfs_stat.fsync++;
if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
S_ISLNK(coda_inode->i_mode)))
......
......@@ -44,7 +44,7 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_psdev.h>
#include <linux/coda_cache.h>
#include <linux/coda_sysctl.h>
#include <linux/coda_proc.h>
/*
......@@ -401,19 +401,106 @@ static struct file_operations coda_psdev_fops = {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry proc_coda = {
struct proc_dir_entry proc_sys_root = {
PROC_SYS, 3, "sys", /* inode, name */
S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, /* mode, nlink, uid, gid */
0, &proc_dir_inode_operations, /* size, ops */
NULL, NULL, /* get_info, fill_inode */
NULL, /* next */
NULL, NULL /* parent, subdir */
};
struct proc_dir_entry proc_fs_coda = {
PROC_FS_CODA, 4, "coda",
S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
0, &proc_dir_inode_operations,
NULL, NULL,
NULL,
NULL, NULL
};
struct proc_dir_entry proc_sys_coda = {
0, 4, "coda",
S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR, 2, 0, 0,
0, &proc_net_inode_operations,
S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
0, &proc_dir_inode_operations,
NULL, NULL,
NULL,
NULL, NULL
};
struct proc_dir_entry proc_fs = {
PROC_FS, 2, "fs",
S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
0, &proc_dir_inode_operations,
NULL, NULL,
NULL,
NULL, NULL
};
#if 0
struct proc_dir_entry proc_coda_ncstats = {
0 , 12, "coda-ncstats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
cfsnc_nc_info
};
#endif
struct proc_dir_entry proc_coda_vfs = {
PROC_VFS_STATS , 9, "vfs_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_vfs_stats_get_info
};
struct proc_dir_entry proc_coda_vfs_control = {
0 , 9, "vfs_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_vfs_stats_get_info
};
struct proc_dir_entry proc_coda_upcall = {
PROC_UPCALL_STATS , 12, "upcall_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_upcall_stats_get_info
};
struct proc_dir_entry proc_coda_upcall_control = {
0 , 12, "upcall_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_upcall_stats_get_info
};
struct proc_dir_entry proc_coda_permission = {
PROC_PERMISSION_STATS , 16, "permission_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_permission_stats_get_info
};
struct proc_dir_entry proc_coda_permission_control = {
0 , 16, "permission_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_permission_stats_get_info
};
struct proc_dir_entry proc_coda_cache_inv = {
PROC_CACHE_INV_STATS , 15, "cache_inv_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_cache_inv_stats_get_info
};
struct proc_dir_entry proc_coda_cache_inv_control = {
0 , 15, "cache_inv_stats",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
coda_cache_inv_stats_get_info
};
#endif
......@@ -429,9 +516,27 @@ int init_coda_psdev(void)
memset(coda_super_info, 0, sizeof(coda_super_info));
memset(&coda_callstats, 0, sizeof(coda_callstats));
reset_coda_vfs_stats();
reset_coda_upcall_stats();
reset_coda_permission_stats();
reset_coda_cache_inv_stats();
#ifdef CONFIG_PROC_FS
proc_register(&proc_root,&proc_coda);
proc_register(&proc_coda, &proc_coda_ncstats);
proc_register(&proc_root,&proc_fs);
proc_register(&proc_fs,&proc_fs_coda);
proc_register(&proc_fs_coda,&proc_coda_vfs);
proc_register(&proc_fs_coda,&proc_coda_upcall);
proc_register(&proc_fs_coda,&proc_coda_permission);
proc_register(&proc_fs_coda,&proc_coda_cache_inv);
#if 0
proc_register(&proc_fs_coda, &proc_coda_ncstats);
#endif
proc_register(&proc_sys_root,&proc_sys_coda);
proc_register(&proc_sys_coda,&proc_coda_vfs_control);
proc_register(&proc_sys_coda,&proc_coda_upcall_control);
proc_register(&proc_sys_coda,&proc_coda_permission_control);
proc_register(&proc_sys_coda,&proc_coda_cache_inv_control);
coda_sysctl_init();
#endif
return 0;
......@@ -476,8 +581,22 @@ void cleanup_module(void)
#if CONFIG_PROC_FS
coda_sysctl_clean();
proc_unregister(&proc_coda, proc_coda_ncstats.low_ino);
proc_unregister(&proc_root, proc_coda.low_ino);
proc_unregister(&proc_sys_coda, proc_coda_cache_inv_control.low_ino);
proc_unregister(&proc_sys_coda, proc_coda_permission_control.low_ino);
proc_unregister(&proc_sys_coda, proc_coda_upcall_control.low_ino);
proc_unregister(&proc_sys_coda,proc_coda_vfs_control.low_ino);
proc_unregister(&proc_sys_root, proc_sys_coda.low_ino);
#if 0
proc_unregister(&proc_fs_coda, proc_coda_ncstats.low_ino);
#endif
proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino);
proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino);
proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino);
proc_unregister(&proc_fs_coda, proc_coda_vfs.low_ino);
proc_unregister(&proc_fs, proc_fs_coda.low_ino);
proc_unregister(&proc_root, proc_fs.low_ino);
#endif
}
......
/*
* stats.c
*
* CODA operation statistics
*
* (c) March, 1998 Zhanyong Wan <zhanyong.wan@yale.edu>
*
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/swapctl.h>
#include <linux/proc_fs.h>
#include <linux/malloc.h>
#include <linux/stat.h>
#include <linux/ctype.h>
#include <asm/bitops.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/utsname.h>
#include <linux/coda.h>
#include <linux/coda_linux.h>
#include <linux/coda_fs_i.h>
#include <linux/coda_psdev.h>
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
struct coda_vfs_stats coda_vfs_stat;
struct coda_permission_stats coda_permission_stat;
struct coda_cache_inv_stats coda_cache_inv_stat;
struct coda_upcall_stats_entry coda_upcall_stat[CFS_NCALLS];
/* keep this in sync with coda.h! */
char *coda_upcall_names[] = {
"totals ", /* 0 */
"noop ", /* 1 */
"root ", /* 2 */
"sync ", /* 3 */
"open ", /* 4 */
"close ", /* 5 */
"ioctl ", /* 6 */
"getattr ", /* 7 */
"setattr ", /* 8 */
"access ", /* 9 */
"lookup ", /* 10 */
"create ", /* 11 */
"remove ", /* 12 */
"link ", /* 13 */
"rename ", /* 14 */
"mkdir ", /* 15 */
"rmdir ", /* 16 */
"readdir ", /* 17 */
"symlink ", /* 18 */
"readlink ", /* 19 */
"fsync ", /* 20 */
"inactive ", /* 21 */
"vget ", /* 22 */
"signal ", /* 23 */
"replace ", /* 24 */
"flush ", /* 25 */
"purgeuser ", /* 26 */
"zapfile ", /* 27 */
"zapdir ", /* 28 */
"zapvnode ", /* 28 */
"purgefid ", /* 30 */
"open_by_path" /* 31 */
};
void reset_coda_vfs_stats( void )
{
memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
}
#if 0
static void reset_upcall_entry( struct coda_upcall_stats_entry * pentry )
{
pentry->count = 0;
pentry->time_sum = pentry->time_squared_sum = 0;
}
#endif
void reset_coda_upcall_stats( void )
{
memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );
}
void reset_coda_permission_stats( void )
{
memset( &coda_permission_stat, 0, sizeof( coda_permission_stat ) );
}
void reset_coda_cache_inv_stats( void )
{
memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
}
void do_time_stats( struct coda_upcall_stats_entry * pentry,
unsigned long runtime )
{
unsigned long time = runtime * 1000 /HZ; /* time in ms */
CDEBUG(D_SPECIAL, "time: %ld\n", time);
if ( pentry->count == 0 ) {
pentry->time_sum = pentry->time_squared_sum = 0;
}
pentry->count++;
pentry->time_sum += time;
pentry->time_squared_sum += time*time;
}
void coda_upcall_stats(int opcode, long unsigned runtime)
{
struct coda_upcall_stats_entry * pentry;
if ( opcode < 0 || opcode > CFS_NCALLS - 1) {
printk("Nasty opcode %d passed to coda_upcall_stats\n",
opcode);
return;
}
pentry = &coda_upcall_stat[opcode];
do_time_stats(pentry, runtime);
/* fill in the totals */
pentry = &coda_upcall_stat[0];
do_time_stats(pentry, runtime);
}
unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry )
{
return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;
}
static inline unsigned long absolute( unsigned long x )
{
return x >= 0 ? x : -x;
}
static unsigned long sqr_root( unsigned long x )
{
unsigned long y = x, r;
int n_bit = 0;
if ( x == 0 )
return 0;
if ( x < 0)
x = -x;
while ( y ) {
y >>= 1;
n_bit++;
}
r = 1 << (n_bit/2);
while ( 1 ) {
r = (r + x/r)/2;
if ( r*r <= x && x < (r+1)*(r+1) )
break;
}
return r;
}
unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry )
{
unsigned long time_avg;
if ( pentry->count <= 1 )
return 0;
time_avg = get_time_average( pentry );
return
sqr_root( (pentry->time_squared_sum / pentry->count) -
time_avg * time_avg );
}
int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
void * buffer, size_t * lenp )
{
if ( write ) {
reset_coda_vfs_stats();
}
*lenp = 0;
return 0;
}
int do_reset_coda_upcall_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp )
{
if ( write ) {
reset_coda_upcall_stats();
}
*lenp = 0;
return 0;
}
int do_reset_coda_permission_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp )
{
if ( write ) {
reset_coda_permission_stats();
}
*lenp = 0;
return 0;
}
int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp )
{
if ( write ) {
reset_coda_cache_inv_stats();
}
*lenp = 0;
return 0;
}
int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy )
{
int len=0;
off_t begin;
struct coda_vfs_stats * ps = & coda_vfs_stat;
/* this works as long as we are below 1024 characters! */
len += sprintf( buffer,
"Coda VFS statistics\n"
"===================\n\n"
"File Operations:\n"
"\tfile_read\t%9d\n"
"\tfile_write\t%9d\n"
"\tfile_mmap\t%9d\n"
"\topen\t\t%9d\n"
"\trelase\t\t%9d\n"
"\tfsync\t\t%9d\n\n"
"Dir Operations:\n"
"\treaddir\t\t%9d\n\n"
"Inode Operations\n"
"\tcreate\t\t%9d\n"
"\tlookup\t\t%9d\n"
"\tlink\t\t%9d\n"
"\tunlink\t\t%9d\n"
"\tsymlink\t\t%9d\n"
"\tmkdir\t\t%9d\n"
"\trmdir\t\t%9d\n"
"\trename\t\t%9d\n"
"\tpermission\t%9d\n"
"\treadpage\t%9d\n",
/* file operations */
ps->file_read,
ps->file_write,
ps->file_mmap,
ps->open,
ps->release,
ps->fsync,
/* dir operations */
ps->readdir,
/* inode operations */
ps->create,
ps->lookup,
ps->link,
ps->unlink,
ps->symlink,
ps->mkdir,
ps->rmdir,
ps->rename,
ps->permission,
ps->readpage );
begin = offset;
*start = buffer + begin;
len -= begin;
if ( len > length )
len = length;
if ( len < 0 )
len = 0;
return len;
}
int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy )
{
int len=0;
int i;
off_t begin;
off_t pos = 0;
char tmpbuf[80];
int tmplen = 0;
ENTRY;
/* this works as long as we are below 1024 characters! */
if ( offset < 80 )
len += sprintf( buffer,"%-79s\n", "Coda upcall statistics");
if ( offset < 160)
len += sprintf( buffer + len,"%-79s\n", "======================");
if ( offset < 240)
len += sprintf( buffer + len,"%-79s\n", "upcall\t\t count\tavg time(ms)\tstd deviation(ms)");
if ( offset < 320)
len += sprintf( buffer + len,"%-79s\n", "------\t\t -----\t------------\t-----------------");
pos = 320;
for ( i = 0 ; i < CFS_NCALLS ; i++ ) {
tmplen += sprintf(tmpbuf,"%s\t%9d\t%10ld\t%10ld",
coda_upcall_names[i],
coda_upcall_stat[i].count,
get_time_average(&coda_upcall_stat[i]),
coda_upcall_stat[i].time_squared_sum);
pos += 80;
if ( pos < offset )
continue;
len += sprintf(buffer + len, "%-79s\n", tmpbuf);
if ( len >= length )
break;
}
begin = len- (pos - offset);
*start = buffer + begin;
len -= begin;
if ( len > length )
len = length;
if ( len < 0 )
len = 0;
EXIT;
return len;
}
int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy )
{
int len=0;
off_t begin;
struct coda_permission_stats * ps = & coda_permission_stat;
/* this works as long as we are below 1024 characters! */
len += sprintf( buffer,
"Coda permission statistics\n"
"==========================\n\n"
"count\t\t%9d\n"
"hit count\t%9d\n",
ps->count,
ps->hit_count );
begin = offset;
*start = buffer + begin;
len -= begin;
if ( len > length )
len = length;
if ( len < 0 )
len = 0;
return len;
}
int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy )
{
int len=0;
off_t begin;
struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
/* this works as long as we are below 1024 characters! */
len += sprintf( buffer,
"Coda cache invalidation statistics\n"
"==================================\n\n"
"flush\t\t%9d\n"
"purge user\t%9d\n"
"zap_dir\t\t%9d\n"
"zap_file\t%9d\n"
"zap_vnode\t%9d\n"
"purge_fid\t%9d\n"
"replace\t\t%9d\n",
ps->flush,
ps->purge_user,
ps->zap_dir,
ps->zap_file,
ps->zap_vnode,
ps->purge_fid,
ps->replace );
begin = offset;
*start = buffer + begin;
len -= begin;
if ( len > length )
len = length;
if ( len < 0 )
len = 0;
return len;
}
......@@ -23,6 +23,7 @@
#include <linux/coda_psdev.h>
#include <linux/coda_fs_i.h>
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
static int coda_readlink(struct dentry *de, char *buffer, int length);
static struct dentry *coda_follow_link(struct dentry *, struct dentry *);
......@@ -60,7 +61,7 @@ static int coda_readlink(struct dentry *de, char *buffer, int length)
ENTRY;
cp = ITOC(inode);
CHECK_CNODE(cp);
coda_vfs_stat.readlink++;
/* the maximum length we receive is len */
if ( length > CFS_MAXPATHLEN )
......@@ -93,11 +94,11 @@ static struct dentry *coda_follow_link(struct dentry *de,
unsigned int len;
char mem[CFS_MAXPATHLEN];
char *path;
ENTRY;
ENTRY;
CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
cnp = ITOC(inode);
CHECK_CNODE(cnp);
coda_vfs_stat.follow_link++;
len = CFS_MAXPATHLEN;
error = venus_readlink(inode->i_sb, &(cnp->c_fid), mem, &len);
......
......@@ -26,7 +26,7 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_psdev.h>
#include <linux/coda_cache.h>
#include <linux/coda_sysctl.h>
#include <linux/coda_proc.h>
extern int coda_debug;
/* extern int cfsnc_use; */
extern int coda_print_entry;
......@@ -47,6 +47,10 @@ struct ctl_table_header *fs_table_header, *coda_table_header;
#define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */
#define CODA_MC 4 /* use/do not use the access cache */
#define CODA_HARD 5 /* mount type "hard" or "soft" */
#define CODA_VFS 6 /* vfs statistics */
#define CODA_UPCALL 7 /* upcall statistics */
#define CODA_PERMISSION 8 /* permission statistics */
#define CODA_CACHE_INV 9 /* cache invalidation statistics */
......@@ -56,6 +60,10 @@ static ctl_table coda_table[] = {
{CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &coda_dointvec},
{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &coda_dointvec},
{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &coda_dointvec},
{CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
{CODA_UPCALL, "upcall_stats", NULL, 0, 0644, NULL, &do_reset_coda_upcall_stats},
{CODA_PERMISSION, "permission_stats", NULL, 0, 0644, NULL, &do_reset_coda_permission_stats},
{CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
{ 0 }
};
......
......@@ -37,6 +37,11 @@
#include <linux/coda_psdev.h>
#include <linux/coda_fs_i.h>
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize,
union inputArgs *buffer);
#define UPARG(op)\
do {\
......@@ -68,10 +73,11 @@ int venus_rootfid(struct super_block *sb, ViceFid *fidp)
union inputArgs *inp;
union outputArgs *outp;
int insize, outsize, error;
ENTRY;
ENTRY;
insize = SIZE(root);
UPARG(CFS_ROOT);
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
if (error) {
......@@ -583,11 +589,13 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
* reply and return Venus' error, also POSITIVE.
*
*/
static inline void coda_waitfor_upcall(struct vmsg *vmp)
static inline unsigned long coda_waitfor_upcall(struct vmsg *vmp)
{
struct wait_queue wait = { current, NULL };
unsigned long posttime;
vmp->vm_posttime = jiffies;
posttime = jiffies;
add_wait_queue(&vmp->vm_sleep, &wait);
for (;;) {
......@@ -616,13 +624,17 @@ static inline void coda_waitfor_upcall(struct vmsg *vmp)
remove_wait_queue(&vmp->vm_sleep, &wait);
current->state = TASK_RUNNING;
return;
CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n", posttime, jiffies-posttime);
return (jiffies - posttime);
}
int coda_upcall(struct coda_sb_info *sbi, int inSize, int *outSize,
static int coda_upcall(struct coda_sb_info *sbi,
int inSize, int *outSize,
union inputArgs *buffer)
{
unsigned long runtime;
struct vcomm *vcommp;
union outputArgs *out;
struct vmsg *vmp;
......@@ -635,7 +647,6 @@ ENTRY;
}
vcommp = sbi->sbi_vcomm;
clstats(((union inputArgs *)buffer)->ih.opcode);
if (!vcomm_open(vcommp))
return(ENODEV);
......@@ -670,7 +681,8 @@ ENTRY;
* ENODEV. */
/* Go to sleep. Wake up on signals only after the timeout. */
coda_waitfor_upcall(vmp);
runtime = coda_waitfor_upcall(vmp);
coda_upcall_stats(((union inputArgs *)buffer)->ih.opcode, runtime);
CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n",
vmp->vm_opcode, jiffies - vmp->vm_posttime,
......
......@@ -109,7 +109,11 @@ extern inline void get_mmu_context(struct task_struct *p)
#endif
}
#define init_new_context(mm) do { } while(0)
extern inline void init_new_context(struct mm_struct *mm)
{
mm->context = 0;
}
#define destroy_context(mm) do { } while(0)
#endif
......
/*
* coda_statis.h
*
* CODA operation statistics
*
* (c) March, 1998
* by Michihiro Kuramochi, Zhenyu Xia and Zhanyong Wan
* zhanyong.wan@yale.edu
*
*/
#ifndef _CODA_PROC_H
#define _CODA_PROC_H
void coda_sysctl_init(void);
void coda_sysctl_clean(void);
void coda_upcall_stats(int opcode, unsigned long jiffies);
#include <linux/sysctl.h>
#include <linux/coda_fs_i.h>
#include <linux/coda.h>
/* these four files are presented to show the result of the statistics:
*
* /proc/fs/coda/vfs_stats
* upcall_stats
* permission_stats
* cache_inv_stats
*
* these four files are presented to reset the statistics to 0:
*
* /proc/sys/coda/vfs_stats
* upcall_stats
* permission_stats
* cache_inv_stats
*/
/* VFS operation statistics */
struct coda_vfs_stats
{
/* file operations */
int file_read;
int file_write;
int file_mmap;
int open;
int release;
int fsync;
/* dir operations */
int readdir;
/* inode operations */
int create;
int lookup;
int link;
int unlink;
int symlink;
int mkdir;
int rmdir;
int rename;
int permission;
int readpage;
/* symlink operatoins*/
int follow_link;
int readlink;
};
struct coda_upcall_stats_entry
{
int count;
unsigned long time_sum;
unsigned long time_squared_sum;
};
/* cache hits for permissions statistics */
struct coda_permission_stats
{
int count;
int hit_count;
};
/* cache invalidation statistics */
struct coda_cache_inv_stats
{
int flush;
int purge_user;
int zap_dir;
int zap_file;
int zap_vnode;
int purge_fid;
int replace;
};
/* these global variables hold the actual statistics data */
extern struct coda_vfs_stats coda_vfs_stat;
extern struct coda_permission_stats coda_permission_stat;
extern struct coda_cache_inv_stats coda_cache_inv_stat;
/* reset statistics to 0 */
void reset_coda_vfs_stats( void );
void reset_coda_upcall_stats( void );
void reset_coda_permission_stats( void );
void reset_coda_cache_inv_stats( void );
/* some utitlities to make it easier for you to do statistics for time */
void do_time_stats( struct coda_upcall_stats_entry * pentry,
unsigned long jiffy );
/*
double get_time_average( const struct coda_upcall_stats_entry * pentry );
double get_time_std_deviation( const struct coda_upcall_stats_entry * pentry );
*/
unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry );
unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry );
/* like coda_dointvec, these functions are to be registered in the ctl_table
* data structure for /proc/sys/... files
*/
int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
void * buffer, size_t * lenp );
int do_reset_coda_upcall_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp );
int do_reset_coda_permission_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp );
int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp );
/* these functions are called to form the content of /proc/fs/coda/... files */
int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy );
int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy );
int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy );
int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
int length, int dummy );
#endif /* _CODA_PROC_H */
......@@ -94,8 +94,6 @@ int venus_access(struct super_block *sb, struct ViceFid *fid, int mask);
int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
unsigned int cmd, struct PioctlData *data);
int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
int coda_upcall(struct coda_sb_info *mntinfo, int inSize,
int *outSize, union inputArgs *buffer);
int venus_fsync(struct super_block *sb, struct ViceFid *fid);
......
/*
* Sysctl operations for Coda.
* Original version: (C) 1996 Peter Braam
* Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
*
* Carnegie Mellon encourages users of this code to contribute improvements
* to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
*/
void coda_sysctl_init(void);
void coda_sysctl_clean(void);
......@@ -131,7 +131,7 @@ extern int d_invalidate(struct dentry *);
/* dcache memory management */
extern int select_dcache(int, int);
extern void shrink_dcache_memory(void);
extern void shrink_dcache_memory(int, unsigned int);
extern void check_dcache_memory(void);
extern void free_inode_memory(int); /* defined in fs/inode.c */
......
This diff is collapsed.
......@@ -51,6 +51,7 @@ enum root_directory_inos {
PROC_PPC_HTAB,
PROC_SOUND,
PROC_MTRR, /* whether enabled or not */
PROC_FS
};
enum pid_directory_inos {
......@@ -205,6 +206,19 @@ enum bus_directory_inos {
PROC_BUS_LAST
};
enum fs_directory_inos {
PROC_FS_CODA = PROC_MCA_LAST,
PROC_FS_LAST
};
enum fs_coda_directory_inos {
PROC_VFS_STATS = PROC_MCA_LAST,
PROC_UPCALL_STATS,
PROC_PERMISSION_STATS,
PROC_CACHE_INV_STATS,
PROC_CODA_FS_LAST
};
/* Finally, the dynamically allocatable proc entries are reserved: */
#define PROC_DYNAMIC_FIRST 4096
......
......@@ -50,6 +50,15 @@ typedef struct freepages_v1
typedef freepages_v1 freepages_t;
extern freepages_t freepages;
typedef struct pager_daemon_v1
{
unsigned int tries_base;
unsigned int tries_min;
unsigned int swap_cluster;
} pager_daemon_v1;
typedef pager_daemon_v1 pager_daemon_t;
extern pager_daemon_t pager_daemon;
#define SC_VERSION 1
#define SC_MAX_VERSION 1
......
......@@ -84,7 +84,8 @@ enum
VM_BDFLUSH, /* struct: Control buffer cache flushing */
VM_OVERCOMMIT_MEMORY, /* Turn off the virtual memory safety limit */
VM_BUFFERMEM, /* struct: Set buffer memory thresholds */
VM_PAGECACHE /* struct: Set cache memory thresholds */
VM_PAGECACHE, /* struct: Set cache memory thresholds */
VM_PAGERDAEMON /* struct: Control kswapd behaviour */
};
......
......@@ -255,12 +255,12 @@ struct ufs_superblock {
__s32 fs_contigsumsize;/* size of cluster summary array */
__s32 fs_maxsymlinklen;/* max length of an internal symlink */
__s32 fs_inodefmt; /* format of on-disk inodes */
__u64 fs_maxfilesize; /* max representable file size */
__u32 fs_maxfilesize[2];/* max representable file size */
__u32 fs_qbmask[2]; /* ~usb_bmask */
__u32 fs_qfmask[2]; /* ~usb_fmask */
__s32 fs_state; /* file system state time stamp */
} fs_44;
} fs_u __attribute__ ((packed));
} fs_u;
__s32 fs_postblformat; /* format of positional layout tables */
__s32 fs_nrpos; /* number of rotational positions */
__s32 fs_postbloff; /* (__s16) rotation block list head */
......
......@@ -189,20 +189,22 @@ static ctl_table kern_table[] = {
static ctl_table vm_table[] = {
{VM_SWAPCTL, "swapctl",
&swap_control, sizeof(swap_control_t), 0600, NULL, &proc_dointvec},
&swap_control, sizeof(swap_control_t), 0644, NULL, &proc_dointvec},
{VM_SWAPOUT, "swapout_interval",
&swapout_interval, sizeof(int), 0600, NULL, &proc_dointvec},
&swapout_interval, sizeof(int), 0644, NULL, &proc_dointvec},
{VM_FREEPG, "freepages",
&freepages, sizeof(freepages_t), 0600, NULL, &proc_dointvec},
&freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec},
{VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&bdflush_min, &bdflush_max},
{VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
{VM_BUFFERMEM, "buffermem",
&buffer_mem, sizeof(buffer_mem_t), 0600, NULL, &proc_dointvec},
&buffer_mem, sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec},
{VM_PAGECACHE, "pagecache",
&page_cache, sizeof(buffer_mem_t), 0600, NULL, &proc_dointvec},
&page_cache, sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec},
{VM_PAGERDAEMON, "kswapd",
&pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
{0}
};
......
......@@ -9,7 +9,7 @@
O_TARGET := mm.o
O_OBJS := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
vmalloc.o slab.o simp.o\
vmalloc.o slab.o \
swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o
include $(TOPDIR)/Rules.make
......@@ -125,7 +125,7 @@ int free_memory_available(int nr)
* free unfragmented memory.
* Added low/high water marks to avoid thrashing -- Rik.
*/
if (nr_free_pages > (num_physpages >> 5) + (nr ? 0 : num_physpages >> 6))
if (nr_free_pages > (nr ? freepages.low : freepages.high))
return nr+1;
list = free_area + NR_MEM_LISTS;
......@@ -282,7 +282,6 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order)
spin_unlock_irqrestore(&page_alloc_lock, flags);
if (!(gfp_mask & __GFP_WAIT))
break;
shrink_dcache();
if (!try_to_free_pages(gfp_mask, SWAP_CLUSTER_MAX))
break;
gfp_mask &= ~__GFP_WAIT; /* go through this only once */
......@@ -335,15 +334,19 @@ __initfunc(unsigned long free_area_init(unsigned long start_mem, unsigned long e
int i;
/*
* select nr of pages we try to keep free for important stuff
* with a minimum of 48 pages. This is totally arbitrary
* Select nr of pages we try to keep free for important stuff
* with a minimum of 48 pages and a maximum of 256 pages, so
* that we don't waste too much memory on large systems.
* This is totally arbitrary.
*/
i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7);
if (i < 48)
i = 48;
if (i > 256)
i = 256;
freepages.min = i;
freepages.low = i + (i>>1);
freepages.high = i + i;
freepages.low = i << 1;
freepages.high = freepages.low + i;
mem_map = (mem_map_t *) LONG_ALIGN(start_mem);
p = mem_map + MAP_NR(end_mem);
start_mem = LONG_ALIGN((unsigned long) p);
......
......@@ -44,8 +44,8 @@
*/
freepages_t freepages = {
48, /* freepages.min */
72, /* freepages.low */
96 /* freepages.high */
96, /* freepages.low */
144 /* freepages.high */
};
/* We track the number of pages currently being asynchronously swapped
......@@ -77,3 +77,9 @@ buffer_mem_t page_cache = {
30, /* borrow percent page cache */
75 /* maximum */
};
pager_daemon_t pager_daemon = {
512, /* base number for calculating the number of tries */
SWAP_CLUSTER_MAX, /* minimum number of tries */
SWAP_CLUSTER_MAX, /* do swap I/O in clusters of this size */
};
......@@ -553,22 +553,23 @@ int kswapd(void *unused)
* more aggressive if we're really
* low on free memory.
*
* The number of tries is 512 divided by an
* 'urgency factor'. In practice this will mean
* a value of 512 / 8 = 64 pages at a time,
* giving 64 * 4 (times/sec) * 4k (pagesize) =
* 1 MB/s in lowest-priority background
* paging. This number rises to 8 MB/s when the
* priority is highest (but then we'll be woken
* up more often and the rate will be even higher).
* -- Should make this sysctl tunable...
* We try page_daemon.tries_base times, divided by
* an 'urgency factor'. In practice this will mean
* a value of pager_daemon.tries_base / 8 or 4 = 64
* or 128 pages at a time.
* This gives us 64 (or 128) * 4k * 4 (times/sec) =
* 1 (or 2) MB/s swapping bandwidth in low-priority
* background paging. This number rises to 8 MB/s
* when the priority is highest (but then we'll be
* woken up more often and the rate will be even
* higher).
*/
tries = (512) >> free_memory_available(3);
tries = pager_daemon.tries_base >> free_memory_available(3);
while (tries--) {
int gfp_mask;
if (++tried > SWAP_CLUSTER_MAX && free_memory_available(0))
if (++tried > pager_daemon.tries_min && free_memory_available(0))
break;
gfp_mask = __GFP_IO;
try_to_free_page(gfp_mask);
......@@ -576,7 +577,7 @@ int kswapd(void *unused)
* Syncing large chunks is faster than swapping
* synchronously (less head movement). -- Rik.
*/
if (atomic_read(&nr_async_pages) >= SWAP_CLUSTER_MAX)
if (atomic_read(&nr_async_pages) >= pager_daemon.swap_cluster)
run_task_queue(&tq_disk);
}
......
......@@ -53,10 +53,6 @@
#
# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
# texts.
#
# 100498 Riley Williams (rhw@bigfoot.com) - added ability to display
# blank lines in help texts: Any line consisting only of a single dot
# will be displayed blank.
#
# Make sure we're really running bash.
......@@ -107,7 +103,7 @@ ${var}:\\
then
echo; echo " Sorry, no help available for this option yet.";echo
else
(echo; echo "$text") | sed 's/^\.$//' | ${PAGER:-more}
(echo; echo "$text") | ${PAGER:-more}
fi
else
echo;
......
......@@ -47,13 +47,6 @@
#
# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
# texts.
#----------------------------------------------------------------------------
#
# 10 Apr 1998 - Added ability to display blank lines in help text: Any line
# which only contains a single dot will be displayed blank.
# Author: Riley Williams <rhw@bigfoot.com>
#
#----------------------------------------------------------------------------
#
......@@ -301,7 +294,7 @@ ${var}:\\
echo "There is no help available for this kernel option."
return 1
else
echo "$text" | sed 's/^\.$//'
echo "$text"
fi
else
echo "There is no help available for this kernel option."
......
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