Commit d641d85b authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.32

parent 9c436be7
......@@ -632,6 +632,13 @@ S: Panoramastrasse 18
S: D-69126 Heidelberg
S: Germany
N: Christopher Horn
E: chorn@warwick.net
D: Miscellaneous sysctl hacks
S: 36 Mudtown Road
S: Wantage, NJ 07461
S: USA
N: Miguel de Icaza Amozurrutia
E: miguel@nuclecu.unam.mx
D: Linux/SPARC team, Midnight Commander maintainer
......
......@@ -47,6 +47,7 @@ encountered a bug!
- Kbd 0.91
- Loadlin 1.6a
- Sh-utils 1.16
- Ncpfs 2.1.1
Upgrade notes
*************
......
......@@ -703,6 +703,18 @@ CONFIG_SYSVIPC
or with the program info ("man info"). Saying Y here enlarges
your kernel by about 7kB. Just say Y.
Sysctl support
CONFIG_SYSCTL
The sysctl interface provides a means of dynamically changing certain
kernel parameters and variables on the fly without requiring a
recompile of the kernel or reboot of the system. The primary interface
consists of a system call, but if the /proc filesystem is enabled, a
tree of modifiable sysctl entries will be generated beneath the
/proc/sys directory. Note that enabling this option will enlarge the
kernel by at least 8kB. As it is generally a good thing, you probably
want to say Y here unless building a kernel for install/rescue disks
or your system is very limited in memory.
Kernel support for ELF binaries
CONFIG_BINFMT_ELF
ELF (Executable and Linkable Format) is a format for libraries and
......
Ioctl Numbers
16 Dec 1996
12 Feb 1997
Michael Chastain
<mec@shout.net>
......@@ -108,3 +108,5 @@ Code Seq# Include File Comments
0x90 00 linux/sbpcd.h
0x99 00-0F 537-Addinboard driver in development, e-mail contact:
b.kohl@ipn-b.comlink.apc.org
0xA0 all Small Device Project in development, e-mail contact:
khollis@northwest.com
......@@ -249,7 +249,7 @@ S: Maintained
NCP FILESYSTEM:
P: Volker Lendecke
M: lendecke@namu01.Num.Math.Uni-Goettingen.de
M: lendecke@Math.Uni-Goettingen.de
L: linware@sh.cvut.cz
S: Maintained
......@@ -301,9 +301,9 @@ S: Supported
SMB FILESYSTEM:
P: Volker Lendecke
M: lendecke@namu01.Num.Math.Uni-Goettingen.de
M: lendecke@Math.Uni-Goettingen.de
L: samba@listproc.anu.edu.au
S: Odd Fixes
S: Maintained
SMP: (except SPARC)
P: Alan Cox
......
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 31
SUBLEVEL = 32
ARCH = i386
......@@ -114,8 +114,9 @@ endif
# Include the make variables (CC, etc...)
#
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o net/network.a
CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
FILESYSTEMS =fs/filesystems.a
NETWORKS =net/network.a
DRIVERS =drivers/block/block.a \
drivers/char/char.a
LIBS =$(TOPDIR)/lib/lib.a
......@@ -173,8 +174,9 @@ boot: vmlinux
vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
$(ARCHIVES) \
$(CORE_FILES) \
$(FILESYSTEMS) \
$(NETWORKS) \
$(DRIVERS) \
$(LIBS) \
-o vmlinux
......
......@@ -30,7 +30,7 @@ HEAD := arch/alpha/kernel/head.o
SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/mm arch/alpha/lib \
arch/alpha/math-emu
ARCHIVES := arch/alpha/kernel/kernel.o arch/alpha/mm/mm.o $(ARCHIVES)
CORE_FILES := arch/alpha/kernel/kernel.o arch/alpha/mm/mm.o $(CORE_FILES)
LIBS := $(TOPDIR)/arch/alpha/math-emu/math-emu.a \
$(TOPDIR)/arch/alpha/lib/lib.a $(LIBS) $(TOPDIR)/arch/alpha/lib/lib.a
......
......@@ -91,8 +91,10 @@ if [ "$CONFIG_PCI" = "y" ]; then
fi
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
endmenu
source drivers/block/Config.in
......
......@@ -39,6 +39,7 @@ CONFIG_ALPHA_SRM=y
CONFIG_TGA_CONSOLE=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
......
......@@ -22,7 +22,7 @@
/*
* stack offsets
*/
#define SP_OFF 160
#define SP_OFF 184
#define SWITCH_STACK_SIZE 320
......@@ -47,9 +47,11 @@
* regs 9-15 preserved by C code
* regs 16-18 saved by PAL-code
* regs 29-30 saved and set up by PAL-code
* JRP - Save regs 16-18 in a special area of the stack, so that
* the palcode-provided values are available to the signal handler.
*/
#define SAVE_ALL \
subq $30,160,$30; \
subq $30,184,$30; \
stq $0,0($30); \
stq $1,8($30); \
stq $2,16($30); \
......@@ -71,7 +73,10 @@
stq $26,128($30); \
stq $27,136($30); \
stq $28,144($30); \
stq $2,152($30)
stq $2,152($30); \
stq $16,160($30); \
stq $17,168($30); \
stq $18,176($30)
#define RESTORE_ALL \
lda $19,hae; \
......@@ -108,7 +113,7 @@
ldq $26,128($30); \
ldq $27,136($30); \
ldq $28,144($30); \
addq $30,160,$30
addq $30,184,$30
.text
.set noat
......
......@@ -218,6 +218,9 @@ static void setup_frame(struct sigaction * sa,
put_user(regs->gp , sc->sc_regs+29);
for (i = 0; i < 31; i++)
put_user(sw->fp[i], sc->sc_fpregs+i);
put_user(regs->trap_a0, &sc->sc_traparg_a0);
put_user(regs->trap_a1, &sc->sc_traparg_a1);
put_user(regs->trap_a2, &sc->sc_traparg_a2);
/*
* The following is:
......
......@@ -70,7 +70,7 @@ endif
HEAD := arch/i386/kernel/head.o
SUBDIRS := $(SUBDIRS) arch/i386/kernel arch/i386/mm arch/i386/lib
ARCHIVES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(ARCHIVES)
CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
ifdef CONFIG_MATH_EMULATION
......
......@@ -31,6 +31,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
fi
bool 'MCA support' CONFIG_MCA
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......
......@@ -22,6 +22,7 @@ CONFIG_NET=y
CONFIG_PCI=y
# CONFIG_MCA is not set
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
# CONFIG_M386 is not set
......@@ -191,6 +192,8 @@ CONFIG_VFAT_FS=y
# CONFIG_UMSDOS_FS is not set
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_ROOT_NFS is not set
# CONFIG_SMB_FS is not set
CONFIG_ISO9660_FS=y
......
......@@ -40,6 +40,8 @@
static unsigned char cache_21 = 0xff;
static unsigned char cache_A1 = 0xff;
unsigned int local_irq_count[NR_CPUS];
#ifdef __SMP_PROF__
static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
#endif
......@@ -329,7 +331,6 @@ int get_smp_prof_list(char *buf) {
unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile int global_irq_lock;
unsigned volatile int global_irq_count;
unsigned int local_irq_count[NR_CPUS];
#define irq_active(cpu) \
(global_irq_count != local_irq_count[cpu])
......@@ -353,11 +354,11 @@ static inline void check_smp_invalidate(int cpu)
static unsigned long previous_irqholder;
#undef INIT_STUCK
#define INIT_STUCK 10000000
#define INIT_STUCK 100000000
#undef STUCK
#define STUCK \
if (!--stuck) {printk("wait_on_irq stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", where, previous_irqholder, local_count, global_irq_count); stuck = INIT_STUCK;}
if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, global_irq_count); stuck = INIT_STUCK; }
static inline void wait_on_irq(int cpu, unsigned long where)
{
......@@ -393,6 +394,28 @@ static inline void wait_on_irq(int cpu, unsigned long where)
}
}
/*
* This is called when we want to synchronize with
* interrupts. We may for example tell a device to
* stop sending interrupts: but to make sure there
* are no interrupts that are executing on another
* CPU we need to call this function.
*
* On UP this is a no-op.
*/
void synchronize_irq(void)
{
int cpu = smp_processor_id();
int local_count = local_irq_count[cpu];
/* Do we need to wait? */
if (local_count != global_irq_count) {
/* The stupid way to do this */
cli();
sti();
}
}
#undef INIT_STUCK
#define INIT_STUCK 10000000
......@@ -436,7 +459,7 @@ void __global_cli(void)
int cpu = smp_processor_id();
unsigned long where;
__asm__("movl 12(%%esp),%0":"=r" (where));
__asm__("movl 16(%%esp),%0":"=r" (where));
__cli();
get_irqlock(cpu, where);
}
......
......@@ -1232,8 +1232,10 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
void smp_flush_tlb(void)
{
unsigned long flags;
if(smp_activated && smp_processor_id()!=active_kernel_processor)
panic("CPU #%d:Attempted flush tlb IPI when not AKP(=%d)\n",smp_processor_id(),active_kernel_processor);
if(smp_activated && smp_processor_id()!=active_kernel_processor) {
printk("CPU #%d:Attempted flush tlb IPI when not AKP(=%d)\n",smp_processor_id(),active_kernel_processor);
*(char *)0=0;
}
/* printk("SMI-");*/
/*
......
......@@ -454,7 +454,8 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
)*60 + sec; /* finally seconds */
}
static unsigned long get_cmos_time(void)
/* not static: needed by APM */
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
int i;
......
......@@ -114,7 +114,7 @@ int kstack_depth_to_print = 24;
#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)
/*static*/ void die_if_kernel(const char * str, struct pt_regs * regs, long err)
static void show_regs(struct pt_regs *regs)
{
int i;
unsigned long esp;
......@@ -130,8 +130,6 @@ int kstack_depth_to_print = 24;
esp = regs->esp;
ss = regs->xss & 0xffff;
}
console_verbose();
printk("%s: %04lx\n", str, err & 0xffff);
printk("CPU: %d\n", smp_processor_id());
printk("EIP: %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->xcs,regs->eip,regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
......@@ -182,6 +180,13 @@ int kstack_depth_to_print = 24;
for(i=0;i<20;i++)
printk("%02x ",0xff & get_seg_byte(regs->xcs & 0xffff,(i+(char *)regs->eip)));
printk("\n");
}
/*static*/ void die_if_kernel(const char * str, struct pt_regs * regs, long err)
{
console_verbose();
printk("%s: %04lx\n", str, err & 0xffff);
show_regs(regs);
do_exit(SIGSEGV);
}
......@@ -231,6 +236,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
{
printk("NMI\n"); show_regs(regs);
#ifdef CONFIG_SMP_NMI_INVAL
smp_flush_tlb_rcv();
#else
......
......@@ -49,6 +49,7 @@ comment 'General setup'
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_AMIGA" = "y" ]; then
......
......@@ -38,6 +38,7 @@ CONFIG_M68040=y
#
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_ZORRO=y
......
......@@ -50,6 +50,7 @@ bool 'Networking support' CONFIG_NET
# fi
#fi
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
endmenu
mainmenu_option next_comment
......
......@@ -26,6 +26,7 @@ CONFIG_BINFMT_AOUT=y
CONFIG_CPU_LITTLE_ENDIAN=y
# CONFIG_NET is not set
# CONFIG_SYSVIPC is not set
CONFIG_SYSCTL=y
#
# Loadable module support
......
......@@ -30,6 +30,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
fi
fi
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
......
......@@ -26,14 +26,14 @@ HEAD := arch/sparc/kernel/head.o
SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib arch/sparc/mm \
arch/sparc/prom
ARCHIVES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(ARCHIVES)
CORE_FILES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(CORE_FILES)
LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \
$(TOPDIR)/arch/sparc/lib/lib.a
ifdef CONFIG_AP1000
SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp
ARCHIVES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o $(TOPDIR)/mpp/mpplib.o $(ARCHIVES)
CORE_FILES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o $(TOPDIR)/mpp/mpplib.o $(CORE_FILES)
DRIVERS := $(DRIVERS) drivers/ap1000/ap1000.a
CFLAGS := $(CFLAGS) -D__MPP__=1
endif
......
......@@ -50,6 +50,7 @@ fi
tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......
......@@ -59,6 +59,7 @@ CONFIG_SUN_MOSTEK_RTC=y
CONFIG_SUN_OPENPROMFS=m
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_JAVA=m
......
......@@ -32,7 +32,7 @@ HEAD := arch/sparc64/kernel/head.o
SUBDIRS := $(SUBDIRS) arch/sparc64/kernel arch/sparc64/lib arch/sparc64/mm \
arch/sparc64/prom
ARCHIVES := arch/sparc64/kernel/kernel.o arch/sparc64/mm/mm.o $(ARCHIVES)
CORE_FILES := arch/sparc64/kernel/kernel.o arch/sparc64/mm/mm.o $(CORE_FILES)
LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc64/prom/promlib.a \
$(TOPDIR)/arch/sparc64/lib/lib.a
......
......@@ -49,6 +49,7 @@ fi
tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......
......@@ -59,6 +59,7 @@ CONFIG_SUN_MOSTEK_RTC=y
CONFIG_SUN_OPENPROMFS=m
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_JAVA=m
......
......@@ -24,9 +24,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/string.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
#include <asm/system.h>
......@@ -109,6 +107,52 @@ static inline int is_extended_partition(struct partition *p)
SYS_IND(p) == LINUX_EXTENDED_PARTITION);
}
static unsigned int get_ptable_blocksize(kdev_t dev)
{
int ret = 1024;
/*
* See whether the low-level driver has given us a minumum blocksize.
* If so, check to see whether it is larger than the default of 1024.
*/
if (!blksize_size[MAJOR(dev)])
{
return ret;
}
/*
* Check for certain special power of two sizes that we allow.
* With anything larger than 1024, we must force the blocksize up to
* the natural blocksize for the device so that we don't have to try
* and read partial sectors. Anything smaller should be just fine.
*/
switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
{
case 2048:
ret = 2048;
break;
case 4096:
ret = 4096;
break;
case 8192:
ret = 8192;
break;
case 1024:
case 512:
case 256:
case 0:
/*
* These are all OK.
*/
break;
default:
panic("Strange blocksize for partition table\n");
}
return ret;
}
#ifdef CONFIG_MSDOS_PARTITION
/*
* Create devices for each logical partition in an extended partition.
......@@ -138,7 +182,7 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
while (1) {
if ((current_minor & mask) == 0)
return;
if (!(bh = bread(dev,0,1024)))
if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
return;
/*
* This block is from a device that we're about to stomp on.
......@@ -222,7 +266,7 @@ static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
struct bsd_partition *p;
int mask = (1 << hd->minor_shift) - 1;
if (!(bh = bread(dev,0,1024)))
if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
return;
bh->b_state = 0;
l = (struct bsd_disklabel *) (bh->b_data+512);
......@@ -259,7 +303,7 @@ static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s
read_mbr:
#endif
if (!(bh = bread(dev,0,1024))) {
if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
printk(" unable to read partition table\n");
return -1;
}
......@@ -438,7 +482,7 @@ static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long fir
struct d_partition * partition;
#define DISKLABELMAGIC (0x82564557UL)
if (!(bh = bread(dev,0,1024))) {
if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
printk("unable to read partition table\n");
return -1;
}
......@@ -501,7 +545,7 @@ static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sec
unsigned long spc;
#define SUN_LABEL_MAGIC 0xDABE
if(!(bh = bread(dev, 0, 1024))) {
if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
printk("Dev %s: unable to read partition table\n",
kdevname(dev));
return -1;
......
......@@ -15,15 +15,6 @@
#endif
/* Turn this on to have the driver print out the meanings of the
ATAPI error codes. This will use up additional kernel-space
memory, though. */
#ifndef VERBOSE_IDE_CD_ERRORS
#define VERBOSE_IDE_CD_ERRORS 0
#endif
/* Turning this on will remove code to work around various nonstandard
ATAPI implementations. If you know your drive follows the standard,
this will give you a slightly smaller kernel. */
......
......@@ -117,6 +117,8 @@ static inline int lp_char_interrupt(char lpchar, int minor)
struct lp_stats *stats;
do {
if(need_resched)
schedule();
if ((status = LP_S(minor)) & LP_PBUSY) {
if (!LP_CAREFUL_READY(minor, status))
return 0;
......
......@@ -115,14 +115,10 @@ set_palette (void)
void
__set_origin(unsigned short offset)
{
unsigned long flags;
clear_selection();
save_flags(flags); cli();
__origin = offset;
write_vga(12, offset);
restore_flags(flags);
}
/*
......@@ -140,18 +136,14 @@ hide_cursor(void)
void
set_cursor(int currcons)
{
unsigned long flags;
if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
return;
if (__real_origin != __origin)
__set_origin(__real_origin);
save_flags(flags); cli();
if (deccm) {
write_vga(14, (pos - video_mem_base)>>1);
} else
hide_cursor();
restore_flags(flags);
}
unsigned long
......
......@@ -758,7 +758,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
short ioaddr = dev->base_addr;
unsigned long flags;
if (net_debug > 3)printk("%s: sent %ld byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
if (net_debug > 3)printk("%s: sent %d byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
/* keep the upload from being interrupted, since we
ask the chip to start transmitting before the
......
......@@ -1359,8 +1359,9 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (dev->interrupt)
printk("%s: Re-entering the interrupt handler.\n", dev->name);
DISABLE_IRQs; /* Ensure non re-entrancy */
synchronize_irq();
dev->interrupt = MASK_INTERRUPTS;
for (limit=0; limit<8; limit++) {
......@@ -1389,13 +1390,11 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev->name, sts);
return;
}
if (sts & (STS_AIS | STS_UNF | STS_SE | STS_LNF | STS_RWT | STS_RU | STS_TJT))
printk("STS=%08x\n",sts);
}
/* Load the TX ring with any locally stored packets */
if (!set_bit(0, (void *)&lp->cache.lock)) {
while (lp->cache.skb && !dev->tbusy && lp->tx_enable) {
if (lp->cache.skb && !dev->tbusy && lp->tx_enable) {
de4x5_queue_pkt(de4x5_get_cache(dev), dev);
}
lp->cache.lock = 0;
......
......@@ -614,7 +614,7 @@ int init_module(void)
if(err<0)
return err;
printk(SHAPER_BANNER);
if (register_netdev(dev) != 0)
if (register_netdev(&dev_shape) != 0)
return -EIO;
printk("Traffic shaper initialised.\n");
return 0;
......
This diff is collapsed.
This diff is collapsed.
#define MAX_SCSI_DEVICE_CODE 10
const char *const pio_scsi_dev_types[MAX_SCSI_DEVICE_CODE] =
{
"Direct-Access ",
"Sequential-Access",
"Printer ",
"Processor ",
"WORM ",
"CD-ROM ",
"Scanner ",
"Optical Device ",
"Medium Changer ",
"Communications "
};
/*
* eata_set_info
* buffer : pointer to the data that has been written to the hostfile
......@@ -147,4 +131,3 @@ int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length,
* tab-width: 8
* End:
*/
......@@ -331,6 +331,10 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
int blocks = len / 128;
int start = 0;
int bl;
#ifdef CONFIG_SCSI_G_NCR5380_PORT
int i;
#endif
NCR5380_local_declare();
NCR5380_setup(instance);
......@@ -605,21 +609,6 @@ static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
return len-start;
}
const char *const private_scsi_device_types[] =
{
"Direct-Access ",
"Sequential-Access",
"Printer ",
"Processor ",
"WORM ",
"CD-ROM ",
"Scanner ",
"Optical Device ",
"Medium Changer ",
"Communications "
};
#define MAX_SCSI_DEVICE_CODE sizeof(private_scsi_device_types)/sizeof(char*)
int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
{
int len = 0;
......@@ -630,7 +619,8 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
Scsi_Device *dev;
Scsi_Cmnd *ptr;
struct NCR5380_hostdata *hostdata;
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
cli();
for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
......@@ -673,7 +663,7 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
long tr = hostdata->time_read[dev->id] / HZ;
long tw = hostdata->time_write[dev->id] / HZ;
PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? private_scsi_device_types[(int)dev->type] : "Unknown");
PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int)dev->type] : "Unknown");
for (i=0; i<8; i++)
if (dev->vendor[i] >= 0x20)
*(buffer+(len++)) = dev->vendor[i];
......
......@@ -110,7 +110,6 @@ static volatile struct Scsi_Host * host_active = NULL;
#define SCSI_BLOCK(HOST) ((HOST->block && host_active && HOST != host_active) \
|| (HOST->can_queue && HOST->host_busy >= HOST->can_queue))
#define MAX_SCSI_DEVICE_CODE 10
const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
{
"Direct-Access ",
......
......@@ -34,6 +34,7 @@
# define FALSE 0
#endif
#define MAX_SCSI_DEVICE_CODE 10
extern void scsi_make_blocked_list(void);
extern volatile int in_scan_scsis;
......
......@@ -239,25 +239,12 @@ int parseOpt(parseHandle *handle, char **param)
return(cmdIndex);
}
#define MAX_SCSI_DEVICE_CODE 10
const char *const scsi_dev_types[MAX_SCSI_DEVICE_CODE] =
{
"Direct-Access ",
"Sequential-Access",
"Printer ",
"Processor ",
"WORM ",
"CD-ROM ",
"Scanner ",
"Optical Device ",
"Medium Changer ",
"Communications "
};
void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len)
{
int x, y = *size;
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
y = sprintf(buffer + len,
"Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
scd->host->host_no, scd->channel, scd->id, scd->lun);
......@@ -285,7 +272,7 @@ void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len)
y += sprintf(buffer + len + y, " Type: %s ",
scd->type < MAX_SCSI_DEVICE_CODE ?
scsi_dev_types[(int)scd->type] : "Unknown " );
scsi_device_types[(int)scd->type] : "Unknown " );
y += sprintf(buffer + len + y, " ANSI"
" SCSI revision: %02x", (scd->scsi_level < 3)?1:2);
if (scd->scsi_level == 2)
......@@ -315,3 +302,4 @@ void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len)
* tab-width: 8
* End:
*/
......@@ -60,7 +60,7 @@
*/
#define SD_TIMEOUT (15 * HZ)
#define SD_MOD_TIMEOUT (15 * HZ)
#define SD_MOD_TIMEOUT (75 * HZ)
#define CLUSTERABLE_DEVICE(SC) (SC->host->use_clustering && \
SC->device->type != TYPE_MOD)
......@@ -254,6 +254,11 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
error_sector <<= 1;
if (block_sectors < 2) block_sectors = 2;
}
else if (sector_size == 2048)
{
error_sector <<= 2;
if (block_sectors < 4) block_sectors = 4;
}
else if (sector_size == 256)
error_sector >>= 1;
error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
......@@ -634,6 +639,13 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
goto repeat;
}
if (rscsi_disks[dev].sector_size == 2048)
if((block & 3) || (SCpnt->request.nr_sectors & 3)) {
printk("sd.c:Bad block number requested");
SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
goto repeat;
}
switch (SCpnt->request.cmd)
{
case WRITE :
......@@ -900,6 +912,13 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
cmd[1] = (SCpnt->lun << 5) & 0xe0;
if (rscsi_disks[dev].sector_size == 2048){
if(block & 3) panic("sd.c:Bad block number requested");
if(this_count & 3) panic("sd.c:Bad block number requested");
block = block >> 2;
this_count = this_count >> 2;
}
if (rscsi_disks[dev].sector_size == 1024){
if(block & 1) panic("sd.c:Bad block number requested");
if(this_count & 1) panic("sd.c:Bad block number requested");
......@@ -1201,6 +1220,7 @@ static int sd_init_onedisk(int i)
if (rscsi_disks[i].sector_size != 512 &&
rscsi_disks[i].sector_size != 1024 &&
rscsi_disks[i].sector_size != 2048 &&
rscsi_disks[i].sector_size != 256)
{
printk ("sd%c : unsupported sector size %d.\n",
......@@ -1215,6 +1235,22 @@ static int sd_init_onedisk(int i)
return i;
}
}
if( rscsi_disks[i].sector_size == 2048 )
{
int m;
/*
* We must fix the sd_blocksizes and sd_hardsizes
* to allow us to read the partition tables.
* The disk reading code does not allow for reading
* of partial sectors.
*/
for (m=i<<4; m<((i+1)<<4); m++)
{
sd_blocksizes[m] = 2048;
}
}
{
/*
* The msdos fs needs to know the hardware sector size
......@@ -1238,6 +1274,8 @@ static int sd_init_onedisk(int i)
i+'a', hard_sector, rscsi_disks[i].capacity,
mb, sz_quot, sz_rem);
}
if(rscsi_disks[i].sector_size == 2048)
rscsi_disks[i].capacity <<= 2; /* Change into 512 byte sectors */
if(rscsi_disks[i].sector_size == 1024)
rscsi_disks[i].capacity <<= 1; /* Change into 512 byte sectors */
if(rscsi_disks[i].sector_size == 256)
......@@ -1341,10 +1379,12 @@ static int sd_init()
sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
sizeof(int), GFP_ATOMIC);
for(i=0;i<(sd_template.dev_max << 4);i++){
sd_blocksizes[i] = 1024;
sd_hardsizes[i] = 512;
}
for(i=0;i<(sd_template.dev_max << 4);i++)
{
sd_blocksizes[i] = 1024;
sd_hardsizes[i] = 512;
}
blksize_size[MAJOR_NR] = sd_blocksizes;
hardsect_size[MAJOR_NR] = sd_hardsizes;
sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
......@@ -1477,9 +1517,15 @@ int revalidate_scsidisk(kdev_t dev, int maxusage){
gdev->part[minor].nr_sects = 0;
/*
* Reset the blocksize for everything so that we can read
* the partition table.
* the partition table. Technically we will determine the
* correct block size when we revalidate, but we do this just
* to make sure that everything remains consistent.
*/
blksize_size[MAJOR_NR][minor] = 1024;
if( rscsi_disks[target].sector_size == 2048 )
blksize_size[MAJOR_NR][minor] = 2048;
else
blksize_size[MAJOR_NR][minor] = 1024;
}
#ifdef MAYBE_REINIT
......
......@@ -127,6 +127,103 @@ static struct proc_dir_entry proc_scsi_seagate =
broken! */
#endif
/*
Thanks to Brian Antoine for the example code in his Messy-Loss ST-01
driver, and Mitsugu Suzuki for information on the ST-01
SCSI host.
*/
/*
CONTROL defines
*/
#define CMD_RST 0x01
#define CMD_SEL 0x02
#define CMD_BSY 0x04
#define CMD_ATTN 0x08
#define CMD_START_ARB 0x10
#define CMD_EN_PARITY 0x20
#define CMD_INTR 0x40
#define CMD_DRVR_ENABLE 0x80
/*
STATUS
*/
#ifdef SWAPSTAT
#define STAT_MSG 0x08
#define STAT_CD 0x02
#else
#define STAT_MSG 0x02
#define STAT_CD 0x08
#endif
#define STAT_BSY 0x01
#define STAT_IO 0x04
#define STAT_REQ 0x10
#define STAT_SEL 0x20
#define STAT_PARITY 0x40
#define STAT_ARB_CMPL 0x80
/*
REQUESTS
*/
#define REQ_MASK (STAT_CD | STAT_IO | STAT_MSG)
#define REQ_DATAOUT 0
#define REQ_DATAIN STAT_IO
#define REQ_CMDOUT STAT_CD
#define REQ_STATIN (STAT_CD | STAT_IO)
#define REQ_MSGOUT (STAT_MSG | STAT_CD)
#define REQ_MSGIN (STAT_MSG | STAT_CD | STAT_IO)
extern volatile int seagate_st0x_timeout;
#ifdef PARITY
#define BASE_CMD CMD_EN_PARITY
#else
#define BASE_CMD 0
#endif
/*
Debugging code
*/
#define PHASE_BUS_FREE 1
#define PHASE_ARBITRATION 2
#define PHASE_SELECTION 4
#define PHASE_DATAIN 8
#define PHASE_DATAOUT 0x10
#define PHASE_CMDOUT 0x20
#define PHASE_MSGIN 0x40
#define PHASE_MSGOUT 0x80
#define PHASE_STATUSIN 0x100
#define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN)
#define PRINT_COMMAND 0x200
#define PHASE_EXIT 0x400
#define PHASE_RESELECT 0x800
#define DEBUG_FAST 0x1000
#define DEBUG_SG 0x2000
#define DEBUG_LINKED 0x4000
#define DEBUG_BORKEN 0x8000
/*
* Control options - these are timeouts specified in .01 seconds.
*/
/* 30, 20 work */
#define ST0X_BUS_FREE_DELAY 25
#define ST0X_SELECTION_DELAY 25
#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::)
#define SEAGATE 1 /* these determine the type of the controller */
#define FD 2
#define ST0X_ID_STR "Seagate ST-01/ST-02"
#define FD_ID_STR "TMC-8XX/TMC-950"
static int internal_command (unsigned char target, unsigned char lun,
const void *cmnd,
void *buff, int bufflen, int reselect);
......
......@@ -35,102 +35,6 @@ int seagate_st0x_biosparam(Disk *, kdev_t, int*);
seagate_st0x_queue_command, seagate_st0x_abort, \
seagate_st0x_reset, NULL, seagate_st0x_biosparam, \
1, 7, SG_ALL, 1, 0, 0, DISABLE_CLUSTERING}
#endif
/*
Thanks to Brian Antoine for the example code in his Messy-Loss ST-01
driver, and Mitsugu Suzuki for information on the ST-01
SCSI host.
*/
/*
CONTROL defines
*/
#define CMD_RST 0x01
#define CMD_SEL 0x02
#define CMD_BSY 0x04
#define CMD_ATTN 0x08
#define CMD_START_ARB 0x10
#define CMD_EN_PARITY 0x20
#define CMD_INTR 0x40
#define CMD_DRVR_ENABLE 0x80
/*
STATUS
*/
#ifdef SWAPSTAT
#define STAT_MSG 0x08
#define STAT_CD 0x02
#else
#define STAT_MSG 0x02
#define STAT_CD 0x08
#endif
#define STAT_BSY 0x01
#define STAT_IO 0x04
#define STAT_REQ 0x10
#define STAT_SEL 0x20
#define STAT_PARITY 0x40
#define STAT_ARB_CMPL 0x80
/*
REQUESTS
*/
#define REQ_MASK (STAT_CD | STAT_IO | STAT_MSG)
#define REQ_DATAOUT 0
#define REQ_DATAIN STAT_IO
#define REQ_CMDOUT STAT_CD
#define REQ_STATIN (STAT_CD | STAT_IO)
#define REQ_MSGOUT (STAT_MSG | STAT_CD)
#define REQ_MSGIN (STAT_MSG | STAT_CD | STAT_IO)
extern volatile int seagate_st0x_timeout;
#ifdef PARITY
#define BASE_CMD CMD_EN_PARITY
#else
#define BASE_CMD 0
#endif
/*
Debugging code
*/
#define PHASE_BUS_FREE 1
#define PHASE_ARBITRATION 2
#define PHASE_SELECTION 4
#define PHASE_DATAIN 8
#define PHASE_DATAOUT 0x10
#define PHASE_CMDOUT 0x20
#define PHASE_MSGIN 0x40
#define PHASE_MSGOUT 0x80
#define PHASE_STATUSIN 0x100
#define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN)
#define PRINT_COMMAND 0x200
#define PHASE_EXIT 0x400
#define PHASE_RESELECT 0x800
#define DEBUG_FAST 0x1000
#define DEBUG_SG 0x2000
#define DEBUG_LINKED 0x4000
#define DEBUG_BORKEN 0x8000
/*
* Control options - these are timeouts specified in .01 seconds.
*/
/* 30, 20 work */
#define ST0X_BUS_FREE_DELAY 25
#define ST0X_SELECTION_DELAY 25
#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::)
#define SEAGATE 1 /* these determine the type of the controller */
#define FD 2
#define ST0X_ID_STR "Seagate ST-01/ST-02"
#define FD_ID_STR "TMC-8XX/TMC-950"
#endif
#endif /* ASM */
#endif /* _SEAGATE_H */
......@@ -60,9 +60,10 @@ struct Scsi_Device_Template sr_template = {NULL, "cdrom", "sr", NULL, TYPE_ROM,
sr_finish, sr_attach, sr_detach};
Scsi_CD * scsi_CDs = NULL;
static int * sr_sizes;
static int * sr_sizes = NULL;
static int * sr_blocksizes;
static int * sr_blocksizes = NULL;
static int * sr_hardsizes = NULL; /* Hardware sector size */
static int sr_open(struct cdrom_device_info*, int);
void get_sectorsize(int);
......@@ -121,7 +122,8 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot){
retval = scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
SCSI_IOCTL_TEST_UNIT_READY, 0);
if(retval){
if(retval)
{
/* Unable to test, unit probably not ready. This usually
* means there is no disc in the drive. Mark as changed,
* and we will figure it out later once the drive is
......@@ -140,7 +142,18 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot){
#ifdef CONFIG_BLK_DEV_SR_VENDOR
sr_cd_check(cdi);
#endif
/*
* If the disk changed, the capacity will now be different,
* so we force a re-read of this information
* Force 2048 for the sector size so that filesystems won't
* be trying to use something that is too small if the disc
* has changed.
*/
scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
scsi_CDs[MINOR(cdi->dev)].sector_size =
sr_hardsizes[MINOR(cdi->dev)] = 2048;
}
return retval;
}
......@@ -894,6 +907,12 @@ void get_sectorsize(int i){
scsi_CDs[i].capacity = 0;
scsi_CDs[i].needs_sector_size = 1;
}
/*
* Add this so that we have the ability to correctly gauge
* what the device is capable of.
*/
sr_hardsizes[i] = scsi_CDs[i].sector_size;
scsi_CDs[i].needs_sector_size = 0;
sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
};
......@@ -928,8 +947,16 @@ static int sr_init()
sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max *
sizeof(int), GFP_ATOMIC);
sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max *
sizeof(int), GFP_ATOMIC);
/*
* These are good guesses for the time being.
*/
for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048;
for(i=0;i<sr_template.dev_max;i++) sr_hardsizes[i] = 2048;
blksize_size[MAJOR_NR] = sr_blocksizes;
hardsect_size[MAJOR_NR] = sr_hardsizes;
return 0;
}
......@@ -1023,7 +1050,13 @@ void cleanup_module( void)
* sizeof(Scsi_CD));
scsi_init_free((char *) sr_sizes, sr_template.dev_max * sizeof(int));
sr_sizes = NULL;
scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int));
sr_blocksizes = NULL;
scsi_init_free((char *) sr_hardsizes, sr_template.dev_max * sizeof(int));
sr_hardsizes = NULL;
}
blksize_size[MAJOR_NR] = NULL;
......
......@@ -18,6 +18,8 @@ bool '/proc filesystem support' CONFIG_PROC_FS
if [ "$CONFIG_INET" = "y" ]; then
tristate 'NFS filesystem support' CONFIG_NFS_FS
if [ "$CONFIG_NFS_FS" = "y" ]; then
define_bool CONFIG_SUNRPC y
define_bool CONFIG_LOCKD y
bool ' Root file system on NFS' CONFIG_ROOT_NFS
if [ "$CONFIG_ROOT_NFS" = "y" ]; then
bool ' BOOTP support' CONFIG_RNFS_BOOTP
......
......@@ -17,7 +17,7 @@ O_OBJS = open.o read_write.o inode.o devices.o file_table.o buffer.o \
MOD_LIST_NAME := FS_MODULES
ALL_SUB_DIRS = minix ext2 fat msdos vfat proc isofs nfs umsdos \
hpfs sysv smbfs ncpfs ufs affs romfs autofs
hpfs sysv smbfs ncpfs ufs affs romfs autofs lockd nfsd
ifeq ($(CONFIG_QUOTA),y)
O_OBJS += dquot.o
......@@ -89,6 +89,23 @@ else
endif
endif
ifeq ($(CONFIG_NFSD),y)
CONFIG_LOCKD := y
SUB_DIRS += nfsd
else
ifeq ($(CONFIG_NFSD),m)
MOD_SUB_DIRS += nfsd
endif
endif
ifeq ($(CONFIG_LOCKD),y)
SUB_DIRS += lockd
else
ifeq ($(CONFIG_LOCKD),m)
MOD_SUB_DIRS := lockd $(MOD_SUB_DIRS)
endif
endif
ifeq ($(CONFIG_UMSDOS_FS),y)
SUB_DIRS += umsdos
else
......@@ -185,6 +202,15 @@ else
endif
endif
ifeq ($(CONFIG_BINFMT_EM86),y)
BINFMTS += binfmt_em86.o
else
ifeq ($(CONFIG_BINFMT_EM86),m)
M_OBJS += binfmt_em86.o
endif
endif
# binfmt_script is always there
BINFMTS += binfmt_script.o
......
......@@ -10,7 +10,6 @@
*
* ------------------------------------------------------------------------- */
#include <linux/modversions.h>
#include <linux/auto_fs.h>
static int autofs_dir_readdir(struct inode *inode, struct file *filp,
......
......@@ -10,7 +10,6 @@
*
* ------------------------------------------------------------------------- */
#include <linux/modversions.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/auto_fs.h>
......
......@@ -10,7 +10,6 @@
*
* ------------------------------------------------------------------------- */
#include <linux/modversions.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/file.h>
......@@ -143,6 +142,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL);
if ( !sbi ) {
s->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
......@@ -208,7 +208,7 @@ static void autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz
struct statfs tmp;
tmp.f_type = AUTOFS_SUPER_MAGIC;
tmp.f_bsize = PAGE_SIZE/sizeof(long);
tmp.f_bsize = 1024;
tmp.f_blocks = 0;
tmp.f_bfree = 0;
tmp.f_bavail = 0;
......
......@@ -10,7 +10,6 @@
*
* ------------------------------------------------------------------------- */
#include <linux/modversions.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/malloc.h>
......
......@@ -10,7 +10,6 @@
*
* ------------------------------------------------------------------------- */
#include <linux/modversions.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/auto_fs.h>
......
......@@ -10,8 +10,9 @@
*
* ------------------------------------------------------------------------- */
#include <linux/modversions.h>
#include <linux/malloc.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/auto_fs.h>
/* We make this a static variable rather than a part of the superblock; it
......@@ -40,6 +41,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
static int autofs_write(struct file *file, const void *addr, int bytes)
{
unsigned short fs;
unsigned long old_signal;
const char *data = (const char *)addr;
int written;
......@@ -49,10 +51,18 @@ static int autofs_write(struct file *file, const void *addr, int bytes)
fs = get_fs();
set_fs(KERNEL_DS);
old_signal = current->signal;
while ( bytes && (written = file->f_op->write(file->f_inode,file,data,bytes)) > 0 ) {
data += written;
bytes -= written;
}
if ( written == -EPIPE && !(old_signal & (1 << (SIGPIPE-1))) ) {
/* Keep the currently executing process from receiving a
SIGPIPE unless it was already supposed to get one */
current->signal &= ~(1 << (SIGPIPE-1));
}
set_fs(fs);
return (bytes > 0);
......
/*
* linux/fs/binfmt_em86.c
*
* Based on linux/fs/binfmt_script.c
* Copyright (C) 1996 Martin von Lwis
* original #!-checking implemented by tytso.
*
* em86 changes Copyright (C) 1997 Jim Paradis
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/malloc.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#define EM86_INTERP "/usr/bin/em86"
#define EM86_I_NAME "em86"
static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *cp, *interp, *i_name, *i_arg;
int retval;
struct elfhdr elf_ex;
/* Make sure this is a Linux/Intel ELF executable... */
elf_ex = *((struct elfhdr *)bprm->buf);
if (elf_ex.e_ident[0] != 0x7f ||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
return -ENOEXEC;
}
/* First of all, some simple consistency checks */
if ((elf_ex.e_type != ET_EXEC &&
elf_ex.e_type != ET_DYN) ||
(!((elf_ex.e_machine == EM_386) || (elf_ex.e_machine == EM_486))) ||
(!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
!bprm->inode->i_op->default_file_ops->mmap)){
return -ENOEXEC;
}
bprm->sh_bang++; /* Well, the bang-shell is implicit... */
iput(bprm->inode);
bprm->dont_iput = 1;
/* Unlike in the script case, we don't have to do any hairy
* parsing to find our interpreter... it's hardcoded!
*/
interp = EM86_INTERP;
i_name = EM86_I_NAME;
i_arg = NULL; /* We reserve the right to add an arg later */
/*
* Splice in (1) the interpreter's name for argv[0]
* (2) (optional) argument to interpreter
* (3) filename of emulated file (replace argv[0])
*
* This is done in reverse order, because of how the
* user environment and arguments are stored.
*/
remove_arg_zero(bprm);
bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2);
bprm->argc++;
if (i_arg) {
bprm->p = copy_strings(1, &i_arg, bprm->page, bprm->p, 2);
bprm->argc++;
}
bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);
bprm->argc++;
if (!bprm->p)
return -E2BIG;
/*
* OK, now restart the process with the interpreter's inode.
* Note that we use open_namei() as the name is now in kernel
* space, and we don't need to copy it.
*/
retval = open_namei(interp, 0, 0, &bprm->inode, NULL);
if (retval)
return retval;
bprm->dont_iput=0;
retval=prepare_binprm(bprm);
if(retval<0)
return retval;
return search_binary_handler(bprm,regs);
}
static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
{
int retval;
MOD_INC_USE_COUNT;
retval = do_load_em86(bprm,regs);
MOD_DEC_USE_COUNT;
return retval;
}
struct linux_binfmt em86_format = {
#ifndef MODULE
NULL, 0, load_em86, NULL, NULL
#else
NULL, &mod_use_count_, load_em86, NULL, NULL
#endif
};
int init_em86_binfmt(void) {
return register_binfmt(&em86_format);
}
#ifdef MODULE
int init_module(void)
{
return init_em86_binfmt();
}
void cleanup_module( void) {
unregister_binfmt(&em86_format);
}
#endif
......@@ -29,6 +29,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <asm/system.h>
#include <asm/uaccess.h>
......@@ -498,6 +499,31 @@ struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
}
}
unsigned int get_hardblocksize(kdev_t dev)
{
int blksize = 0;
/*
* Get the hard sector size for the given device. If we don't know
* what it is, return 0.
*/
if (hardsect_size[MAJOR(dev)] != NULL)
{
blksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
if (blksize != 0)
{
return blksize;
}
}
/*
* We don't know what the hardware sector size for this device is.
* Return 0 indicating that we don't know.
*/
return 0;
}
void set_blocksize(kdev_t dev, int size)
{
extern int *blksize_size[];
......@@ -979,17 +1005,15 @@ static void get_more_buffer_heads(void)
static inline void recover_reusable_buffer_heads(void)
{
if (reuse_list) {
struct buffer_head *bh;
unsigned long flags;
struct buffer_head *head;
head = xchg(&reuse_list, NULL);
save_flags(flags);
do {
cli();
bh = reuse_list;
reuse_list = bh->b_next_free;
restore_flags(flags);
struct buffer_head *bh = head;
head = head->b_next_free;
put_unused_buffer_head(bh);
} while (reuse_list);
} while (head);
}
}
......
......@@ -78,6 +78,11 @@ void binfmt_setup(void)
#ifdef CONFIG_BINFMT_JAVA
init_java_binfmt();
#endif
#ifdef CONFIG_BINFMT_EM86
init_em86_binfmt();
#endif
/* This cannot be configured out of the kernel */
init_script_binfmt();
}
......
......@@ -32,6 +32,7 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/blkdev.h>
static char error_buf[1024];
......@@ -377,10 +378,26 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
unsigned short resuid = EXT2_DEF_RESUID;
unsigned short resgid = EXT2_DEF_RESGID;
unsigned long logic_sb_block = 1;
unsigned long offset = 0;
kdev_t dev = sb->s_dev;
int blocksize = BLOCK_SIZE;
int hblock;
int db_count;
int i, j;
/*
* See what the current blocksize for the device is, and
* use that as the blocksize. Otherwise (or if the blocksize
* is smaller than the default) use the default.
* This is important for devices that have a hardware
* sectorsize that is larger than the default.
*/
blocksize = get_hardblocksize(dev);
if( blocksize == 0 || blocksize < BLOCK_SIZE )
{
blocksize = BLOCK_SIZE;
}
sb->u.ext2_sb.s_mount_opt = 0;
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
......@@ -391,8 +408,19 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
MOD_INC_USE_COUNT;
lock_super (sb);
set_blocksize (dev, BLOCK_SIZE);
if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
set_blocksize (dev, blocksize);
/*
* If the superblock doesn't start on a sector boundary,
* calculate the offset. FIXME(eric) this doesn't make sense
* that we would have to do this.
*/
if (blocksize != BLOCK_SIZE) {
logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
offset = (sb_block*BLOCK_SIZE) % blocksize;
}
if (!(bh = bread (dev, logic_sb_block, blocksize))) {
sb->s_dev = 0;
unlock_super (sb);
printk ("EXT2-fs: unable to read superblock\n");
......@@ -403,7 +431,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
* Note: s_es must be initialized s_es as soon as possible because
* some ext2 macro-instructions depend on its value
*/
es = (struct ext2_super_block *) bh->b_data;
es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
sb->u.ext2_sb.s_es = es;
sb->s_magic = le16_to_cpu(es->s_magic);
if (sb->s_magic != EXT2_SUPER_MAGIC) {
......@@ -438,7 +466,17 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
if (sb->s_blocksize != BLOCK_SIZE &&
(sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
sb->s_blocksize == 4096)) {
unsigned long offset;
/*
* Make sure the blocksize for the filesystem is larger
* than the hardware sectorsize for the machine.
*/
hblock = get_hardblocksize(dev);
if( (hblock != 0)
&& (sb->s_blocksize < hblock) )
{
printk("EXT2-fs: blocksize too small for device.\n");
goto failed_mount;
}
brelse (bh);
set_blocksize (dev, sb->s_blocksize);
......
......@@ -16,13 +16,18 @@ struct buffer_head *fat_bread (
{
struct buffer_head *ret = NULL;
/* Note that the blocksize is 512 or 1024, but the first read
is always of size 1024. Doing readahead may be counterproductive
/* Note that the blocksize is 512, 1024 or 2048, but the first read
is always of size 1024 (or 2048). Doing readahead may be counterproductive
or just plain wrong. */
if (sb->s_blocksize == 512) {
ret = bread (sb->s_dev,block,512);
} else {
struct buffer_head *real = bread (sb->s_dev,block>>1,1024);
struct buffer_head *real;
if (sb->s_blocksize == 1024){
real = bread (sb->s_dev,block>>1,1024);
}else{
real = bread (sb->s_dev,block>>2,2048);
}
if (real != NULL){
ret = (struct buffer_head *)
......@@ -59,7 +64,11 @@ struct buffer_head *fat_bread (
*/
memset (ret,0,sizeof(*ret));
ret->b_data = real->b_data;
if (block & 1) ret->b_data += 512;
if (sb->s_blocksize == 2048) {
if (block & 3) ret->b_data += (block & 3) << 9;
}else{
if (block & 1) ret->b_data += 512;
}
ret->b_next = real;
}else{
brelse (real);
......
......@@ -172,8 +172,8 @@ static int parse_options(char *options,int *fat, int *blksize, int *debug,
*blksize = simple_strtoul(value,&value,0);
if (*value)
return 0;
if (*blksize != 512 && *blksize != 1024){
printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n");
if (*blksize != 512 && *blksize != 1024 && *blksize != 2048){
printk ("MSDOS FS: Invalid blocksize (512, 1024 or 2048)\n");
}
}
else if (!strcmp(this_char,"sys_immutable")) {
......@@ -205,16 +205,26 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
}
}
if (!parse_options((char *) data, &fat, &blksize, &debug, &opts)
|| (blksize != 512 && blksize != 1024)) {
|| (blksize != 512 && blksize != 1024 && blksize != 2048))
{
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
cache_init();
lock_super(sb);
/* The first read is always 1024 bytes */
sb->s_blocksize = 1024;
set_blocksize(sb->s_dev, 1024);
if( blksize > 1024 )
{
/* Force the superblock to a larger size here. */
sb->s_blocksize = blksize;
set_blocksize(sb->s_dev, blksize);
}
else
{
/* The first read is always 1024 bytes */
sb->s_blocksize = 1024;
set_blocksize(sb->s_dev, 1024);
}
bh = fat_bread(sb, 0);
unlock_super(sb);
if (bh == NULL || !fat_is_uptodate(sb,bh)) {
......@@ -285,7 +295,7 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
/* the misfit with buffer cache and cluster */
/* because clusters (DOS) are often aligned */
/* on odd sectors. */
sb->s_blocksize_bits = blksize == 512 ? 9 : 10;
sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11);
if (error || debug) {
/* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
......@@ -451,7 +461,7 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
!is_exec(raw_entry->ext)))
? S_IRUGO|S_IWUGO : S_IRWXUGO)
& ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG;
inode->i_op = (sb->s_blocksize == 1024)
inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048)
? &fat_file_inode_operations_1024
: &fat_file_inode_operations;
MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
......
......@@ -79,6 +79,10 @@ asmlinkage int sys_setup(void)
init_proc_fs();
#endif
#ifdef CONFIG_LOCKD
nlmxdr_init();
#endif
#ifdef CONFIG_NFS_FS
init_nfs_fs();
#endif
......
......@@ -131,28 +131,12 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
return 0;
while (filp->f_pos < inode->i_size) {
int de_len, next_offset;
int de_len;
#ifdef DEBUG
printk("Block, offset, f_pos: %x %x %x\n",
block, offset, filp->f_pos);
printk("inode->i_size = %x\n",inode->i_size);
#endif
/* Next directory_record on next CDROM sector */
if (offset >= bufsize) {
#ifdef DEBUG
printk("offset >= bufsize\n");
#endif
brelse(bh);
offset = 0;
block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
if (!block)
return 0;
bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
if (!bh)
return 0;
continue;
}
de = (struct iso_directory_record *) (bh->b_data + offset);
inode_number = (block << bufbits) + (offset & (bufsize - 1));
......@@ -166,7 +150,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
CDROM sector. If we are at the end of the directory, we
kick out of the while loop. */
if (de_len == 0) {
if ((de_len == 0) || (offset == bufsize) ) {
brelse(bh);
filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ ISOFS_BLOCK_SIZE);
......@@ -180,40 +164,18 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
continue;
}
/* Make sure that the entire directory record is in the
current bh block.
If not, put the two halves together in "tmpde" */
next_offset = offset + de_len;
if (next_offset > bufsize) {
#ifdef DEBUG
printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
#endif
next_offset &= (bufsize - 1);
memcpy(tmpde, de, bufsize - offset);
brelse(bh);
block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
if (!block)
{
return 0;
}
bh = breada(inode->i_dev, block, bufsize,
filp->f_pos,
inode->i_size);
if (!bh)
{
#ifdef DEBUG
printk("!bh block=%ld, bufsize=%ld\n",block,bufsize);
printk("filp->f_pos = %ld\n",filp->f_pos);
printk("inode->i_size = %ld\n", inode->i_size);
#endif
return 0;
}
memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
de = tmpde;
offset += de_len;
if (offset > bufsize) {
/*
* This would only normally happen if we had
* a buggy cdrom image. All directory
* entries should terminate with a null size
* or end exactly at the end of the sector.
*/
printk("next_offset (%x) > bufsize (%x)\n",
offset,bufsize);
break;
}
offset = next_offset;
/* Handle the case of the '.' directory */
if (de->name_len[0] == 1 && de->name[0] == 0) {
......
......@@ -86,7 +86,10 @@ static int parse_options(char *options, struct iso9660_options * popt)
popt->check = 's'; /* default: strict */
popt->conversion = 'b'; /* default: no conversion */
popt->blocksize = 1024;
popt->mode = S_IRUGO;
popt->mode = S_IRUGO | S_IXUGO; /* r-x for all. The disc could
be shared with DOS machines so
virtually anything could be
a valid executable. */
popt->gid = 0;
popt->uid = 0;
if (!options) return 1;
......@@ -227,23 +230,22 @@ static unsigned int isofs_get_last_session(kdev_t dev)
struct super_block *isofs_read_super(struct super_block *s,void *data,
int silent)
{
struct buffer_head *bh=NULL;
int iso_blknum;
unsigned int blocksize_bits;
int high_sierra;
kdev_t dev = s->s_dev;
unsigned int vol_desc_start;
int orig_zonesize;
struct iso_volume_descriptor *vdp;
struct hs_volume_descriptor *hdp;
struct iso_primary_descriptor *pri = NULL;
struct hs_primary_descriptor *h_pri = NULL;
struct buffer_head * bh = NULL;
unsigned int blocksize;
unsigned int blocksize_bits;
kdev_t dev = s->s_dev;
struct hs_volume_descriptor * hdp;
struct hs_primary_descriptor * h_pri = NULL;
int high_sierra;
int iso_blknum;
struct iso9660_options opt;
int orig_zonesize;
struct iso_primary_descriptor * pri = NULL;
struct iso_directory_record * rootp;
struct iso_volume_descriptor * vdp;
unsigned int vol_desc_start;
struct iso_directory_record *rootp;
struct iso9660_options opt;
MOD_INC_USE_COUNT;
......@@ -265,6 +267,23 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
printk("uid = %d\n", opt.uid);
#endif
/*
* First of all, get the hardware blocksize for this device.
* If we don't know what it is, or the hardware blocksize is
* larger than the blocksize the user specified, then use
* that value.
*/
blocksize = get_hardblocksize(dev);
if( (blocksize != 0)
&& (blocksize > opt.blocksize) )
{
/*
* Force the blocksize we are going to use to be the
* hardware blocksize.
*/
opt.blocksize = blocksize;
}
blocksize_bits = 0;
{
int i = opt.blocksize;
......@@ -273,6 +292,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
i >>=1;
}
}
set_blocksize(dev, opt.blocksize);
lock_super(s);
......@@ -362,6 +382,24 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
/* RDE: convert log zone size to bit shift */
orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
/*
* If the zone size is smaller than the hardware sector size,
* this is a fatal error. This would occur if the
* disc drive had sectors that were 2048 bytes, but the filesystem
* had blocks that were 512 bytes (which should only very rarely
* happen.
*/
if( (blocksize != 0)
&& (orig_zonesize < blocksize) )
{
printk("Logical zone size(%ld) < hardware blocksize(%ld)\n",
orig_zonesize, blocksize);
goto out;
}
switch (s -> u.isofs_sb.s_log_zone_size)
{ case 512: s -> u.isofs_sb.s_log_zone_size = 9; break;
case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
......@@ -403,8 +441,20 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
* Force the blocksize to 512 for 512 byte sectors. The file
* read primitives really get it wrong in a bad way if we don't
* do this.
*
* Note - we should never be setting the blocksize to something
* less than the hardware sector size for the device. If we
* do, we would end up having to read larger buffers and split
* out portions to satisfy requests.
*
* Note2- the idea here is that we want to deal with the optimal
* zonesize in the filesystem. If we have it set to something less,
* then we have horrible problems with trying to piece together
* bits of adjacent blocks in order to properly read directory
* entries. By forcing the blocksize in this way, we ensure
* that we will never be required to do this.
*/
if( orig_zonesize < opt.blocksize )
if( orig_zonesize != opt.blocksize )
{
opt.blocksize = orig_zonesize;
blocksize_bits = 0;
......@@ -482,6 +532,34 @@ int isofs_bmap(struct inode * inode,int block)
printk("_isofs_bmap: block<0");
return 0;
}
/*
* If we are beyond the end of this file, don't give out any
* blocks.
*/
if( (block << ISOFS_BUFFER_BITS(inode)) >= inode->i_size )
{
off_t max_legal_read_offset;
/*
* If we are *way* beyond the end of the file, print a message.
* Access beyond the end of the file up to the next page boundary
* is normal, however because of the way the page cache works.
* In this case, we just return 0 so that we can properly fill
* the page with useless information without generating any
* I/O errors.
*/
max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
& ~(PAGE_SIZE - 1);
if( (block << ISOFS_BUFFER_BITS(inode)) >= max_legal_read_offset )
{
printk("_isofs_bmap: block>= EOF(%d, %d)", block,
inode->i_size);
}
return 0;
}
return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
}
......@@ -502,7 +580,6 @@ void isofs_read_inode(struct inode * inode)
struct buffer_head * bh;
struct iso_directory_record * raw_inode;
unsigned char *pnt = NULL;
void *cpnt = NULL;
int high_sierra;
int block;
int volume_seq_no ;
......@@ -519,30 +596,6 @@ void isofs_read_inode(struct inode * inode)
raw_inode = ((struct iso_directory_record *) pnt);
high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
int frag1, offset;
offset = (inode->i_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);
goto fail;
}
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");
goto fail;
}
offset += *pnt - bufsize;
memcpy((char *)cpnt+frag1, bh->b_data, offset);
pnt = ((unsigned char *) cpnt);
raw_inode = ((struct iso_directory_record *) pnt);
}
if (raw_inode->flags[-high_sierra] & 2) {
inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
inode->i_nlink = 1; /* Set to 1. We know there are 2, but
......@@ -682,10 +735,6 @@ void isofs_read_inode(struct inode * inode)
else if (S_ISFIFO(inode->i_mode))
init_fifo(inode);
}
if (cpnt) {
kfree (cpnt);
cpnt = NULL;
}
return;
fail:
/* With a data error we return this information */
......@@ -725,8 +774,6 @@ int isofs_lookup_grandparent(struct inode * parent, int extent)
unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
unsigned int block,offset;
int parent_dir, inode_number;
int old_offset;
void * cpnt = NULL;
int result;
int directory_size;
struct buffer_head * bh;
......@@ -786,7 +833,7 @@ int isofs_lookup_grandparent(struct inode * parent, int extent)
CDROM sector. If we are at the end of the directory, we
kick out of the while loop. */
if (*((unsigned char *) de) == 0)
if ((*((unsigned char *) de) == 0) || (offset == bufsize) )
{
brelse(bh);
offset = 0;
......@@ -813,31 +860,12 @@ int isofs_lookup_grandparent(struct inode * parent, int extent)
bh block. If not, we malloc a buffer, and put the two
halves together, so that we can cleanly read the block. */
old_offset = offset;
offset += *((unsigned char *) de);
if (offset >= bufsize)
if (offset > bufsize)
{
unsigned int frag1;
frag1 = bufsize - old_offset;
cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
if (!cpnt) return -1;
memcpy(cpnt, bh->b_data + old_offset, frag1);
de = (struct iso_directory_record *) ((char *)cpnt);
brelse(bh);
offset -= bufsize;
directory_size -= bufsize;
if(directory_size < 0)
{
printk("Directory size < 0\n");
return -1;
}
block++;
if(!(bh = bread(parent->i_dev,block,bufsize))) {
kfree(cpnt);
return -1;
}
memcpy((char *)cpnt+frag1, bh->b_data, offset);
printk("Directory overrun\n");
goto out;
}
if (find_rock_ridge_relocation(de, parent) == extent){
......@@ -845,20 +873,12 @@ int isofs_lookup_grandparent(struct inode * parent, int extent)
goto out;
}
if (cpnt) {
kfree(cpnt);
cpnt = NULL;
}
}
/* We go here for any condition we cannot handle.
We also drop through to here at the end of the directory. */
out:
if (cpnt) {
kfree(cpnt);
cpnt = NULL;
}
brelse(bh);
#ifdef DEBUG
printk("Resultant Inode %d\n",result);
......
......@@ -203,6 +203,17 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
break;
case SIG('N','M'):
if (truncate) break;
/*
* If the flags are 2 or 4, this indicates '.' or '..'.
* We don't want to do anything with this, because it
* screws up the code that calls us. We don't really
* care anyways, since we can just use the non-RR
* name.
*/
if (rr->u.NM.flags & 6) {
break;
}
if (rr->u.NM.flags & ~1) {
printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
break;
......
......@@ -84,10 +84,16 @@ isonum_733 (char * p)
return (isonum_731 (p));
}
/* We have to convert from a MM/DD/YY format to the unix ctime format. We have to
take into account leap years and all of that good stuff. Unfortunately, the kernel
does not have the information on hand to take into account daylight savings time,
so there will be cases (roughly half the time) where the dates are off by one hour. */
/*
* We have to convert from a MM/DD/YY format to the unix ctime format.
* We have to take into account leap years and all of that good stuff.
* Unfortunately, the kernel does not have the information on hand to
* take into account daylight savings time, but it shouldn't matter.
* The time stored should be localtime (with or without DST in effect),
* and the timezone offset should hold the offset required to get back
* to GMT. Thus we should always be correct.
*/
int iso_date(char * p, int flag)
{
int year, month, day, hour ,minute, second, tz;
......@@ -121,9 +127,33 @@ int iso_date(char * p, int flag)
if (tz & 0x80)
tz |= (-1 << 8);
/* timezone offset is unreliable on some disks */
if (-48 <= tz && tz <= 52)
crtime += tz * 15 * 60;
/*
* The timezone offset is unreliable on some disks,
* so we make a sanity check. In no case is it ever
* more than 13 hours from GMT, which is 52*15min.
* The time is always stored in localtime with the
* timezone offset being what get added to GMT to
* get to localtime. Thus we need to subtract the offset
* to get to true GMT, which is what we store the time
* as internally. On the local system, the user may set
* their timezone any way they wish, of course, so GMT
* gets converted back to localtime on the receiving
* system.
*
* NOTE: mkisofs in versions prior to mkisofs-1.10 had
* the sign wrong on the timezone offset. This has now
* been corrected there too, but if you are getting screwy
* results this may be the explaination. If enough people
* complain, a user configuration option could be added
* to add the timezone offset in with the wrong sign
* for 'compatibility' with older discs, but I cannot see how
* it will matter that much.
*
* Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
* for pointing out the sign error.
*/
if (-52 <= tz && tz <= 52)
crtime -= tz * 15 * 60;
}
return crtime;
}
......
#
# Makefile for the linux lock manager stuff
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := lockd.o
O_OBJS := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \
svcproc.o svcsubs.o mon.o xdr.o
OX_OBJS := lockd_syms.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
/*
* linux/fs/lockd/clntlock.c
*
* Lock handling for the client side NLM implementation
*
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
#define __KERNEL_SYSCALLS__
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/nfs_fs.h>
#include <linux/unistd.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#define NLMDBG_FACILITY NLMDBG_CIENT
/*
* Local function prototypes
*/
static int reclaimer(void *ptr);
/*
* The following functions handle blocking and granting from the
* client perspective.
*/
/*
* This is the representation of a blocked client lock.
*/
struct nlm_wait {
struct nlm_wait * b_next; /* linked list */
struct wait_queue * b_wait; /* where to wait on */
struct nlm_host * b_host;
struct file_lock * b_lock; /* local file lock */
unsigned short b_reclaim; /* got to reclaim lock */
u32 b_status; /* grant callback status */
};
static struct nlm_wait * nlm_blocked = NULL;
/*
* Block on a lock
*/
int
nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
{
struct nlm_wait block, **head;
int err;
u32 pstate;
block.b_host = host;
block.b_lock = fl;
block.b_wait = NULL;
block.b_status = NLM_LCK_BLOCKED;
block.b_next = nlm_blocked;
nlm_blocked = &block;
/* Remember pseudo nsm state */
pstate = host->h_state;
/* Go to sleep waiting for GRANT callback. Some servers seem
* to lose callbacks, however, so we're going to poll from
* time to time just to make sure.
*
* For now, the retry frequency is pretty high; normally
* a 1 minute timeout would do. See the comment before
* nlmclnt_lock for an explanation.
*/
current->timeout = jiffies + 30 * HZ;
interruptible_sleep_on(&block.b_wait);
for (head = &nlm_blocked; *head; head = &(*head)->b_next) {
if (*head == &block) {
*head = block.b_next;
break;
}
}
if (!signalled()) {
*statp = block.b_status;
return 0;
}
/* Okay, we were interrupted. Cancel the pending request
* unless the server has rebooted.
*/
if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0)
printk(KERN_NOTICE
"lockd: CANCEL call failed (errno %d)\n", -err);
return -ERESTARTSYS;
}
/*
* The server lockd has called us back to tell us the lock was granted
*/
u32
nlmclnt_grant(struct nlm_lock *lock)
{
struct nlm_wait *block;
/*
* Look up blocked request based on arguments.
* Warning: must not use cookie to match it!
*/
for (block = nlm_blocked; block; block = block->b_next) {
if (nlm_compare_locks(block->b_lock, &lock->fl))
break;
}
/* Ooops, no blocked request found. */
if (block == NULL)
return nlm_lck_denied;
/* Alright, we found the lock. Set the return status and
* wake up the caller.
*/
block->b_status = NLM_LCK_GRANTED;
wake_up(&block->b_wait);
return nlm_granted;
}
/*
* The following procedures deal with the recovery of locks after a
* server crash.
*/
/*
* Reclaim all locks on server host. We do this by spawning a separate
* reclaimer thread.
* FIXME: should bump MOD_USE_COUNT while reclaiming
*/
void
nlmclnt_recovery(struct nlm_host *host, u32 newstate)
{
if (!host->h_reclaiming++) {
if (host->h_nsmstate == newstate)
return;
printk(KERN_WARNING
"lockd: Uh-oh! Interfering reclaims for host %s",
host->h_name);
host->h_monitored = 0;
host->h_nsmstate = newstate;
host->h_state++;
nlm_release_host(host);
} else {
host->h_monitored = 0;
host->h_nsmstate = newstate;
host->h_state++;
host->h_count++;
kernel_thread(reclaimer, host, 0);
}
}
static int
reclaimer(void *ptr)
{
struct nlm_host *host = (struct nlm_host *) ptr;
struct nlm_wait *block;
struct file_lock *fl;
struct inode *inode;
/* This one ensures that our parent doesn't terminate while the
* reclaim is in progress */
lockd_up();
/* First, reclaim all locks that have been granted previously. */
do {
for (fl = file_lock_table; fl; fl = fl->fl_next) {
inode = fl->fl_file->f_inode;
if (inode->i_sb->s_magic == NFS_SUPER_MAGIC
&& nlm_cmp_addr(NFS_ADDR(inode), &host->h_addr)
&& fl->fl_u.nfs_fl.state != host->h_state
&& (fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) {
fl->fl_u.nfs_fl.flags &= ~ NFS_LCK_GRANTED;
nlmclnt_reclaim(host, fl);
break;
}
}
} while (fl);
host->h_reclaiming = 0;
wake_up(&host->h_gracewait);
/* Now, wake up all processes that sleep on a blocked lock */
for (block = nlm_blocked; block; block = block->b_next) {
if (block->b_host == host) {
block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
wake_up(&block->b_wait);
}
}
/* Release host handle after use */
nlm_release_host(host);
lockd_down();
return 0;
}
This diff is collapsed.
/*
* linux/fs/lockd/host.c
*
* Management for NLM peer hosts. The nlm_host struct is shared
* between client and server implementation. The only reason to
* do so is to reduce code bloat.
*
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/in.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
#define NLM_HOST_MAX 64
#define NLM_HOST_NRHASH 32
#define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
#define NLM_PTRHASH(ptr) ((((u32) ptr) / 32) & (NLM_HOST_NRHASH-1))
#define NLM_HOST_REBIND (60 * HZ)
#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
#define NLM_HOST_ADDR(sv) (&(sv)->s_nlmclnt->cl_xprt->addr)
static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH];
static unsigned long next_gc = 0;
static int nrhosts = 0;
static struct semaphore nlm_host_sema = MUTEX;
static void nlm_gc_hosts(void);
/*
* Find an NLM server handle in the cache. If there is none, create it.
*/
struct nlm_host *
nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
{
return nlm_lookup_host(NULL, sin, proto, version);
}
/*
* Find an NLM client handle in the cache. If there is none, create it.
*/
struct nlm_host *
nlmsvc_lookup_host(struct svc_rqst *rqstp)
{
return nlm_lookup_host(rqstp->rq_client, &rqstp->rq_addr, 0, 0);
}
/*
* Match the given host against client/address
*/
static inline int
nlm_match_host(struct nlm_host *host, struct svc_client *clnt,
struct sockaddr_in *sin)
{
if (clnt)
return host->h_exportent == clnt;
return nlm_cmp_addr(&host->h_addr, sin);
}
/*
* Common host lookup routine for server & client
*/
struct nlm_host *
nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
int proto, int version)
{
struct nlm_host *host, **hp;
u32 addr;
int hash;
if (!clnt && !sin) {
printk(KERN_NOTICE "lockd: no clnt or addr in lookup_host!\n");
return NULL;
}
dprintk("lockd: nlm_lookup_host(%08lx, p=%d, v=%d)\n",
sin? ntohl(sin->sin_addr.s_addr) : 0, proto, version);
if (clnt)
hash = NLM_PTRHASH(clnt);
else
hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
/* Lock hash table */
down(&nlm_host_sema);
if (next_gc < jiffies)
nlm_gc_hosts();
for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) {
if (host->h_version != version || host->h_proto != proto)
continue;
if (nlm_match_host(host, clnt, sin)) {
if (hp != nlm_hosts + hash) {
*hp = host->h_next;
host->h_next = nlm_hosts[hash];
nlm_hosts[hash] = host;
}
host->h_expires = jiffies + NLM_HOST_EXPIRE;
host->h_count++;
up(&nlm_host_sema);
return host;
}
}
/* special hack for nlmsvc_invalidate_client */
if (sin == NULL)
goto nohost;
/* Ooops, no host found, create it */
dprintk("lockd: creating host entry\n");
if (!(host = (struct nlm_host *) kmalloc(sizeof(*host), GFP_KERNEL)))
goto nohost;
memset(host, 0, sizeof(*host));
addr = sin->sin_addr.s_addr;
sprintf(host->h_name, "%d.%d.%d.%d",
(unsigned char) (ntohl(addr) >> 24),
(unsigned char) (ntohl(addr) >> 16),
(unsigned char) (ntohl(addr) >> 8),
(unsigned char) (ntohl(addr) >> 0));
host->h_addr = *sin;
host->h_addr.sin_port = 0; /* ouch! */
host->h_version = version;
host->h_proto = proto;
host->h_authflavor = RPC_AUTH_NULL;
host->h_rpcclnt = NULL;
host->h_sema = MUTEX;
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
host->h_expires = jiffies + NLM_HOST_EXPIRE;
host->h_count = 1;
host->h_state = 0; /* pseudo NSM state */
host->h_nsmstate = 0; /* real NSM state */
host->h_exportent = clnt;
host->h_next = nlm_hosts[hash];
nlm_hosts[hash] = host;
if (++nrhosts > NLM_HOST_MAX)
next_gc = 0;
nohost:
up(&nlm_host_sema);
return host;
}
/*
* Create the NLM RPC client for an NLM peer
*/
struct rpc_clnt *
nlm_bind_host(struct nlm_host *host)
{
struct rpc_clnt *clnt;
struct rpc_xprt *xprt;
dprintk("lockd: nlm_bind_host(%08lx)\n",
ntohl(host->h_addr.sin_addr.s_addr));
/* Lock host handle */
down(&host->h_sema);
/* If we've already created an RPC client, check whether
* RPC rebind is required */
if ((clnt = host->h_rpcclnt) != NULL) {
if (host->h_nextrebind < jiffies) {
clnt->cl_port = 0;
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
dprintk("lockd: next rebind in %ld jiffies\n",
host->h_nextrebind - jiffies);
}
} else {
uid_t saved_euid = current->euid;
/* Create RPC socket as root user so we get a priv port */
current->euid = 0;
xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
current->euid = saved_euid;
if (xprt == NULL)
goto forgetit;
xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
host->h_version, host->h_authflavor);
if (clnt == NULL) {
xprt_destroy(xprt);
goto forgetit;
}
clnt->cl_autobind = 1; /* turn on pmap queries */
xprt->nocong = 1; /* No congestion control for NLM */
host->h_rpcclnt = clnt;
}
up(&host->h_sema);
return clnt;
forgetit:
printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
up(&host->h_sema);
return NULL;
}
/*
* Force a portmap lookup of the remote lockd port
*/
void
nlm_rebind_host(struct nlm_host *host)
{
dprintk("lockd: rebind host %s\n", host->h_name);
if (host->h_rpcclnt && host->h_nextrebind < jiffies) {
host->h_rpcclnt->cl_port = 0;
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
}
}
/*
* Release NLM host after use
*/
void
nlm_release_host(struct nlm_host *host)
{
dprintk("lockd: release host %s\n", host->h_name);
host->h_count -= 1;
}
/*
* Shut down the hosts module.
* Note that this routine is called only at server shutdown time.
*/
void
nlm_shutdown_hosts(void)
{
struct nlm_host *host;
int i;
dprintk("lockd: shutting down host module\n");
down(&nlm_host_sema);
/* First, make all hosts eligible for gc */
dprintk("lockd: nuking all hosts...\n");
for (i = 0; i < NLM_HOST_NRHASH; i++) {
for (host = nlm_hosts[i]; host; host = host->h_next)
host->h_expires = 0;
}
/* Then, perform a garbage collection pass */
nlm_gc_hosts();
up(&nlm_host_sema);
/* complain if any hosts are left */
if (nrhosts) {
printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
dprintk("lockd: %d hosts left:\n", nrhosts);
for (i = 0; i < NLM_HOST_NRHASH; i++) {
for (host = nlm_hosts[i]; host; host = host->h_next) {
dprintk(" %s (cnt %d use %d exp %ld)\n",
host->h_name, host->h_count,
host->h_inuse, host->h_expires);
}
}
}
}
/*
* Garbage collect any unused NLM hosts.
* This GC combines reference counting for async operations with
* mark & sweep for resources held by remote clients.
*/
static void
nlm_gc_hosts(void)
{
struct nlm_host **q, *host;
struct rpc_clnt *clnt;
int i;
dprintk("lockd: host garbage collection\n");
for (i = 0; i < NLM_HOST_NRHASH; i++) {
for (host = nlm_hosts[i]; host; host = host->h_next)
host->h_inuse = 0;
}
/* Mark all hosts that hold locks, blocks or shares */
nlmsvc_mark_resources();
for (i = 0; i < NLM_HOST_NRHASH; i++) {
q = &nlm_hosts[i];
while ((host = *q) != NULL) {
if (host->h_count || host->h_inuse
|| host->h_expires >= jiffies) {
q = &host->h_next;
continue;
}
dprintk("lockd: delete host %s\n", host->h_name);
*q = host->h_next;
if ((clnt = host->h_rpcclnt) != NULL) {
if (clnt->cl_users) {
printk(KERN_WARNING
"lockd: active RPC handle\n");
clnt->cl_dead = 1;
} else {
rpc_destroy_client(host->h_rpcclnt);
}
}
kfree(host);
nrhosts--;
}
}
next_gc = jiffies + NLM_HOST_COLLECT;
}
/*
* linux/fs/lockd/lockd_syms.c
*
* Symbols exported by the lockd module.
*
* Authors: Olaf Kirch (okir@monad.swb.de)
*
* Copyright (C) 1997 Olaf Kirch <okir@monad.swb.de>
*/
#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
#ifdef CONFIG_MODULES
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sched.h>
#include <linux/uio.h>
#include <linux/unistd.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
/* Start/stop the daemon */
EXPORT_SYMBOL(lockd_up);
EXPORT_SYMBOL(lockd_down);
/* NFS client entry */
EXPORT_SYMBOL(nlmclnt_proc);
/* NFS server entry points/hooks */
EXPORT_SYMBOL(nlmsvc_invalidate_client);
EXPORT_SYMBOL(nlmsvc_ops);
/* Configuration at insmod time */
EXPORT_SYMBOL(nlmsvc_grace_period);
EXPORT_SYMBOL(nlmsvc_timeout);
#endif /* CONFIG_MODULES */
/*
* linux/fs/lockd/mon.c
*
* The kernel statd client.
*
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/types.h>
#include <linux/utsname.h>
#include <linux/kernel.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#include <linux/lockd/sm_inter.h>
#define NLMDBG_FACILITY NLMDBG_MONITOR
static struct rpc_clnt * nsm_create(void);
extern struct rpc_program nsm_program;
/*
* Local NSM state
*/
u32 nsm_local_state = 0;
/*
* Common procedure for SM_MON/SM_UNMON calls
*/
static int
nsm_mon_unmon(struct nlm_host *host, char *what, u32 proc)
{
struct rpc_clnt *clnt;
struct nsm_args args;
struct nsm_res res;
int status;
dprintk("lockd: nsm_%s(%s)\n", what, host->h_name);
if (!(clnt = nsm_create()))
return -EACCES;
args.addr = host->h_addr.sin_addr.s_addr;
args.prog = NLM_PROGRAM;
args.vers = 1;
args.proc = NLMPROC_NSM_NOTIFY;
if ((status = rpc_call(clnt, proc, &args, &res, 0)) < 0)
return status;
if (res.status != 0) {
printk(KERN_NOTICE "lockd: cannot %s %s\n", what, host->h_name);
return -EACCES;
}
nsm_local_state = res.state;
return 0;
}
/*
* Set up monitoring of a remote host
*/
int
nsm_monitor(struct nlm_host *host)
{
int status;
if ((status = nsm_mon_unmon(host, "monitor", SM_MON)) >= 0)
host->h_monitored = 1;
return status;
}
/*
* Cease to monitor remote host
*/
int
nsm_unmonitor(struct nlm_host *host)
{
int status;
if ((status = nsm_mon_unmon(host, "unmonitor", SM_UNMON)) >= 0)
host->h_monitored = 0;
return status;
}
/*
* Create NSM client for the local host
*/
static struct rpc_clnt *
nsm_create(void)
{
struct sockaddr_in sin;
struct rpc_xprt *xprt;
struct rpc_clnt *clnt;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sin.sin_port = 0;
if (!(xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL)))
return NULL;
clnt = rpc_create_client(xprt, "localhost",
&nsm_program, SM_VERSION,
RPC_AUTH_NULL);
if (!clnt) {
xprt_destroy(xprt);
} else {
clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
}
return clnt;
}
/*
* XDR functions for NSM.
*/
static int
xdr_error(struct rpc_rqst *rqstp, u32 *p, void *dummy)
{
return -EACCES;
}
static int
xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
{
char buffer[20];
u32 addr = ntohl(argp->addr);
dprintk("nsm: xdr_encode_mon(%08lx, %ld, %ld, %ld)\n",
htonl(argp->addr), htonl(argp->proc),
htonl(argp->vers), htonl(argp->proc));
/*
* Use the dotted-quad IP address of the remote host as
* identifier. Linux statd always looks up the canonical
* hostname first for whatever remote hostname it receives,
* so this works alright.
*/
sprintf(buffer, "%d.%d.%d.%d", (addr>>24) & 0xff, (addr>>16) & 0xff,
(addr>>8) & 0xff, (addr) & 0xff);
if (!(p = xdr_encode_string(p, buffer))
|| !(p = xdr_encode_string(p, system_utsname.nodename)))
return -EIO;
*p++ = htonl(argp->prog);
*p++ = htonl(argp->vers);
*p++ = htonl(argp->proc);
/* This is the private part. Needed only for SM_MON call */
if (rqstp->rq_task->tk_proc == SM_MON) {
*p++ = argp->addr;
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
return 0;
}
static int
xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
{
resp->status = ntohl(*p++);
resp->state = ntohl(*p++);
dprintk("nsm: xdr_decode_stat_res status %d state %d\n",
resp->status, resp->state);
return 0;
}
static int
xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
{
resp->status = ntohl(*p++);
return 0;
}
#define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN))
#define SM_my_id_sz (3+1+SM_my_name_sz)
#define SM_mon_id_sz (1+XDR_QUADLEN(20)+SM_my_id_sz)
#define SM_mon_sz (SM_mon_id_sz+4)
static struct rpc_procinfo nsm_procedures[] = {
{ "sm_null",
(kxdrproc_t) xdr_error,
(kxdrproc_t) xdr_error, 0, 0 },
{ "sm_stat",
(kxdrproc_t) xdr_error,
(kxdrproc_t) xdr_error, 0, 0 },
{ "sm_mon",
(kxdrproc_t) xdr_encode_mon,
(kxdrproc_t) xdr_decode_stat_res, SM_mon_sz, 2 },
{ "sm_unmon",
(kxdrproc_t) xdr_encode_mon,
(kxdrproc_t) xdr_decode_stat, SM_mon_id_sz, 1 },
{ "sm_unmon_all",
(kxdrproc_t) xdr_error,
(kxdrproc_t) xdr_error, 0, 0 },
{ "sm_simu_crash",
(kxdrproc_t) xdr_error,
(kxdrproc_t) xdr_error, 0, 0 },
{ "sm_notify",
(kxdrproc_t) xdr_error,
(kxdrproc_t) xdr_error, 0, 0 },
};
static struct rpc_version nsm_version1 = {
1,
sizeof(nsm_procedures)/sizeof(nsm_procedures[0]),
nsm_procedures
};
static struct rpc_version * nsm_version[] = {
NULL,
&nsm_version1,
};
static struct rpc_stat nsm_stats;
struct rpc_program nsm_program = {
"statd",
SM_PROGRAM,
sizeof(nsm_version)/sizeof(nsm_version[0]),
nsm_version,
&nsm_stats
};
/*
* linux/fs/lockd/svc.c
*
* This is the central lockd service.
*
* FIXME: Separate the lockd NFS server functionality from the lockd NFS
* client functionality. Oh why didn't Sun create two separate
* services in the first place?
*
* Authors: Olaf Kirch (okir@monad.swb.de)
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/nfs.h>
#include <linux/in.h>
#include <linux/uio.h>
#include <linux/version.h>
#include <linux/unistd.h>
#include <linux/malloc.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/lockd/lockd.h>
#define NLMDBG_FACILITY NLMDBG_SVC
#define LOCKD_BUFSIZE (1024 + NLMSSVC_XDRSIZE)
#define BLOCKABLE_SIGS (~(_S(SIGKILL) | _S(SIGSTOP)))
#define _S(sig) (1 << ((sig) - 1))
extern struct svc_program nlmsvc_program;
struct nlmsvc_binding * nlmsvc_ops = NULL;
static int nlmsvc_sema = 0;
static int nlmsvc_pid = 0;
unsigned long nlmsvc_grace_period = 0;
unsigned long nlmsvc_timeout = 0;
/*
* Currently the following can be set only at insmod time.
* Ideally, they would be accessible through the sysctl interface.
*/
unsigned long nlm_grace_period = 0;
unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
/*
* This is the lockd kernel thread
*/
static void
lockd(struct svc_rqst *rqstp)
{
struct svc_serv *serv = rqstp->rq_server;
sigset_t oldsigmask;
int err = 0;
lock_kernel();
/* Lock module and set up kernel thread */
MOD_INC_USE_COUNT;
/* exit_files(current); */
exit_mm(current);
current->session = 1;
current->pgrp = 1;
sprintf(current->comm, "lockd");
/* kick rpciod */
rpciod_up();
dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
if (!nlm_timeout)
nlm_timeout = LOCKD_DFLT_TIMEO;
#ifdef RPC_DEBUG
nlmsvc_grace_period = 10 * HZ;
#else
if (nlm_grace_period) {
nlmsvc_grace_period += (1 + nlm_grace_period / nlm_timeout)
* nlm_timeout * HZ;
} else {
nlmsvc_grace_period += 5 * nlm_timeout * HZ;
}
#endif
nlmsvc_grace_period += jiffies;
nlmsvc_timeout = nlm_timeout * HZ;
nlmsvc_pid = current->pid;
/*
* The main request loop. We don't terminate until the last
* NFS mount or NFS daemon has gone away, and we've been sent a
* signal.
*/
while (nlmsvc_sema || !signalled()) {
if (signalled())
current->signal = 0;
/*
* Retry any blocked locks that have been notified by
* the VFS. Don't do this during grace period.
* (Theoretically, there shouldn't even be blocked locks
* during grace period).
*/
if (!nlmsvc_grace_period) {
current->timeout = nlmsvc_retry_blocked();
} else if (nlmsvc_grace_period < jiffies)
nlmsvc_grace_period = 0;
/*
* Find a socket with data available and call its
* recvfrom routine.
*/
if ((err = svc_recv(serv, rqstp)) == -EAGAIN)
continue;
if (err < 0) {
if (err != -EINTR)
printk(KERN_WARNING
"lockd: terminating on error %d\n",
-err);
break;
}
dprintk("lockd: request from %08lx\n",
ntohl(rqstp->rq_addr.sin_addr.s_addr));
/*
* Look up the NFS client handle. The handle is needed for
* all but the GRANTED callback RPCs.
*/
if (nlmsvc_ops) {
nlmsvc_ops->exp_readlock();
rqstp->rq_client =
nlmsvc_ops->exp_getclient(&rqstp->rq_addr);
} else {
rqstp->rq_client = NULL;
}
/* Process request with all signals blocked. */
oldsigmask = current->blocked;
current->blocked = BLOCKABLE_SIGS;
svc_process(serv, rqstp);
current->blocked = oldsigmask;
/* Unlock export hash tables */
if (nlmsvc_ops)
nlmsvc_ops->exp_unlock();
}
nlm_shutdown_hosts();
/* Exit the RPC thread */
svc_exit_thread(rqstp);
/* release rpciod */
rpciod_down();
/* Release module */
MOD_DEC_USE_COUNT;
nlmsvc_pid = 0;
}
/*
* Make a socket for lockd
* FIXME: Move this to net/sunrpc/svc.c so that we can share this with nfsd.
*/
static int
lockd_makesock(struct svc_serv *serv, int protocol, unsigned short port)
{
struct sockaddr_in sin;
dprintk("lockd: creating socket proto = %d\n", protocol);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
return svc_create_socket(serv, protocol, &sin);
}
int
lockd_up(void)
{
struct svc_serv * serv;
int error;
if (nlmsvc_pid || nlmsvc_sema++)
return 0;
dprintk("lockd: creating service\n");
if ((serv = svc_create(&nlmsvc_program, 0, NLMSVC_XDRSIZE)) == NULL)
return -ENOMEM;
if ((error = lockd_makesock(serv, IPPROTO_UDP, 0)) < 0
|| (error = lockd_makesock(serv, IPPROTO_TCP, 0)) < 0) {
svc_destroy(serv);
return error;
}
if ((error = svc_create_thread(lockd, serv)) < 0)
nlmsvc_sema--;
/* Release server */
svc_destroy(serv);
return 0;
}
void
lockd_down(void)
{
if (!nlmsvc_pid || --nlmsvc_sema > 0)
return;
kill_proc(nlmsvc_pid, SIGKILL, 1);
nlmsvc_sema = 0;
nlmsvc_pid = 0;
}
#ifdef MODULE
/* New module support in 2.1.18 */
#if LINUX_VERSION_CODE >= 0x020112
EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
MODULE_PARM(nlm_grace_period, "10-240l");
MODULE_PARM(nlm_timeout, "3-20l");
#endif
int
init_module(void)
{
nlmxdr_init();
return 0;
}
void
cleanup_module(void)
{
/* FIXME: delete all NLM clients */
nlm_shutdown_hosts();
}
#endif
/*
* Define NLM program and procedures
*/
static struct svc_version nlmsvc_version1 = {
1, 16, nlmsvc_procedures, NULL
};
static struct svc_version nlmsvc_version3 = {
3, 24, nlmsvc_procedures, NULL
};
#ifdef CONFIG_NFSD_NFS3
static struct svc_version nlmsvc_version4 = {
4, 24, nlmsvc_procedures4, NULL
};
#endif
static struct svc_version * nlmsvc_version[] = {
NULL,
&nlmsvc_version1,
NULL,
&nlmsvc_version3,
#ifdef CONFIG_NFSD_NFS3
&nlmsvc_version4,
#endif
};
static struct svc_stat nlmsvc_stats;
#define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
struct svc_program nlmsvc_program = {
NLM_PROGRAM, /* program number */
1, NLM_NRVERS-1, /* version range */
NLM_NRVERS, /* number of entries in nlmsvc_version */
nlmsvc_version, /* version table */
"lockd", /* service name */
&nlmsvc_stats, /* stats table */
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -8,11 +8,11 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := nfs.o
O_OBJS := proc.o sock.o rpcsock.o inode.o file.o bio.o \
nfsiod.o dir.o symlink.o
O_OBJS := inode.o file.o read.o write.o dir.o symlink.o proc.o \
nfs2xdr.o
ifdef CONFIG_ROOT_NFS
O_OBJS += nfsroot.o
O_OBJS += nfsroot.o
endif
M_OBJS := $(O_TARGET)
......
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.
#
# Makefile for the linux nfs-filesystem routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := nfsd.o
O_OBJS := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
export.o auth.o lockd.o nfscache.o nfsxdr.o
ifdef CONFIG_PROC_FS
O_OBJS += stats.o
endif
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
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.
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.
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.
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.
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.
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