Commit 717def95 authored by Linus Torvalds's avatar Linus Torvalds

Stephen Tweedie:

* 2.1.88, adds a bunch of new functionality to
  the swapper.  The main changes are:

* All swapping goes through the swap cache (aka. page cache) now.

* There is no longer a swap lock map.  Because we need to atomically
  test and create a new swap-cache page in order to do swap IO, it is
  sufficient just to lock the struct page itself.  Having only one
  layer of locking to deal with removes a number of races concerning
  swapping shared pages.

* We can swap shared pages, and still keep them shared when they are
  swapped back in!!!  Currently, only private shared pages (as in pages
  shared after a fork()) benefit from this, but the basic mechanism will
  be appropriate for MAP_ANONYMOUS | MAP_SHARED pages too
  (implementation to follow).  Pages will remain shared after a swapoff.

* The page cache is now quite happy dealing with swap-cache pages too.
  In particular, write-ahead and read-ahead of swap through the page
  cache will work fine (and in fact, write-ahead does get done already
  under certain circumstances with this patch --- that's essentially how
  the swapping of shared pages gets done).  Support code to perform
  asynchronous readahead of swap is included, but is not actually used
  anywhere yet.

  I've tested with a number of forked processes running with a shared
  working set larger than physical memory, and with SysV shared memory.
  I haven't found any problems with it so far.

Linus: I've also changed the way we consider us to need more memory in kswapd,
       but that was entirely orthogonal and did not impact these patches. ]

[Changelog pieced together by davej]
parent 3c99713c
......@@ -1841,10 +1841,12 @@ S: 2612 XV Delft
S: The Netherlands
N: David Woodhouse
E: dwmw2@cam.ac.uk
E: Dave@imladris.demon.co.uk
D: Extensive ARCnet rewrite
D: ARCnet COM20020, COM90xx IO-MAP drivers
D: SO_BINDTODEVICE in 2.1.x (from Elliot Poger's code in 2.0.31)
D: Contributed to NCPFS rewrite for 2.1.x dcache
D: Alpha platforms: SX164, LX164 and Ruffian ported to 2.1.x
S: Robinson College, Grange Road
S: Cambridge. CB3 9AN
S: England
......
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 88
SUBLEVEL = 89
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
......@@ -46,6 +46,8 @@ choice 'Alpha system type' \
EB64+ CONFIG_ALPHA_EB64P \
EB164 CONFIG_ALPHA_EB164 \
PC164 CONFIG_ALPHA_PC164 \
LX164 CONFIG_ALPHA_LX164 \
SX164 CONFIG_ALPHA_SX164 \
Jensen CONFIG_ALPHA_JENSEN \
Noname CONFIG_ALPHA_NONAME \
Mikasa CONFIG_ALPHA_MIKASA \
......@@ -54,6 +56,7 @@ choice 'Alpha system type' \
Miata CONFIG_ALPHA_MIATA \
Sable CONFIG_ALPHA_SABLE \
AlphaBook1 CONFIG_ALPHA_BOOK1 \
Ruffian CONFIG_ALPHA_RUFFIAN \
Platform2000 CONFIG_ALPHA_P2K" Cabriolet
if [ "$CONFIG_ALPHA_BOOK1" = "y" ]
......@@ -102,7 +105,8 @@ then
define_bool CONFIG_ALPHA_EV4 y
define_bool CONFIG_ALPHA_T2 y
fi
if [ "$CONFIG_ALPHA_MIATA" = "y" ]
if [ "$CONFIG_ALPHA_MIATA" = "y" -o "$CONFIG_ALPHA_LX164" = "y" \
-o "$CONFIG_ALPHA_SX164" = "y" -o "$CONFIG_ALPHA_RUFFIAN" = "y" ]
then
define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_EV5 y
......@@ -122,7 +126,8 @@ if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
-o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \
-o "$CONFIG_ALPHA_MIKASA" = "y" -o "$CONFIG_ALPHA_ALCOR" = "y" \
-o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \
-o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" ]
-o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \
-o "$CONFIG_ALPHA_LX164" = "y" -o "$CONFIG_ALPHA_SX164" = "y" ]
then
bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
fi
......
......@@ -35,6 +35,13 @@ endif
ifdef CONFIG_ALPHA_T2
O_OBJS += t2.o
endif
ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),nn)
O_OBJS += smc37c93x.o
endif
ifdef CONFIG_ALPHA_SX164
O_OBJS += smc37c669.o
endif
all: kernel.o head.o
......
This diff is collapsed.
This diff is collapsed.
......@@ -375,6 +375,10 @@ unsigned long pyxis_init(unsigned long mem_start, unsigned long mem_end)
mb() ;
pyxis_err = *(vuip)PYXIS_ERR ;
#ifdef CONFIG_ALPHA_RUFFIAN
printk("pyxis_init: Skipping window register rewrites --"
" trust DeskStation firmware!\n");
#else
/*
* Set up the PCI->physical memory translation windows.
* For now, windows 1,2 and 3 are disabled. In the future, we may
......@@ -390,6 +394,7 @@ unsigned long pyxis_init(unsigned long mem_start, unsigned long mem_end)
*(vuip)PYXIS_W2_BASE = 0x0 ;
*(vuip)PYXIS_W3_BASE = 0x0 ;
mb();
#endif
/*
* check ASN in HWRPB for validity, report if bad
......@@ -510,3 +515,42 @@ void pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
}
#endif
}
#if defined(CONFIG_ALPHA_RUFFIAN)
/* Note: This is only used by MILO, AFAIK... */
/*
* The DeskStation Ruffian motherboard firmware does not place
* the memory size in the PALimpure area. Therefore, we use
* the Bank Configuration Registers in PYXIS to obtain the size.
*/
unsigned long pyxis_get_bank_size(unsigned long offset)
{
unsigned long bank_addr, bank, ret = 0;
/* Valid offsets are: 0x800, 0x840 and 0x880
since Ruffian only uses three banks. */
bank_addr = (unsigned long)PYXIS_MCR + offset;
bank = *(vulp)bank_addr;
/* Check BANK_ENABLE */
if (bank & 0x01) {
static unsigned long size[] = {
0x40000000UL, /* 0x00, 1G */
0x20000000UL, /* 0x02, 512M */
0x10000000UL, /* 0x04, 256M */
0x08000000UL, /* 0x06, 128M */
0x04000000UL, /* 0x08, 64M */
0x02000000UL, /* 0x0a, 32M */
0x01000000UL, /* 0x0c, 16M */
0x00800000UL, /* 0x0e, 8M */
0x80000000UL, /* 0x10, 2G */
};
bank = (bank & 0x1e) >> 1;
if (bank < sizeof(size)/sizeof(*size))
ret = size[bank];
}
return ret;
}
#endif /* CONFIG_ALPHA_RUFFIAN */
......@@ -107,11 +107,13 @@ static void init_pit (void)
outb(LATCH >> 8, 0x40); /* MSB */
request_region(0x40, 0x20, "timer"); /* reserve pit */
#else
#ifndef CONFIG_ALPHA_RUFFIAN
outb(0x36, 0x43); /* counter 0: system timer */
outb(0x00, 0x40);
outb(0x00, 0x40);
request_region(0x70, 0x10, "timer"); /* reserve rtc */
#endif
request_region(0x70, 0x10, "timer"); /* reserve rtc */
#endif /* RTC */
outb(0xb6, 0x43); /* counter 2: speaker */
outb(0x31, 0x42);
......@@ -186,38 +188,115 @@ void setup_arch(char **cmdline_p,
#endif
}
#define N(a) (sizeof(a)/sizeof(a[0]))
static void
get_sysnames(long type, long variation,
char **type_name, char **variation_name)
{
static char *sys_unknown = "Unknown";
static char *systype_names[] = {
"0",
"ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
"Pelican", "Morgan", "Sable", "Medulla", "Noname",
"Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
"Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
"Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
"Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
"Tsunami", "Wildfire", "CUSCO"
};
static char *unofficial_names[] = {"100", "Ruffian"};
static char * eb164_names[] = {"EB164", "PC164", "LX164", "SX164"};
static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
static char * alcor_names[] = {"Alcor", "Maverick", "Bret"};
static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
static char * eb64p_names[] = {"EB64+", "Cabriolet", "AlphaPCI64"};
static int eb64p_indices[] = {0,0,1.2};
static char * eb66_names[] = {"EB66", "EB66+"};
static int eb66_indices[] = {0,0,1};
long member;
/* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */
if (type < 0)
type = -type;
/* If not in the tables, make it UNKNOWN,
else set type name to family */
if (type < N(systype_names)) {
*type_name = systype_names[type];
} else if ((type > ST_UNOFFICIAL_BIAS) &&
(type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) {
*type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
} else {
*type_name = sys_unknown;
*variation_name = sys_unknown;
return;
}
/* Set variation to "0"; if variation is zero, done */
*variation_name = systype_names[0];
if (variation == 0) {
return;
}
member = (variation >> 10) & 0x3f; /* member ID is a bit-field */
switch (type) {
case ST_DEC_EB164:
if (member < N(eb164_indices))
*variation_name = eb164_names[eb164_indices[member]];
break;
case ST_DEC_ALCOR:
if (member < N(alcor_indices))
*variation_name = alcor_names[alcor_indices[member]];
break;
case ST_DEC_EB64P:
if (member < N(eb64p_indices))
*variation_name = eb64p_names[eb64p_indices[member]];
break;
case ST_DEC_EB66:
if (member < N(eb66_indices))
*variation_name = eb66_names[eb66_indices[member]];
break;
}
}
/*
* BUFFER is PAGE_SIZE bytes long.
*/
int get_cpuinfo(char *buffer)
{
const char *cpu_name[] = {
"EV3", "EV4", "Unknown 1", "LCA4", "EV5", "EV45", "EV56",
"EV6", "PCA56"
static char *cpu_names[] = {
"EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56",
"EV6", "PCA56", "PCA57"
};
# define SYSTYPE_NAME_BIAS 20
const char *systype_name[] = {
"Cabriolet", "EB66P", "-18", "-17", "-16", "-15",
"-14", "-13", "-12", "-11", "-10", "-9", "-8",
"-7", "-6", "-5", "-4", "-3", "-2", "-1", "0",
"ADU", "Cobra", "Ruby", "Flamingo", "5", "Jensen",
"Pelican", "8", "Sable", "AXPvme", "Noname",
"Turbolaser", "Avanti", "Mustang", "Alcor", "16",
"Mikasa", "18", "EB66", "EB64+", "AlphaBook1",
"Rawhide", "Lego", "Lynx", "25", "EB164", "Noritake",
"Cortex", "29", "Miata", "31", "Takara", "Yukon"
};
struct percpu_struct *cpu;
unsigned int cpu_index;
long sysname_index;
extern struct unaligned_stat {
unsigned long count, va, pc;
} unaligned[2];
# define N(a) (sizeof(a)/sizeof(a[0]))
struct percpu_struct *cpu;
unsigned int cpu_index;
char *cpu_name;
char *systype_name;
char *sysvariation_name;
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
cpu_index = (unsigned) (cpu->type - 1);
sysname_index = hwrpb->sys_type + SYSTYPE_NAME_BIAS;
cpu_name = "Unknown";
if (cpu_index < N(cpu_names))
cpu_name = cpu_names[cpu_index];
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
&systype_name, &sysvariation_name);
return sprintf(buffer,
"cpu\t\t\t: Alpha\n"
......@@ -226,7 +305,7 @@ int get_cpuinfo(char *buffer)
"cpu revision\t\t: %ld\n"
"cpu serial number\t: %s\n"
"system type\t\t: %s\n"
"system variation\t: %ld\n"
"system variation\t: %s\n"
"system revision\t\t: %ld\n"
"system serial number\t: %s\n"
"cycle frequency [Hz]\t: %lu\n"
......@@ -238,12 +317,9 @@ int get_cpuinfo(char *buffer)
"kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
"user unaligned acc\t: %ld (pc=%lx,va=%lx)\n",
(cpu_index < N(cpu_name)
? cpu_name[cpu_index] : "Unknown"),
cpu->variation, cpu->revision, (char*)cpu->serial_no,
(sysname_index < N(systype_name)
? systype_name[sysname_index] : "Unknown"),
hwrpb->sys_variation, hwrpb->sys_revision,
cpu_name, cpu->variation, cpu->revision,
(char*)cpu->serial_no,
systype_name, sysvariation_name, hwrpb->sys_revision,
(char*)hwrpb->ssn,
hwrpb->cycle_freq,
hwrpb->intr_freq / 4096,
......@@ -254,5 +330,4 @@ int get_cpuinfo(char *buffer)
loops_per_sec / 500000, (loops_per_sec / 5000) % 100,
unaligned[0].count, unaligned[0].pc, unaligned[0].va,
unaligned[1].count, unaligned[1].pc, unaligned[1].va);
# undef N
}
This diff is collapsed.
/*
* SMC 37C93X initialization code
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/malloc.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <asm/hwrpb.h>
#include <asm/io.h>
#include <asm/segment.h>
#if 0
# define DBG_DEVS(args) printk args
#else
# define DBG_DEVS(args)
#endif
#define KB 1024
#define MB (1024*KB)
#define GB (1024*MB)
/* device "activate" register contents */
#define DEVICE_ON 1
#define DEVICE_OFF 0
/* configuration on/off keys */
#define CONFIG_ON_KEY 0x55
#define CONFIG_OFF_KEY 0xaa
/* configuration space device definitions */
#define FDC 0
#define IDE1 1
#define IDE2 2
#define PARP 3
#define SER1 4
#define SER2 5
#define RTCL 6
#define KYBD 7
#define AUXIO 8
/* Chip register offsets from base */
#define CONFIG_CONTROL 0x02
#define INDEX_ADDRESS 0x03
#define LOGICAL_DEVICE_NUMBER 0x07
#define DEVICE_ID 0x20
#define DEVICE_REV 0x21
#define POWER_CONTROL 0x22
#define POWER_MGMT 0x23
#define OSC 0x24
#define ACTIVATE 0x30
#define ADDR_HI 0x60
#define ADDR_LO 0x61
#define INTERRUPT_SEL 0x70
#define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */
#define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */
#define FDD_MODE_REGISTER 0x90
#define FDD_OPTION_REGISTER 0x91
/* values that we read back that are expected ... */
#define VALID_DEVICE_ID 2
/* default device addresses */
#define KYBD_INTERRUPT 1
#define MOUS_INTERRUPT 12
#define COM2_BASE 0x2f8
#define COM2_INTERRUPT 3
#define COM1_BASE 0x3f8
#define COM1_INTERRUPT 4
#define PARP_BASE 0x3bc
#define PARP_INTERRUPT 7
#define SMC_DEBUG 0
static unsigned long __init SMCConfigState(unsigned long baseAddr)
{
unsigned char devId;
unsigned char devRev;
unsigned long configPort;
unsigned long indexPort;
unsigned long dataPort;
configPort = indexPort = baseAddr;
dataPort = configPort + 1;
outb(CONFIG_ON_KEY, configPort);
outb(CONFIG_ON_KEY, configPort);
outb(DEVICE_ID, indexPort);
devId = inb(dataPort);
if ( devId == VALID_DEVICE_ID ) {
outb(DEVICE_REV, indexPort);
devRev = inb(dataPort);
}
else {
baseAddr = 0;
}
return baseAddr;
}
static void __init SMCRunState(unsigned long baseAddr)
{
outb(CONFIG_OFF_KEY, baseAddr);
}
static unsigned long __init SMCDetectUltraIO(void)
{
unsigned long baseAddr;
baseAddr = 0x3F0;
if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) {
return( baseAddr );
}
baseAddr = 0x370;
if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) {
return( baseAddr );
}
return( ( unsigned long )0 );
}
static void __init SMCEnableDevice(unsigned long baseAddr,
unsigned long device,
unsigned long portaddr,
unsigned long interrupt)
{
unsigned long indexPort;
unsigned long dataPort;
indexPort = baseAddr;
dataPort = baseAddr + 1;
outb(LOGICAL_DEVICE_NUMBER, indexPort);
outb(device, dataPort);
outb(ADDR_LO, indexPort);
outb(( portaddr & 0xFF ), dataPort);
outb(ADDR_HI, indexPort);
outb((portaddr >> 8) & 0xFF, dataPort);
outb(INTERRUPT_SEL, indexPort);
outb(interrupt, dataPort);
outb(ACTIVATE, indexPort);
outb(DEVICE_ON, dataPort);
}
static void __init SMCEnableKYBD(unsigned long baseAddr)
{
unsigned long indexPort;
unsigned long dataPort;
indexPort = baseAddr;
dataPort = baseAddr + 1;
outb(LOGICAL_DEVICE_NUMBER, indexPort);
outb(KYBD, dataPort);
outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
outb(KYBD_INTERRUPT, dataPort);
outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */
outb(MOUS_INTERRUPT, dataPort);
outb(ACTIVATE, indexPort);
outb(DEVICE_ON, dataPort);
}
static void __init SMCEnableFDC(unsigned long baseAddr)
{
unsigned long indexPort;
unsigned long dataPort;
unsigned char oldValue;
indexPort = baseAddr;
dataPort = baseAddr + 1;
outb(LOGICAL_DEVICE_NUMBER, indexPort);
outb(FDC, dataPort);
outb(FDD_MODE_REGISTER, indexPort);
oldValue = inb(dataPort);
oldValue |= 0x0E; /* Enable burst mode */
outb(oldValue, dataPort);
outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
outb(0x06, dataPort );
outb(DMA_CHANNEL_SEL, indexPort); /* DMA channel select */
outb(0x02, dataPort);
outb(ACTIVATE, indexPort);
outb(DEVICE_ON, dataPort);
}
#if SMC_DEBUG
static void __init SMCReportDeviceStatus(unsigned long baseAddr)
{
unsigned long indexPort;
unsigned long dataPort;
unsigned char currentControl;
indexPort = baseAddr;
dataPort = baseAddr + 1;
outb(POWER_CONTROL, indexPort);
currentControl = inb(dataPort);
printk(currentControl & (1 << FDC)
? "\t+FDC Enabled\n" : "\t-FDC Disabled\n");
printk(currentControl & (1 << IDE1)
? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n");
printk(currentControl & (1 << IDE2)
? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n");
printk(currentControl & (1 << PARP)
? "\t+PARP Enabled\n" : "\t-PARP Disabled\n");
printk(currentControl & (1 << SER1)
? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n");
printk(currentControl & (1 << SER2)
? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n");
printk( "\n" );
}
#endif
int __init SMC93x_Init(void)
{
unsigned long SMCUltraBase;
if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) {
printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
SMCUltraBase);
#if SMC_DEBUG
SMCReportDeviceStatus(SMCUltraBase);
#endif
SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT);
SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT);
SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT);
/* On PC164, IDE on the SMC is not enabled;
CMD646 (PCI) on MB */
SMCEnableKYBD(SMCUltraBase);
SMCEnableFDC(SMCUltraBase);
#if SMC_DEBUG
SMCReportDeviceStatus(SMCUltraBase);
#endif
SMCRunState(SMCUltraBase);
return 1;
}
else {
#if SMC_DEBUG
printk("No SMC FDC37C93X Ultra I/O Controller found\n");
#endif
return 0;
}
}
......@@ -33,31 +33,6 @@ static int read_ldt(void * ptr, unsigned long bytecount)
return copy_to_user(ptr, address, size) ? -EFAULT : size;
}
static inline int limits_ok(struct modify_ldt_ldt_s *ldt_info)
{
unsigned long base, limit;
/* linear address of first and last accessible byte */
unsigned long first, last;
base = ldt_info->base_addr;
limit = ldt_info->limit;
if (ldt_info->limit_in_pages)
limit = limit * PAGE_SIZE + PAGE_SIZE - 1;
first = base;
last = limit + base;
/* segment grows down? */
if (ldt_info->contents == 1) {
/* data segment grows down */
first = base+limit+1;
last = base+65535;
if (ldt_info->seg_32bit)
last = base-1;
}
return (last >= first && last < TASK_SIZE);
}
static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
{
struct modify_ldt_ldt_s ldt_info;
......@@ -73,9 +48,6 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
if ((ldt_info.contents == 3 && (oldmode || ldt_info.seg_not_present == 0)) || ldt_info.entry_number >= LDT_ENTRIES)
return -EINVAL;
if (!limits_ok(&ldt_info) && (oldmode || ldt_info.seg_not_present == 0))
return -EINVAL;
if (!current->ldt) {
for (i=1 ; i<NR_TASKS ; i++) {
if (task[i] == current) {
......
......@@ -116,7 +116,6 @@
* 16/11/96 - Fiddled and frigged for 2.0.18
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
......
......@@ -36,7 +36,6 @@
* $Log: cumana_NCR5380.c,v $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
......
......@@ -35,7 +35,6 @@
* $Log: ecoscsi_NCR5380.c,v $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
......
......@@ -35,7 +35,6 @@
* $Log: oak.c,v $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
......
......@@ -148,7 +148,7 @@ static int allowed_drive_mask = 0x33;
#include <asm/io.h>
#include <asm/uaccess.h>
static int can_use_virtual_dma=0;
static int can_use_virtual_dma=2;
/* =======
* can use virtual DMA:
* 0 = use of virtual DMA disallowed by config
......@@ -2083,7 +2083,7 @@ static void format_interrupt(void)
#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
#define CT(x) ((x) | 0x40)
#define CT(x) ((x) | 0xc0)
static void setup_format_params(int track)
{
struct fparm {
......@@ -2465,6 +2465,32 @@ static inline int check_dma_crossing(char *start,
}
#endif
/* work around a bug in pseudo DMA
* (on some FDCs) pseudo DMA does not stop when the CPU stops
* sending data. Hence we need a different way to signal the
* transfer length: We use SECT_PER_TRACK. Unfortunately, this
* does not work with MT, hence we can only transfer one head at
* a time
*/
static int virtualdmabug_workaround() {
int hard_sectors, end_sector;
if(CT(COMMAND) == FD_WRITE) {
COMMAND &= ~0x80; /* switch off multiple track mode */
hard_sectors = raw_cmd->length >> (7 + SIZECODE);
end_sector = SECTOR + hard_sectors - 1;
#ifdef FLOPPY_SANITY_CHECK
if(end_sector > SECT_PER_TRACK) {
printk("too many sectors %d > %d\n",
end_sector, SECT_PER_TRACK);
return 0;
}
#endif
SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points
* to end of transfer */
}
}
/*
* Formulate a read/write request.
* this routine decides where to load the data (directly to buffer, or to
......@@ -2541,11 +2567,17 @@ static int make_raw_rw_request(void)
CODE2SIZE;
SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
SECTOR = ((sector_t % _floppy->sect) << 2 >> SIZECODE) + 1;
/* tracksize describes the size which can be filled up with sectors
* of size ssize.
*/
tracksize = _floppy->sect - _floppy->sect % ssize;
if (tracksize < _floppy->sect){
SECT_PER_TRACK ++;
if (tracksize <= sector_t % _floppy->sect)
SECTOR--;
/* if we are beyond tracksize, fill up using smaller sectors */
while (tracksize <= sector_t % _floppy->sect){
while(tracksize + ssize > _floppy->sect){
SIZECODE--;
......@@ -2555,8 +2587,12 @@ static int make_raw_rw_request(void)
tracksize += ssize;
}
max_sector = HEAD * _floppy->sect + tracksize;
} else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing)
} else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) {
max_sector = _floppy->sect;
} else if (!HEAD && CT(COMMAND) == FD_WRITE) {
/* for virtual DMA bug workaround */
max_sector = _floppy->sect;
}
aligned_sector_t = sector_t - (sector_t % _floppy->sect) % ssize;
max_size = CURRENT->nr_sectors;
......@@ -2625,6 +2661,8 @@ static int make_raw_rw_request(void)
/* check_dma_crossing(raw_cmd->kernel_data,
raw_cmd->length,
"end of make_raw_request [1]");*/
virtualdmabug_workaround();
return 2;
}
}
......@@ -2730,6 +2768,8 @@ static int make_raw_rw_request(void)
return 0;
}
#endif
virtualdmabug_workaround();
return 2;
}
......
This diff is collapsed.
......@@ -123,7 +123,7 @@ dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
# The actual configuration in any kernel release could change at any time as I hack it to
# simulate various conditions that I am testing.
#
if [ "`whoami`" = "eric" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
fi
if [ "$CONFIG_PPC" = "y" ]; then
......
......@@ -471,7 +471,7 @@ static void do_sr_request (void)
{
spin_unlock_irqrestore(&io_request_lock, flags);
scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
/* scsi_ioctl may allow CURRENT to change, so start over. *
/* scsi_ioctl may allow CURRENT to change, so start over. */
SDev->was_reset = 0;
continue;
}
......
......@@ -5,8 +5,6 @@
#include <linux/unistd.h>
#include <asm/uaccess.h>
static int errno;
static int do_mod_firmware_load(const char *fn, char **fp)
{
int fd;
......
......@@ -1321,14 +1321,13 @@ static struct buffer_head * create_buffers(unsigned long page,
/* Run the hooks that have to be done when a page I/O has completed. */
static inline void after_unlock_page (struct page * page)
{
if (test_and_clear_bit(PG_decr_after, &page->flags))
if (test_and_clear_bit(PG_decr_after, &page->flags)) {
atomic_dec(&nr_async_pages);
if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) {
/*
* We're doing a swap, so check that this page is
* swap-cached and do the necessary cleanup.
*/
swap_after_unlock_page(page->offset);
#ifdef DEBUG_SWAP
printk ("DebugVM: Finished IO on page %p, nr_async_pages %d\n",
(char *) page_address(page),
atomic_read(&nr_async_pages));
#endif
}
if (test_and_clear_bit(PG_free_after, &page->flags))
__free_page(page);
......
......@@ -105,7 +105,7 @@ struct inode_operations fat_file_inode_operations_1024 = {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
generic_readpage, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
fat_truncate, /* truncate */
......
......@@ -701,19 +701,22 @@ void iput(struct inode *inode)
list_add(&inode->i_list, inode_in_use.prev);
}
#ifdef INODE_PARANOIA
if (inode->i_flock)
printk(KERN_ERR "iput: inode %s/%ld still has locks!\n",
kdevname(inode->i_dev), inode->i_ino);
if (!list_empty(&inode->i_dentry))
printk("iput: device %s inode %ld still has aliases!\n",
printk(KERN_ERR "iput: device %s inode %ld still has aliases!\n",
kdevname(inode->i_dev), inode->i_ino);
if (inode->i_count)
printk("iput: device %s inode %ld count changed, count=%d\n",
printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n",
kdevname(inode->i_dev), inode->i_ino, inode->i_count);
if (atomic_read(&inode->i_sem.count) != 1)
printk("iput: Aieee, semaphore in use device %s, count=%d\n",
printk(KERN_ERR "iput: Aieee, semaphore in use device %s, count=%d\n",
kdevname(inode->i_dev), atomic_read(&inode->i_sem.count));
#endif
}
if (inode->i_count > (1<<15)) {
printk("iput: device %s inode %ld count wrapped\n",
if (inode->i_count > (1<<31)) {
printk(KERN_ERR "iput: inode %s/%ld count wrapped\n",
kdevname(inode->i_dev), inode->i_ino);
}
spin_unlock(&inode_lock);
......
......@@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/fcntl.h> /* for f_flags values */
#include <linux/file.h>
#include <asm/uaccess.h>
......@@ -52,7 +53,8 @@ asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
int on, error = -EBADF;
lock_kernel();
if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
filp = fget(fd);
if (!filp)
goto out;
error = 0;
switch (cmd) {
......@@ -90,13 +92,16 @@ asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
break;
default:
if (filp->f_dentry && filp->f_dentry->d_inode && S_ISREG(filp->f_dentry->d_inode->i_mode))
error = -ENOTTY;
if (!filp->f_dentry || !filp->f_dentry->d_inode)
error = -ENOENT;
else if (S_ISREG(filp->f_dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
else if (filp->f_op && filp->f_op->ioctl)
error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
else
error = -ENOTTY;
}
fput(filp);
out:
unlock_kernel();
return error;
......
......@@ -101,11 +101,12 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
unsigned int block, offset;
int inode_number;
int inode_number = 0; /* Quiet GCC */
struct buffer_head *bh;
int len;
int map;
int high_sierra = 0;
int high_sierra;
int first_de = 1;
char *p = NULL; /* Quiet GCC */
struct iso_directory_record *de;
......@@ -114,6 +115,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
offset = filp->f_pos & (bufsize - 1);
block = isofs_bmap(inode, filp->f_pos >> bufbits);
high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
if (!block)
return 0;
......@@ -129,7 +131,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
printk("inode->i_size = %x\n",inode->i_size);
#endif
de = (struct iso_directory_record *) (bh->b_data + offset);
inode_number = (block << bufbits) + (offset & (bufsize - 1));
if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
de_len = *(unsigned char *) de;
#ifdef DEBUG
......@@ -177,6 +179,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
break;
}
if(de->flags[-high_sierra] & 0x80) {
first_de = 0;
filp->f_pos += de_len;
continue;
}
first_de = 1;
/* Handle the case of the '.' directory */
if (de->name_len[0] == 1 && de->name[0] == 0) {
if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
......@@ -200,7 +209,6 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
is no Rock Ridge NM field. */
if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
/* Do not report hidden or associated files */
high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
if (de->flags[-high_sierra] & 5) {
filp->f_pos += de_len;
continue;
......
......@@ -5,7 +5,8 @@
* 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 filesystem.
* 1994 Eberhard Moenkeberg - multi session handling.
* 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
*
* 1997 Gordon Chaffee - Joliet CDs
* 1998 Eric Lammerts - ISO9660 Level 3
*/
#include <linux/config.h>
......@@ -655,17 +656,24 @@ int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
int isofs_bmap(struct inode * inode,int block)
{
off_t b_off, offset, size;
struct inode *ino;
unsigned int firstext;
unsigned long nextino;
int i;
if (block<0) {
printk("_isofs_bmap: block<0");
return 0;
}
b_off = block << ISOFS_BUFFER_BITS(inode);
/*
* If we are beyond the end of this file, don't give out any
* blocks.
*/
if( (block << ISOFS_BUFFER_BITS(inode)) >= inode->i_size )
if( b_off > inode->i_size )
{
off_t max_legal_read_offset;
......@@ -679,7 +687,7 @@ int isofs_bmap(struct inode * inode,int block)
*/
max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
& ~(PAGE_SIZE - 1);
if( (block << ISOFS_BUFFER_BITS(inode)) >= max_legal_read_offset )
if( b_off >= max_legal_read_offset )
{
printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block,
......@@ -688,7 +696,42 @@ int isofs_bmap(struct inode * inode,int block)
return 0;
}
return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
offset = 0;
firstext = inode->u.isofs_i.i_first_extent;
size = inode->u.isofs_i.i_section_size;
nextino = inode->u.isofs_i.i_next_section_ino;
#ifdef DEBUG
printk("first inode: inode=%lu nextino=%lu firstext=%u size=%lu\n",
inode->i_ino, nextino, firstext, size);
#endif
i = 0;
while(b_off >= offset + size) {
offset += size;
if(nextino == 0) return 0;
ino = iget(inode->i_sb, nextino);
if(!ino) return 0;
firstext = ino->u.isofs_i.i_first_extent;
size = ino->u.isofs_i.i_section_size;
#ifdef DEBUG
printk("read inode: inode=%lu ino=%lu nextino=%lu firstext=%u size=%lu\n",
inode->i_ino, nextino, ino->u.isofs_i.i_next_section_ino, firstext, size);
#endif
nextino = ino->u.isofs_i.i_next_section_ino;
iput(ino);
if(++i > 100) {
printk("isofs_bmap: More than 100 file sections ?!?, aborting...\n");
printk("isofs_bmap: ino=%lu block=%d firstext=%u size=%u nextino=%lu\n",
inode->i_ino, block, firstext, (unsigned)size, nextino);
return 0;
}
}
#ifdef DEBUG
printk("isofs_bmap: mapped inode:block %lu:%d to block %lu\n",
inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode));
#endif
return (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
}
......@@ -702,6 +745,82 @@ static void test_and_set_uid(uid_t *p, uid_t value)
}
}
static int isofs_read_level3_size(struct inode * inode)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
struct buffer_head * bh = NULL;
struct iso_directory_record * raw_inode = NULL; /* quiet gcc */
unsigned char *pnt = NULL;
void *cpnt = NULL;
int block = 0; /* Quiet GCC */
unsigned long ino;
int i;
inode->i_size = 0;
inode->u.isofs_i.i_next_section_ino = 0;
ino = inode->i_ino;
i = 0;
do {
if(i > 100) {
printk("isofs_read_level3_size: More than 100 file sections ?!?, aborting...\n"
"isofs_read_level3_size: inode=%lu ino=%lu\n", inode->i_ino, ino);
return 0;
}
if(bh == NULL || block != ino >> ISOFS_BUFFER_BITS(inode)) {
if(bh) brelse(bh);
block = ino >> ISOFS_BUFFER_BITS(inode);
if (!(bh=bread(inode->i_dev,block, bufsize))) {
printk("unable to read i-node block");
return 1;
}
}
pnt = ((unsigned char *) bh->b_data
+ (ino & (bufsize - 1)));
if ((ino & (bufsize - 1)) + *pnt > bufsize){
int frag1, offset;
offset = (ino & (bufsize - 1));
frag1 = bufsize - offset;
cpnt = kmalloc(*pnt,GFP_KERNEL);
if (cpnt == NULL) {
printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
brelse(bh);
return 1;
}
memcpy(cpnt, bh->b_data + offset, frag1);
brelse(bh);
if (!(bh = bread(inode->i_dev,++block, bufsize))) {
kfree(cpnt);
printk("unable to read i-node block");
return 1;
}
offset += *pnt - bufsize;
memcpy((char *)cpnt+frag1, bh->b_data, offset);
pnt = ((unsigned char *) cpnt);
}
if(*pnt == 0) {
ino = (ino & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE;
continue;
}
raw_inode = ((struct iso_directory_record *) pnt);
inode->i_size += isonum_733 (raw_inode->size);
if(i == 1) inode->u.isofs_i.i_next_section_ino = ino;
ino += *pnt;
if (cpnt) {
kfree (cpnt);
cpnt = NULL;
}
i++;
} while(raw_inode->flags[-inode->i_sb->u.isofs_sb.s_high_sierra] & 0x80);
brelse(bh);
return 0;
}
void isofs_read_inode(struct inode * inode)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
......@@ -744,9 +863,16 @@ void isofs_read_inode(struct inode * inode)
}
inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
inode->i_size = isonum_733 (raw_inode->size);
inode->i_blocks = inode->i_blksize = 0;
inode->u.isofs_i.i_section_size = isonum_733 (raw_inode->size);
if(raw_inode->flags[-high_sierra] & 0x80) {
if(isofs_read_level3_size(inode)) goto fail;
} else {
inode->i_size = isonum_733 (raw_inode->size);
}
/* There are defective discs out there - we do this to protect
ourselves. A cdrom will never contain more than 800Mb */
if((inode->i_size < 0 || inode->i_size > 800000000) &&
......
......@@ -111,6 +111,7 @@
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/file.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
......@@ -289,15 +290,21 @@ asmlinkage int sys_flock(unsigned int fd, unsigned int cmd)
int error;
lock_kernel();
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
error = -EBADF;
else if (!flock_make_lock(filp, &file_lock, cmd))
error = -EINVAL;
else if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3))
error = -EBADF;
else
error = flock_lock_file(filp, &file_lock,
(cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
error = -EBADF;
filp = fget(fd);
if (!filp)
goto out;
error = -EINVAL;
if (!flock_make_lock(filp, &file_lock, cmd))
goto out_putf;
error = -EBADF;
if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3))
goto out_putf;
error = flock_lock_file(filp, &file_lock,
(cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
out_putf:
fput(filp);
out:
unlock_kernel();
return (error);
}
......@@ -307,36 +314,34 @@ asmlinkage int sys_flock(unsigned int fd, unsigned int cmd)
*/
int fcntl_getlk(unsigned int fd, struct flock *l)
{
struct flock flock;
struct file *filp;
struct dentry *dentry;
struct inode *inode;
struct file_lock *fl,file_lock;
struct flock flock;
int error;
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
return -EBADF;
error = -EFAULT;
if (copy_from_user(&flock, l, sizeof(flock)))
return -EFAULT;
goto out;
error = -EINVAL;
if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
return -EINVAL;
goto out;
dentry = filp->f_dentry;
if (!dentry)
return -EINVAL;
error = -EBADF;
filp = fget(fd);
if (!filp)
goto out;
inode = dentry->d_inode;
if (!inode)
return -EINVAL;
error = -EINVAL;
if (!filp->f_dentry || !filp->f_dentry->d_inode)
goto out_putf;
if (!posix_make_lock(filp, &file_lock, &flock))
return -EINVAL;
goto out_putf;
if (filp->f_op->lock) {
error = filp->f_op->lock(filp, F_GETLK, &file_lock);
if (error < 0)
return error;
goto out_putf;
fl = &file_lock;
} else {
fl = posix_test_lock(filp, &file_lock);
......@@ -351,8 +356,14 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
flock.l_whence = 0;
flock.l_type = fl->fl_type;
}
error = -EFAULT;
if (!copy_to_user(l, &flock, sizeof(flock)))
error = 0;
return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0);
out_putf:
fput(filp);
out:
return error;
}
/* Apply the lock described by l to an open file descriptor.
......@@ -367,22 +378,26 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
struct inode *inode;
int error;
/*
* This might block, so we do it before checking the inode.
*/
error = -EFAULT;
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
/* Get arguments and validate them ...
*/
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
return -EBADF;
error = -EBADF;
filp = fget(fd);
if (!filp)
goto out;
error = -EINVAL;
if (!(dentry = filp->f_dentry))
return -EINVAL;
goto out_putf;
if (!(inode = dentry->d_inode))
return -EINVAL;
/*
* This might block, so we do it before checking the inode.
*/
if (copy_from_user(&flock, l, sizeof(flock)))
return (-EFAULT);
goto out_putf;
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
......@@ -391,23 +406,26 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
(inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
inode->i_mmap) {
struct vm_area_struct *vma = inode->i_mmap;
error = -EAGAIN;
do {
if (vma->vm_flags & VM_MAYSHARE)
return (-EAGAIN);
goto out_putf;
} while ((vma = vma->vm_next_share) != NULL);
}
error = -EINVAL;
if (!posix_make_lock(filp, &file_lock, &flock))
return (-EINVAL);
goto out_putf;
error = -EBADF;
switch (flock.l_type) {
case F_RDLCK:
if (!(filp->f_mode & FMODE_READ))
return (-EBADF);
goto out_putf;
break;
case F_WRLCK:
if (!(filp->f_mode & FMODE_WRITE))
return (-EBADF);
goto out_putf;
break;
case F_UNLCK:
break;
......@@ -425,20 +443,25 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
}
}
if (!(filp->f_mode & 3))
return (-EBADF);
goto out_putf;
break;
#endif
default:
return (-EINVAL);
error = -EINVAL;
goto out_putf;
}
if (filp->f_op->lock != NULL) {
error = filp->f_op->lock(filp, cmd, &file_lock);
if (error < 0)
return (error);
goto out_putf;
}
error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW);
return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW));
out_putf:
fput(filp);
out:
return error;
}
/*
......
This diff is collapsed.
......@@ -62,14 +62,18 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
lock_kernel();
retval = -EBADF;
if (fd >= NR_OPEN ||
!(file = current->files->fd[fd]) ||
!(dentry = file->f_dentry) ||
!(inode = dentry->d_inode))
file = fget(fd);
if (!file)
goto bad;
/* N.B. Shouldn't this be ENOENT?? */
if (!(dentry = file->f_dentry) ||
!(inode = dentry->d_inode))
goto out_putf;
retval = -EINVAL;
if (origin <= 2)
retval = llseek(file, offset, origin);
out_putf:
fput(file);
bad:
unlock_kernel();
return retval;
......@@ -88,24 +92,28 @@ asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
lock_kernel();
retval = -EBADF;
if (fd >= NR_OPEN ||
!(file = current->files->fd[fd]) ||
!(dentry = file->f_dentry) ||
!(inode = dentry->d_inode))
file = fget(fd);
if (!file)
goto bad;
/* N.B. Shouldn't this be ENOENT?? */
if (!(dentry = file->f_dentry) ||
!(inode = dentry->d_inode))
goto out_putf;
retval = -EINVAL;
if (origin > 2)
goto bad;
goto out_putf;
offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
origin);
retval = (int)offset & INT_MAX;
if (offset >= 0) {
retval = copy_to_user(result, &offset, sizeof(offset));
if (retval)
retval = -EFAULT;
retval = -EFAULT;
if (!copy_to_user(result, &offset, sizeof(offset)))
retval = 0;
}
out_putf:
fput(file);
bad:
unlock_kernel();
return retval;
......@@ -201,9 +209,10 @@ static ssize_t do_readv_writev(int type, struct file *file,
if (count > UIO_MAXIOV)
goto out_nofree;
if (count > UIO_FASTIOV) {
iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
ret = -ENOMEM;
if (!iov) goto out_nofree;
iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
if (!iov)
goto out_nofree;
}
ret = -EFAULT;
if (copy_from_user(iov, vector, count*sizeof(*vector)))
......@@ -280,11 +289,10 @@ asmlinkage ssize_t sys_readv(unsigned long fd, const struct iovec * vector,
file = fget(fd);
if (!file)
goto bad_file;
if (!(file->f_mode & FMODE_READ))
goto out;
ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
out:
if (file->f_mode & FMODE_READ)
ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
fput(file);
bad_file:
unlock_kernel();
return ret;
......@@ -302,15 +310,13 @@ asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
file = fget(fd);
if (!file)
goto bad_file;
if (!(file->f_mode & FMODE_WRITE))
goto out;
down(&file->f_dentry->d_inode->i_sem);
ret = do_readv_writev(VERIFY_READ, file, vector, count);
up(&file->f_dentry->d_inode->i_sem);
out:
if (file->f_mode & FMODE_WRITE) {
down(&file->f_dentry->d_inode->i_sem);
ret = do_readv_writev(VERIFY_READ, file, vector, count);
up(&file->f_dentry->d_inode->i_sem);
}
fput(file);
bad_file:
unlock_kernel();
return ret;
......
This diff is collapsed.
......@@ -4,13 +4,14 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
......@@ -220,12 +221,14 @@ asmlinkage int sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
int err = -EBADF;
lock_kernel();
if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
f = fget(fd);
if (f) {
struct dentry * dentry = f->f_dentry;
err = do_revalidate(dentry);
if (!err)
err = cp_old_stat(dentry->d_inode, statbuf);
fput(f);
}
unlock_kernel();
return err;
......@@ -239,12 +242,14 @@ asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf)
int err = -EBADF;
lock_kernel();
if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
f = fget(fd);
if (f) {
struct dentry * dentry = f->f_dentry;
err = do_revalidate(dentry);
if (!err)
err = cp_new_stat(dentry->d_inode, statbuf);
fput(f);
}
unlock_kernel();
return err;
......
......@@ -15,6 +15,8 @@
#define EV45_CPU 6 /* EV4.5 (21064/xxx) */
#define EV56_CPU 7 /* EV5.6 (21164) */
#define EV6_CPU 8 /* EV6 (21164) */
#define PCA56_CPU 9 /* PCA56 (21164PC) */
#define PCA57_CPU 10 /* PCA57 (??) */
/*
* DEC system types for Alpha systems. Found in HWRPB.
......@@ -39,8 +41,26 @@
#define ST_DEC_EB64P 20 /* EB64+ systype */
#define ST_DEC_EB66P -19 /* EB66 systype */
#define ST_DEC_EBPC64 -20 /* Cabriolet (AlphaPC64) systype */
#define ST_DEC_BURNS 21 /* Laptop systype */
#define ST_DEC_RAWHIDE 22 /* Rawhide systype */
#define ST_DEC_K2 23 /* K2 systype */
#define ST_DEC_LYNX 24 /* Lynx systype */
#define ST_DEC_XL 25 /* Alpha XL systype */
#define ST_DEC_EB164 26 /* EB164 systype */
#define ST_DEC_NORITAKE 27 /* Noritake systype */
#define ST_DEC_CORTEX 28 /* Cortex systype */
#define ST_DEC_MIATA 30 /* MIATA systype */
#define ST_DEC_XXM 31 /* XXM systype */
#define ST_DEC_TAKARA 32 /* Takara systype */
#define ST_DEC_YUKON 33 /* Yukon systype */
#define ST_DEC_TSUNAMI 34 /* Tsunami systype */
#define ST_DEC_WILDFIRE 35 /* Wildfire systype */
#define ST_DEC_CUSCO 36 /* CUSCO systype */
/* UNOFFICIAL!!! */
#define ST_UNOFFICIAL_BIAS 100
#define ST_DTI_RUFFIAN 101 /* RUFFIAN systype */
struct pcb_struct {
unsigned long ksp;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -47,4 +47,12 @@ extern inline void put_filp(struct file *file)
}
}
/*
* Install a file pointer in the files structure.
*/
extern inline void fd_install(unsigned long fd, struct file *file)
{
current->files->fd[fd] = file;
}
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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