From: Linus Torvalds Date: Fri, 23 Nov 2007 20:09:47 +0000 (-0500) Subject: Import 1.1.75 X-Git-Tag: 1.1.75 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=ec1d199493b2a801668065e139860bdf35fae2e9;p=history.git Import 1.1.75 --- diff --git a/CREDITS b/CREDITS index 23ceb1d67e6b..72cb5d1514da 100644 --- a/CREDITS +++ b/CREDITS @@ -546,6 +546,16 @@ S: Boterkorfhoek 34 S: 7546 JA Enschede S: Netherlands +N: David S. Miller +E: davem@caip.rutgers.edu +D: Sparc hacker +D: New Linux-Activists maintainer +D: Linux Emacs elf/qmagic support + other libc/gcc things +D: Yee bore de yee bore! ;-) +S: 2 Bristol Court +S: East Brunswick, New Jersey 08816 +S: USA + N: Rick Miller E: rick@discus.mil.wi.us D: Linux Device Registrar (Major/minor numbers), "au-play", "bwBASIC" diff --git a/Makefile b/Makefile index de9113fbeac4..8b799fdf07e6 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,9 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 74 +SUBLEVEL = 75 ARCH = i386 -all: Version zImage - .EXPORT_ALL_VARIABLES: CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -13,6 +11,8 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else echo sh; fi ; fi) TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) +all: do-it-all + # # Make "config" the default target if there is no configuration file or # "depend" the target if there is no top-level dependency information. @@ -21,11 +21,14 @@ ifeq (.config,$(wildcard .config)) include .config ifeq (.depend,$(wildcard .depend)) include .depend +do-it-all: Version arch-all else CONFIGURATION = depend +do-it-all: depend endif else CONFIGURATION = config +do-it-all: config endif # @@ -55,7 +58,7 @@ SVGA_MODE= -DSVGA_MODE=NORMAL_VGA # standard CFLAGS # -CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe +CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer ifdef CONFIG_CPP CFLAGS := $(CFLAGS) -x c++ @@ -156,6 +159,7 @@ boot/head.s: boot/head.S $(CONFIGURE) include/linux/tasks.h $(CPP) -traditional $< -o $@ tools/version.o: tools/version.c include/linux/version.h + $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o tools/version.o tools/version.c init/main.o: $(CONFIGURE) init/main.c $(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $< diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 35800431acb3..ace120d8e809 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -17,22 +17,7 @@ CPP =$(CC) -E AR =ar STRIP =strip -zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem - $(MAKE) -C zBoot - -zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build - tools/build boot/bootsect boot/setup zBoot/zSystem $(ROOT_DEV) > zImage - sync - -zdisk: zImage - dd bs=8192 if=zImage of=/dev/fd0 - -zlilo: $(CONFIGURE) zImage - if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi - if [ -f $(INSTALL_PATH)/zSystem.map ]; then mv $(INSTALL_PATH)/zSystem.map $(INSTALL_PATH)/zSystem.old; fi - cat zImage > $(INSTALL_PATH)/vmlinuz - cp zSystem.map $(INSTALL_PATH)/ - if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi +arch-all: tools/system tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs $(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \ @@ -44,24 +29,6 @@ tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ sort > System.map -boot/setup.o: boot/setup.s - $(AS) -o $@ $< - -boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile - $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ - -boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile - $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ - -tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs - $(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \ - $(ARCHIVES) \ - $(FILESYSTEMS) \ - $(DRIVERS) \ - $(LIBS) \ - -o tools/zSystem - nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ - sort > zSystem.map # # Leave these dummy entries for now to tell people that they are going away.. @@ -74,4 +41,4 @@ lilo: @exit 1 archclean: - rm -f boot/bootsect boot/setup + @rm -f boot/head.o diff --git a/arch/alpha/boot/head.S b/arch/alpha/boot/head.S index 03a2a90108be..ab1a48d09e7e 100644 --- a/arch/alpha/boot/head.S +++ b/arch/alpha/boot/head.S @@ -6,6 +6,7 @@ #include +#undef halt #define halt .long PAL_halt /* diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 0003cfd24e21..586a451cc72f 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -19,6 +19,8 @@ CPP =$(CC) -E AR =ar STRIP =strip +CFLAGS := $(CFLAGS) -pipe + ifdef CONFIG_M486 CFLAGS := $(CFLAGS) -m486 else @@ -29,6 +31,8 @@ CFLAGS := $(CFLAGS) -m386 endif endif +arch-all: zImage + zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem $(MAKE) -C zBoot diff --git a/arch/i386/boot/head.S b/arch/i386/boot/head.S index 4327b375698a..db54704565e9 100644 --- a/arch/i386/boot/head.S +++ b/arch/i386/boot/head.S @@ -37,7 +37,7 @@ startup_32: mov %ax,%es mov %ax,%fs mov %ax,%gs - lss _stack_start,%esp + lss stack_start,%esp /* * Clear BSS first so that there are no surprises... */ @@ -164,7 +164,7 @@ is386: pushl %ecx # restore original EFLAGS mov %ax,%es mov %ax,%fs mov %ax,%gs - lss _stack_start,%esp + lss stack_start,%esp xorl %eax,%eax lldt %ax pushl %eax # These are the parameters to main :-) @@ -294,6 +294,10 @@ _empty_zero_page: */ _floppy_track_buffer: .fill 512*2*MAX_BUFFER_SECTORS,1,0 + +stack_start: + .long _init_user_stack+4096 + .long KERNEL_DS /* This is the default interrupt "handler" :-) */ int_msg: diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 621f84a91974..be30b6af9733 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -71,6 +71,20 @@ int * blk_size[MAX_BLKDEV] = { NULL, NULL, }; */ int * blksize_size[MAX_BLKDEV] = { NULL, NULL, }; +/* + * hardsect_size contains the size of the hardware sector of a device. + * + * hardsect_size[MAJOR][MINOR] + * + * if (!hardsect_size[MAJOR]) + * then 512 bytes is assumed. + * else + * sector_size is hardsect_size[MAJOR][MINOR] + * This is currently set by some scsi device and read by the msdos fs driver + * This might be a some uses later. + */ +int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, }; + /* * look for a free request in the first N entries. * NOTE: interrupts must be disabled on the way in, and will still diff --git a/drivers/block/sbpcd.c b/drivers/block/sbpcd.c index f38f15b7308d..e209e97b2864 100644 --- a/drivers/block/sbpcd.c +++ b/drivers/block/sbpcd.c @@ -152,7 +152,7 @@ * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and * experiments by Serge Robyns. * First attempts to support the TEAC CD-55A drives; but still not - * useable yet. + * usable yet. * Implemented the CDROMMULTISESSION and CDROMMULTISESSION_SYS ioctls; * this is an attempt to handle multi session CDs more "transparent" * (redirection handling has to be done within the isofs routines, and @@ -243,7 +243,7 @@ * linux/fs/isofs/inode.c * if set to 0 here */ -#define TEAC 0 /* if 1: enable TEAC CD-55A support (not useable yet) */ +#define TEAC 0 /* if 1: enable TEAC CD-55A support (not usable yet) */ #define JUKEBOX 1 /* tray control: eject tray if no disk is in */ #define EJECT 1 /* tray control: eject tray after last use */ #define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */ @@ -625,7 +625,7 @@ static void sbpcd_dprintf(int level, char *fmt, ...) } /* - * DDI interface: runtime trace bit pattern maintainance + * DDI interface: runtime trace bit pattern maintenance */ static int sbpcd_dbg_ioctl(unsigned long arg, int level) { diff --git a/drivers/char/console.c b/drivers/char/console.c index aaf9b66a2f66..0348940ca0d8 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -2337,15 +2337,16 @@ int do_screendump(int arg, int mode) #endif switch(mode) { case 0: - sptr = (char *) origin; + sptr = (char *) origin; for (l=chcount; l>0 ; l--, sptr++) - put_fs_byte(*sptr++,buf++); + put_fs_byte(*sptr++,buf++); break; case 1: put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++); memcpy_tofs(buf,(char *)origin,2*chcount); break; case 2: + gotoxy(currcons, get_fs_byte(buf+2), get_fs_byte(buf+3)); buf+=4; /* ioctl#, console#, x,y */ memcpy_fromfs((char *)origin,buf,2*chcount); break; @@ -2445,9 +2446,12 @@ static inline int atedge(const int p) } /* constrain v such that v <= u */ -static inline short limit(const unsigned short v, const unsigned short u) +static inline unsigned short limit(const unsigned short v, const unsigned short u) { - return ((v > u) ? u : v); +/* gcc miscompiles the ?: operator, so don't use it.. */ + if (v > u) + return u; + return v; } /* invoked via ioctl(TIOCLINUX) */ diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 2e49035397e8..63d0799e1010 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -16,7 +16,7 @@ static char rcsid[] = * * $Log: cyclades.c,v $ * Revision 1.35 1994/12/16 13:54:18 steffen - * addditional patch by Marcio Saito for board detection + * additional patch by Marcio Saito for board detection * Accidently left out in 1.34 * * Revision 1.34 1994/12/10 12:37:12 steffen @@ -304,7 +304,7 @@ static unsigned char *tmp_buf = 0; static struct semaphore tmp_buf_sem = MUTEX; /* - * This is used to look up the divsor speeds and the timeouts + * This is used to look up the divisor speeds and the timeouts * We're normally limited to 15 distinct baud rates. The extra * are accessed via settings in info->flags. * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, @@ -326,7 +326,7 @@ static char baud_bpr[] = { /* 25 MHz baud rate period table */ 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; -static char baud_cor3[] = { /* receive threashold */ +static char baud_cor3[] = { /* receive threshold */ 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x01}; @@ -1925,7 +1925,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, case TIOCMSET: ret_val = set_modem_info(info, cmd, (unsigned int *) arg); -/* The following commands are imcompletely implemented!!! */ +/* The following commands are incompletely implemented!!! */ case TIOCGSOFTCAR: error = verify_area(VERIFY_WRITE, (void *) arg ,sizeof(unsigned int *)); @@ -2038,7 +2038,7 @@ cy_close(struct tty_struct * tty, struct file * filp) info->count = 1; } #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: decrmenting count to %d\n", __LINE__, info->count - 1); + printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1); #endif if (--info->count < 0) { printk("cy_close: bad serial port count for ttys%d: %d\n", @@ -2204,7 +2204,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, #endif info->count--; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: decrmenting count to %d\n", __LINE__, info->count); + printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); #endif info->blocked_open++; @@ -2263,7 +2263,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, if (!tty_hung_up_p(filp)){ info->count++; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: incrmenting count to %d\n", __LINE__, info->count); + printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); #endif } info->blocked_open--; @@ -2279,7 +2279,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, /* * This routine is called whenever a serial port is opened. It - * performs the serial-specific initalization for the tty structure. + * performs the serial-specific initialization for the tty structure. */ int cy_open(struct tty_struct *tty, struct file * filp) @@ -2304,7 +2304,7 @@ cy_open(struct tty_struct *tty, struct file * filp) #endif info->count++; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: incrmenting count to %d\n", __LINE__, info->count); + printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); #endif tty->driver_data = info; info->tty = tty; diff --git a/drivers/char/kbd_kern.h b/drivers/char/kbd_kern.h index 440b0d5bb5eb..db4a9158a6a7 100644 --- a/drivers/char/kbd_kern.h +++ b/drivers/char/kbd_kern.h @@ -2,8 +2,6 @@ #define _KBD_KERN_H #include -#define set_leds() mark_bh(KEYBOARD_BH) - #include extern char *func_table[MAX_NR_FUNC]; @@ -66,6 +64,14 @@ extern unsigned long kbd_init(unsigned long); extern unsigned char getledstate(void); extern void setledstate(struct kbd_struct *kbd, unsigned int led); +extern inline void set_leds(void) +{ + /* con_init calls (indirectly) set_leds before kbd_init + has been called; ignore these early calls */ + if (bh_base[KEYBOARD_BH].routine) + mark_bh(KEYBOARD_BH); +} + extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag) { return ((kbd->modeflags >> flag) & 1); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index ddd4bf56ac4c..b6b5b3de2dbd 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -129,7 +129,7 @@ kd_mksound(unsigned int count, unsigned int ticks) int vt_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int i; + int i, perm; unsigned int console; unsigned char ucval; struct kbd_struct * kbd; @@ -140,13 +140,25 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, if (!vc_cons_allocated(console)) /* impossible? */ return -ENOIOCTLCMD; + /* + * To have permissions to do most of the vt ioctls, we either have + * to be the owner of the tty, or super-user. + */ + perm = 0; + if (current->tty == tty || suser()) + perm = 1; + kbd = kbd_table + console; switch (cmd) { case KIOCSOUND: + if (!perm) + return -EPERM; kd_mksound((unsigned int)arg, 0); return 0; case KDMKTONE: + if (!perm) + return -EPERM; { unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000; @@ -190,7 +202,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * doesn't do a whole lot. i'm not sure if it should do any * restoration of modes or what... */ - if (!suser()) + if (!perm) return -EPERM; switch (arg) { case KD_GRAPHICS: @@ -232,7 +244,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return -EINVAL; case KDSKBMODE: - if (!suser()) + if (!perm) return -EPERM; switch(arg) { case K_RAW: @@ -313,7 +325,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, struct kbkeycode * const a = (struct kbkeycode *)arg; unsigned int sc, kc; - if (!suser()) + if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode)); if (i) @@ -354,7 +366,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, u_char s; u_short v; - if (!suser()) + if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry)); if (i) @@ -445,7 +457,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, u_char *p; char *q; - if (!suser()) + if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry)); if (i) @@ -530,7 +542,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, struct kbdiacrs *a = (struct kbdiacrs *)arg; unsigned int ct; - if (!suser()) + if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs)); if (i) @@ -554,7 +566,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return 0; case KDSKBLED: - if (!suser()) + if (!perm) return -EPERM; if (arg & ~0x77) return -EINVAL; @@ -582,7 +594,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, struct vt_mode *vtmode = (struct vt_mode *)arg; char mode; - if (!suser()) + if (!perm) return -EPERM; i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode)); if (i) @@ -659,7 +671,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * to preserve sanity). */ case VT_ACTIVATE: - if (!suser()) + if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; @@ -674,7 +686,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * wait until the specified VT has been activated */ case VT_WAITACTIVE: - if (!suser()) + if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; @@ -697,7 +709,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * 2: completed switch-to OK */ case VT_RELDISP: - if (!suser()) + if (!perm) return -EPERM; if (vt_cons[console]->vt_mode.mode != VT_PROCESS) return -EINVAL; @@ -747,7 +759,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * Disallocate memory associated to VT (but leave VT1) */ case VT_DISALLOCATE: - if (!suser()) + if (!perm) return -EPERM; if (arg > MAX_NR_CONSOLES) return -ENXIO; @@ -776,7 +788,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, { struct vt_sizes *vtsizes = (struct vt_sizes *) arg; ushort ll,cc; - if (!suser()) + if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes)); if (i) @@ -787,7 +799,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, } case PIO_FONT: - if (!suser()) + if (!perm) return -EPERM; return con_set_font((char *)arg); /* con_set_font() defined in console.c */ @@ -797,7 +809,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, /* con_get_font() defined in console.c */ case PIO_SCRNMAP: - if (!suser()) + if (!perm) return -EPERM; return con_set_trans((char *)arg); /* con_set_trans() defined in console.c */ diff --git a/drivers/net/slip.c b/drivers/net/slip.c index de49f494084e..1193fbb65fac 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -27,7 +27,7 @@ * Dmitry Gorodchanin : SLIP memory leaks * Dmitry Gorodchanin : Code cleanup. Reduce tty driver * buffering from 4096 to 256 bytes. - * Improving SLIP responce time. + * Improving SLIP response time. * CONFIG_SLIP_MODE_SLIP6. * ifconfig sl? up & down now works correctly. * Modularization. diff --git a/drivers/net/slip.h b/drivers/net/slip.h index 92b3c12ca055..b60c1cb041de 100644 --- a/drivers/net/slip.h +++ b/drivers/net/slip.h @@ -54,7 +54,7 @@ struct slip { unsigned long rx_packets; /* inbound frames counter */ unsigned long tx_packets; /* outbound frames counter */ unsigned long rx_errors; /* Parity, etc. errors */ - unsigned long tx_errors; /* Palnned stuff */ + unsigned long tx_errors; /* Planned stuff */ unsigned long rx_dropped; /* No memory for skb */ unsigned long tx_dropped; /* When MTU change */ unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */ diff --git a/drivers/scsi/buslogic.c b/drivers/scsi/buslogic.c index 77f837e64278..14ec86b8de53 100644 --- a/drivers/scsi/buslogic.c +++ b/drivers/scsi/buslogic.c @@ -144,7 +144,7 @@ with a MIDI card, which frequently also uses 0x330. This can also be overridden on the command line to the kernel, via LILO or - LODLIN. */ + LOADLIN. */ static unsigned short bases[7] = { #ifdef BUSLOGIC_PORT_OVERRIDE BUSLOGIC_PORT_OVERRIDE, diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 6c4f46da10cd..3a655c56d353 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -165,6 +165,8 @@ static struct blist blacklist[] = {"MEDIAVIS","CDR-H93MV","1.31"}, /* Locks up if polled for lun != 0 */ {"SANKYO", "CP525","6.64"}, /* causes failed REQ SENSE, extra reset */ {"HP", "C1750A", "3226"}, /* scanjet iic */ + {"HP", "C1790A", ""}, /* scanjet iip */ + {"HP", "C2500A", ""}, /* scanjet iicx */ {NULL, NULL, NULL}}; static int blacklisted(unsigned char * response_data){ @@ -2188,7 +2190,7 @@ static int scsi_register_host(Scsi_Host_Template * tpnt) } /* - * Similarily, this entry point should be called by a loadable module if it + * Similarly, this entry point should be called by a loadable module if it * is trying to remove a low level scsi driver from the system. */ static void scsi_unregister_host(Scsi_Host_Template * tpnt) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 253f8d2dca03..6acb7bb5d327 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -49,6 +49,7 @@ struct hd_struct * sd; Scsi_Disk * rscsi_disks; static int * sd_sizes; static int * sd_blocksizes; +static int * sd_hardsizes; /* Hardware sector size */ extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); @@ -994,6 +995,21 @@ static int sd_init_onedisk(int i) return i; }; } + { + /* + The msdos fs need to know the hardware sector size + So I have created this table. See ll_rw_blk.c + Jacques Gelinas (Jacques@solucorp.qc.ca) + */ + int m; + int hard_sector = rscsi_disks[i].sector_size; + /* There is 16 minor allocated for each devices */ + for (m=i<<4; m<((i+1)<<4); m++){ + sd_hardsizes[m] = hard_sector; + } + printk ("SCSI Hardware sector size is %d bytes on device sd%c\n" + ,hard_sector,i+'a'); + } if(rscsi_disks[i].sector_size == 1024) rscsi_disks[i].capacity <<= 1; /* Change this into 512 byte sectors */ if(rscsi_disks[i].sector_size == 256) @@ -1042,9 +1058,14 @@ static void sd_init() sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int)); - for(i=0;i<(sd_template.dev_max << 4);i++) sd_blocksizes[i] = 1024; + sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * + sizeof(int)); + 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) * sizeof(struct hd_struct)); diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 9d7dca68c821..323c3a86acee 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -290,11 +290,14 @@ static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt); static inline int find_and_clear_bit_16(unsigned short *field) { int rv; + unsigned long flags; + + save_flags(flags); cli(); if (*field == 0) panic("No free mscp"); asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b" : "=&r" (rv), "=m" (*field) : "1" (*field)); - sti(); + restore_flags(flags); return rv; } diff --git a/fs/dcache.c b/fs/dcache.c index a40bdf316065..b236a5cdb30f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -29,7 +29,7 @@ * to be short. */ #define DCACHE_NAME_LEN 15 -#define DCACHE_SIZE 64 +#define DCACHE_SIZE 128 struct hash_list { struct dir_cache_entry * next; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index b272ba11eac5..89853271d560 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -17,11 +17,6 @@ #include #include -#define MULTISESSION /* emoenke@gwdg.de */ -#ifdef MULTISESSION -#include -#endif MULTISESSION - #include #include @@ -150,14 +145,6 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, unsigned int blocksize_bits; int high_sierra; int dev=s->s_dev; -#ifdef MULTISESSION - int i; - unsigned int vol_desc_start; - unsigned int *p_vol_desc_start=&vol_desc_start; - struct inode inode_fake; - struct file file_fake; - extern struct file_operations * get_blkfops(unsigned int); -#endif MULTISESSION struct iso_volume_descriptor *vdp; struct hs_volume_descriptor *hdp; @@ -197,27 +184,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */ -#ifdef MULTISESSION - /* - * look if the driver can tell the multi session redirection - * value; this allows to do the redirection if we are looking - * for the volume descriptor, and to avoid it during "raw" access. - */ - vol_desc_start=0; - inode_fake.i_rdev=dev; - i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake, - &file_fake, - CDROMMULTISESSION_SYS, - (unsigned long) p_vol_desc_start); - if (i!=0) vol_desc_start=0; -#if 0 - printk("isofs.inode: CDROMMULTISESSION_SYS rc=%d\n",i); - printk("isofs.inode: vol_desc_start = %d\n", vol_desc_start); -#endif - for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; iso_blknum++) { -#else for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) { -#endif MULTISESSION if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) { s->s_dev=0; printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n", diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile index 2c690d3ea0fc..479332dc3fe6 100644 --- a/fs/msdos/Makefile +++ b/fs/msdos/Makefile @@ -18,7 +18,7 @@ endif .s.o: $(AS) -o $*.o $< -OBJS= namei.o inode.o file.o dir.o misc.o fat.o +OBJS= buffer.o namei.o inode.o file.o dir.o misc.o fat.o mmap.o msdos.o: $(OBJS) $(LD) -r -o msdos.o $(OBJS) diff --git a/fs/msdos/buffer.c b/fs/msdos/buffer.c new file mode 100644 index 000000000000..8bb34ed49ac1 --- /dev/null +++ b/fs/msdos/buffer.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include + +struct buffer_head *msdos_bread ( + struct super_block *sb, + int block) +{ + struct buffer_head *ret = NULL; + if (sb->s_blocksize == 512){ + ret = bread (sb->s_dev,block,512); + }else{ + struct buffer_head *real = bread (sb->s_dev,block>>1,1024); + if (real != NULL){ + ret = (struct buffer_head *)kmalloc (sizeof(struct buffer_head) + ,GFP_KERNEL); + if (ret != NULL){ + /* #Specification: msdos / strategy / special device / dummy blocks + Many special device (Scsi optical disk for one) use + larger hardware sector size. This allows for higher + capacity. + + Most of the time, the MsDOS file system that sit + on this device is totally unaligned. It use logically + 512 bytes sector size, with logical sector starting + in the middle of a hardware block. The bad news is + that a hardware sector may hold data own by two + different files. This means that the hardware sector + must be read, patch and written allmost all the time. + + Needless to say that it kills write performance + on all OS. + + Internally the linux msdos fs is using 512 bytes + logical sector. When accessing such a device, we + allocate dummy buffer cache blocks, that we stuff + with the information of a real one (1k large). + + This strategy is used to hide this difference to + the core of the msdos fs. The slowdown is not + hidden though! + */ + /* + THe memset is there only to catch errors. The msdos + fs is only unsing b_data + */ + memset (ret,0,sizeof(*ret)); + ret->b_data = real->b_data; + if (block & 1) ret->b_data += 512; + ret->b_next = real; + }else{ + brelse (real); + } + } + } + return ret; +} +struct buffer_head *msdos_getblk ( + struct super_block *sb, + int block) +{ + struct buffer_head *ret = NULL; + if (sb->s_blocksize == 512){ + ret = getblk (sb->s_dev,block,512); + }else{ + /* #Specification: msdos / special device / writing + A write is always preceded by a read of the complete block + (large hardware sector size). This defeat write performance. + There is a possibility to optimize this when writing large + chunk by making sure we are filling large block. Volunter ? + */ + ret = msdos_bread (sb,block); + } + return ret; +} + +void msdos_brelse ( + struct super_block *sb, + struct buffer_head *bh) +{ + if (bh != NULL){ + if (sb->s_blocksize == 512){ + brelse (bh); + }else{ + brelse (bh->b_next); + /* We can free the dummy because a new one is allocated at + each msdos_getblk() and msdos_bread(). + */ + kfree (bh); + } + } +} + +void msdos_mark_buffer_dirty ( + struct super_block *sb, + struct buffer_head *bh, + int dirty_val) +{ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } + mark_buffer_dirty (bh,dirty_val); +} + +void msdos_set_uptodate ( + struct super_block *sb, + struct buffer_head *bh, + int val) +{ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } + bh->b_uptodate = val; +} +int msdos_is_uptodate ( + struct super_block *sb, + struct buffer_head *bh) +{ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } + return bh->b_uptodate; +} + +void msdos_ll_rw_block ( + struct super_block *sb, + int opr, + int nbreq, + struct buffer_head *bh[32]) +{ + if (sb->s_blocksize == 512){ + ll_rw_block(opr,nbreq,bh); + }else{ + struct buffer_head *tmp[32]; + int i; + for (i=0; ib_next; + } + ll_rw_block(opr,nbreq,tmp); + } +} + diff --git a/fs/msdos/dir.c b/fs/msdos/dir.c index 2138b8778c52..77bd05c224d4 100644 --- a/fs/msdos/dir.c +++ b/fs/msdos/dir.c @@ -14,6 +14,8 @@ #include #include +#include "msbuffer.h" + #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+3) & ~3) @@ -62,6 +64,7 @@ int msdos_readdir( struct dirent *dirent, /* dirent in user space */ int count) { + struct super_block *sb = inode->i_sb; int ino,i,i2,last; char c,*walk; struct buffer_head *bh; diff --git a/fs/msdos/fat.c b/fs/msdos/fat.c index 651e58b24461..0e4526599aa5 100644 --- a/fs/msdos/fat.c +++ b/fs/msdos/fat.c @@ -10,6 +10,7 @@ #include #include +#include "msbuffer.h" static struct fat_cache *fat_cache,cache[FAT_CACHE]; @@ -28,16 +29,16 @@ int fat_access(struct super_block *sb,int nr,int new_value) first = nr*3/2; last = first+1; } - if (!(bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >> - SECTOR_BITS)))) { + if (!(bh = bread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >> + SECTOR_BITS),SECTOR_SIZE))) { printk("bread in fat_access failed\n"); return 0; } if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) bh2 = bh; else { - if (!(bh2 = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last - >> SECTOR_BITS)))) { + if (!(bh2 = bread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last + >> SECTOR_BITS),SECTOR_SIZE))) { brelse(bh); printk("bread in fat_access failed\n"); return 0; @@ -74,16 +75,16 @@ int fat_access(struct super_block *sb,int nr,int new_value) } mark_buffer_dirty(bh, 1); for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) { - if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)-> + if (!(c_bh = bread(sb->s_dev,MSDOS_SB(sb)-> fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)-> - fat_length*copy))) break; + fat_length*copy,SECTOR_SIZE))) break; memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE); mark_buffer_dirty(c_bh, 1); if (bh != bh2) { - if (!(c_bh2 = msdos_sread(sb->s_dev, + if (!(c_bh2 = bread(sb->s_dev, MSDOS_SB(sb)->fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->fat_length*copy - +1))) { + +1,SECTOR_SIZE))) { brelse(c_bh); break; } diff --git a/fs/msdos/file.c b/fs/msdos/file.c index fb41fff21d7d..0580b83e7429 100644 --- a/fs/msdos/file.c +++ b/fs/msdos/file.c @@ -18,6 +18,8 @@ #include #include +#include "msbuffer.h" + #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -55,6 +57,52 @@ struct inode_operations msdos_file_inode_operations = { NULL, /* permission */ NULL /* smap */ }; +/* #Specification: msdos / special devices / mmap + Mmapping does work because a special mmap is provide in that case. + Note that it is much less efficient than the generic_mmap normally + used since it allocate extra buffer. generic_mmap is used for + normal device (512 bytes hardware sectors). +*/ +static struct file_operations msdos_file_operations_1024 = { + NULL, /* lseek - default */ + msdos_file_read, /* read */ + msdos_file_write, /* write */ + NULL, /* readdir - bad */ + NULL, /* select - default */ + NULL, /* ioctl - default */ + msdos_mmap, /* mmap */ + NULL, /* no special open is needed */ + NULL, /* release */ + file_fsync /* fsync */ +}; + +/* #Specification: msdos / special devices / swap file + Swap file can't work on special devices with a large sector + size (1024 bytes hard sector). Those devices have a weird + MsDOS filesystem layout. Generally a single hardware sector + may contain 2 unrelated logical sector. This mean that there is + no easy way to do a mapping between disk sector of a file and virtual + memory. So swap file is difficult (not available right now) + on those devices. Off course, Ext2 does not have this problem. +*/ +struct inode_operations msdos_file_inode_operations_1024 = { + &msdos_file_operations_1024, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + msdos_truncate, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; #define MSDOS_PREFETCH 32 struct msdos_pre { @@ -72,6 +120,7 @@ static void msdos_prefetch ( struct msdos_pre *pre, int nb) /* How many must be prefetch at once */ { + struct super_block *sb = inode->i_sb; struct buffer_head *bhreq[MSDOS_PREFETCH]; /* Buffers not */ /* already read */ int nbreq=0; /* Number of buffers in bhreq */ @@ -85,12 +134,12 @@ static void msdos_prefetch ( bh = getblk(inode->i_dev,sector,SECTOR_SIZE); if (bh == NULL) break; pre->bhlist[pre->nblist++] = bh; - if (!bh->b_uptodate) bhreq[nbreq++] = bh; + if (!msdos_is_uptodate(sb,bh)) bhreq[nbreq++] = bh; }else{ break; } } - if (nbreq > 0) ll_rw_block (READ,nbreq,bhreq); + if (nbreq > 0) msdos_ll_rw_block (sb,READ,nbreq,bhreq); for (i=pre->nblist; ibhlist[i] = NULL; } @@ -103,6 +152,7 @@ int msdos_file_read( char *buf, int count) { + struct super_block *sb = inode->i_sb; char *start = buf; char *end = buf + count; int i; @@ -172,7 +222,7 @@ int msdos_file_read( } PRINTK (("file_read pos %ld nblist %d %d %d\n",filp->f_pos,pre.nblist,pre.fetched,count)); wait_on_buffer(bh); - if (!bh->b_uptodate){ + if (!msdos_is_uptodate(sb,bh)){ /* read error ? */ brelse (bh); break; @@ -216,6 +266,7 @@ int msdos_file_write( char *buf, int count) { + struct super_block *sb = inode->i_sb; int sector,offset,size,left,written; int error,carry; char *start,*to,ch; @@ -258,7 +309,7 @@ int msdos_file_write( error = -EIO; break; } - }else if (!(bh = msdos_sread(inode->i_dev,sector))) { + }else if (!(bh = bread(inode->i_dev,sector,SECTOR_SIZE))) { error = -EIO; break; } @@ -292,7 +343,7 @@ int msdos_file_write( inode->i_size = filp->f_pos; inode->i_dirt = 1; } - bh->b_uptodate = 1; + msdos_set_uptodate(sb,bh,1); mark_buffer_dirty(bh, 0); brelse(bh); } diff --git a/fs/msdos/inode.c b/fs/msdos/inode.c index d8de491bdbc1..35bee66036bc 100644 --- a/fs/msdos/inode.c +++ b/fs/msdos/inode.c @@ -11,10 +11,13 @@ #include #include #include +#include #include #include #include +#include "msbuffer.h" + #ifdef MODULE #include #include @@ -79,7 +82,8 @@ static struct super_operations msdos_sops = { static int parse_options(char *options,char *check,char *conversion,uid_t *uid, - gid_t *gid,int *umask,int *debug,int *fat,int *quiet) + gid_t *gid,int *umask,int *debug,int *fat,int *quiet, + int *blksize) { char *this_char,*value; @@ -145,6 +149,14 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid, if (value) return 0; *quiet = 1; } + else if (!strcmp(this_char,"blocksize")) { + *blksize = simple_strtoul(value,&value,0); + if (*value) + return 0; + if (*blksize != 512 && *blksize != 1024){ + printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n"); + } + } else return 0; } return 1; @@ -153,7 +165,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid, /* Read the super block of an MS-DOS FS. */ -struct super_block *msdos_read_super(struct super_block *s,void *data, +struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent) { struct buffer_head *bh; @@ -164,28 +176,34 @@ struct super_block *msdos_read_super(struct super_block *s,void *data, uid_t uid; gid_t gid; int umask; - + int blksize = 512; + if (hardsect_size[MAJOR(sb->s_dev)] != NULL){ + blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]; + if (blksize != 512){ + printk ("MSDOS: Hardware sector size is %d\n",blksize); + } + } if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask, - &debug,&fat,&quiet)) { - s->s_dev = 0; + &debug,&fat,&quiet,&blksize) + || (blksize != 512 && blksize != 1024)) { + sb->s_dev = 0; return NULL; } cache_init(); - lock_super(s); - set_blocksize(s->s_dev, SECTOR_SIZE); - bh = bread(s->s_dev, 0, SECTOR_SIZE); - unlock_super(s); - if (bh == NULL) { - s->s_dev = 0; + lock_super(sb); + /* The first read is always 1024 bytes */ + sb->s_blocksize = 1024; + set_blocksize(sb->s_dev, 1024); + bh = bread(sb->s_dev, 0, 1024); + unlock_super(sb); + if (bh == NULL || !msdos_is_uptodate(sb,bh)) { + brelse (bh); + sb->s_dev = 0; printk("MSDOS bread failed\n"); return NULL; } b = (struct msdos_boot_sector *) bh->b_data; - s->s_blocksize = 512; /* Using this small block size solve the */ - /* the misfit with buffer cache and cluster */ - /* because cluster (DOS) are often aligned */ - /* on odd sector */ - s->s_blocksize_bits = 9; /* we cannot handle anything else yet */ + set_blocksize(sb->s_dev, blksize); /* * The DOS3 partition size limit is *not* 32M as many people think. * Instead, it is 64K sectors (with the usual sector size being @@ -206,75 +224,85 @@ struct super_block *msdos_read_super(struct super_block *s,void *data, logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size); sector_mult = logical_sector_size >> SECTOR_BITS; - MSDOS_SB(s)->cluster_size = b->cluster_size*sector_mult; - MSDOS_SB(s)->fats = b->fats; - MSDOS_SB(s)->fat_start = CF_LE_W(b->reserved)*sector_mult; - MSDOS_SB(s)->fat_length = CF_LE_W(b->fat_length)*sector_mult; - MSDOS_SB(s)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W( + MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult; + MSDOS_SB(sb)->fats = b->fats; + MSDOS_SB(sb)->fat_start = CF_LE_W(b->reserved)*sector_mult; + MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult; + MSDOS_SB(sb)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W( b->fat_length))*sector_mult; - MSDOS_SB(s)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries + MSDOS_SB(sb)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries )); - MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+ROUND_TO_MULTIPLE(( - MSDOS_SB(s)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, + MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE(( + MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, sector_mult); data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ? CF_LE_W(*((unsigned short *) &b->sectors)) : - CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(s)->data_start; + CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(sb)->data_start; error = !b->cluster_size || !sector_mult; if (!error) { - MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/ + MSDOS_SB(sb)->clusters = b->cluster_size ? data_sectors/ b->cluster_size/sector_mult : 0; - MSDOS_SB(s)->fat_bits = fat ? fat : MSDOS_SB(s)->clusters > + MSDOS_SB(sb)->fat_bits = fat ? fat : MSDOS_SB(sb)->clusters > MSDOS_FAT12 ? 16 : 12; - error = !MSDOS_SB(s)->fats || (MSDOS_SB(s)->dir_entries & - (MSDOS_DPS-1)) || MSDOS_SB(s)->clusters+2 > MSDOS_SB(s)-> - fat_length*SECTOR_SIZE*8/MSDOS_SB(s)->fat_bits || + error = !MSDOS_SB(sb)->fats || (MSDOS_SB(sb)->dir_entries & + (MSDOS_DPS-1)) || MSDOS_SB(sb)->clusters+2 > MSDOS_SB(sb)-> + fat_length*SECTOR_SIZE*8/MSDOS_SB(sb)->fat_bits || (logical_sector_size & (SECTOR_SIZE-1)) || !b->secs_track || !b->heads; } brelse(bh); + /* + This must be done after the brelse because the bh is a dummy + allocated by msdos_bread (see buffer.c) + */ + sb->s_blocksize = blksize; /* Using this small block size solve the */ + /* the misfit with buffer cache and cluster */ + /* because cluster (DOS) are often aligned */ + /* on odd sector */ + sb->s_blocksize_bits = blksize == 512 ? 9 : 10; 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," - "uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(s)->fat_bits,check, - conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(s)) ? + "uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(sb)->fat_bits,check, + conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(sb)) ? ",bmap" : ""); printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d," - "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(s)->cluster_size, - MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,MSDOS_SB(s)-> - fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries, - MSDOS_SB(s)->data_start,CF_LE_W(*(unsigned short *) &b-> + "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(sb)->cluster_size, + MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)-> + fat_length,MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries, + MSDOS_SB(sb)->data_start,CF_LE_W(*(unsigned short *) &b-> sectors),b->total_sect,logical_sector_size); + printk ("Transaction block size = %d\n",blksize); } if (error) { if (!silent) printk("VFS: Can't find a valid MSDOS filesystem on dev 0x%04x.\n", - s->s_dev); - s->s_dev = 0; + sb->s_dev); + sb->s_dev = 0; return NULL; } - s->s_magic = MSDOS_SUPER_MAGIC; - MSDOS_SB(s)->name_check = check; - MSDOS_SB(s)->conversion = conversion; + sb->s_magic = MSDOS_SUPER_MAGIC; + MSDOS_SB(sb)->name_check = check; + MSDOS_SB(sb)->conversion = conversion; /* set up enough so that it can read an inode */ - s->s_op = &msdos_sops; - MSDOS_SB(s)->fs_uid = uid; - MSDOS_SB(s)->fs_gid = gid; - MSDOS_SB(s)->fs_umask = umask; - MSDOS_SB(s)->quiet = quiet; - MSDOS_SB(s)->free_clusters = -1; /* don't know yet */ - MSDOS_SB(s)->fat_wait = NULL; - MSDOS_SB(s)->fat_lock = 0; - MSDOS_SB(s)->prev_free = 0; - if (!(s->s_mounted = iget(s,MSDOS_ROOT_INO))) { - s->s_dev = 0; + sb->s_op = &msdos_sops; + MSDOS_SB(sb)->fs_uid = uid; + MSDOS_SB(sb)->fs_gid = gid; + MSDOS_SB(sb)->fs_umask = umask; + MSDOS_SB(sb)->quiet = quiet; + MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */ + MSDOS_SB(sb)->fat_wait = NULL; + MSDOS_SB(sb)->fat_lock = 0; + MSDOS_SB(sb)->prev_free = 0; + if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) { + sb->s_dev = 0; printk("get root inode failed\n"); return NULL; } #ifdef MODULE MOD_INC_USE_COUNT; #endif - return s; + return sb; } @@ -321,6 +349,7 @@ int msdos_bmap(struct inode *inode,int block) void msdos_read_inode(struct inode *inode) { + struct super_block *sb = inode->i_sb; struct buffer_head *bh; struct msdos_dir_entry *raw_entry; int nr; @@ -384,7 +413,9 @@ void msdos_read_inode(struct inode *inode) inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(IS_NOEXEC(inode) ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFREG; - inode->i_op = &msdos_file_inode_operations; /* Now can always bmap */ + inode->i_op = sb->s_blocksize == 1024 + ? &msdos_file_inode_operations_1024 + : &msdos_file_inode_operations; MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); inode->i_nlink = 1; inode->i_size = CF_LE_L(raw_entry->size); @@ -404,6 +435,7 @@ void msdos_read_inode(struct inode *inode) void msdos_write_inode(struct inode *inode) { + struct super_block *sb = inode->i_sb; struct buffer_head *bh; struct msdos_dir_entry *raw_entry; diff --git a/fs/msdos/misc.c b/fs/msdos/misc.c index 630198afa285..79ccbe23bccd 100644 --- a/fs/msdos/misc.c +++ b/fs/msdos/misc.c @@ -12,6 +12,7 @@ #include #include +#include "msbuffer.h" #define PRINTK(x) /* Well-known binary file extensions */ @@ -111,6 +112,7 @@ void unlock_fat(struct super_block *sb) int msdos_add_cluster(struct inode *inode) { + struct super_block *sb = inode->i_sb; int count,nr,limit,last,current,sector,last_sector; struct buffer_head *bh; int cluster_size = MSDOS_SB(inode->i_sb)->cluster_size; @@ -173,7 +175,7 @@ if (last) printk("next set to %d\n",fat_access(inode->i_sb,last,-1)); printk("getblk failed\n"); else { memset(bh->b_data,0,SECTOR_SIZE); - bh->b_uptodate = 1; + msdos_set_uptodate(sb,bh,1); mark_buffer_dirty(bh, 1); brelse(bh); } @@ -255,6 +257,7 @@ void date_unix2dos(int unix_date,unsigned short *time, int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, struct msdos_dir_entry **de) { + struct super_block *sb = dir->i_sb; int sector,offset; while (1) { @@ -269,7 +272,7 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, if (*bh) brelse(*bh); PRINTK (("get_entry sector apres brelse\n")); - if (!(*bh = msdos_sread(dir->i_dev,sector))) { + if (!(*bh = bread(dir->i_dev,sector,SECTOR_SIZE))) { printk("Directory sread (sector %d) failed\n",sector); continue; } @@ -343,7 +346,7 @@ static int raw_scan_sector(struct super_block *sb,int sector,char *name, struct inode *inode; int entry,start,done; - if (!(bh = msdos_sread(sb->s_dev,sector))) return -EIO; + if (!(bh = bread(sb->s_dev,sector,SECTOR_SIZE))) return -EIO; data = (struct msdos_dir_entry *) bh->b_data; for (entry = 0; entry < MSDOS_DPS; entry++) { if (name) RSS_NAME diff --git a/fs/msdos/mmap.c b/fs/msdos/mmap.c new file mode 100644 index 000000000000..da188a39cfc2 --- /dev/null +++ b/fs/msdos/mmap.c @@ -0,0 +1,107 @@ +/* + * fs/msdos/mmap.c + * + * Written by Jacques Gelinas (jacques@solucorp.qc.ca) + * Inspired by fs/nfs/mmap.c (Jaon Tombs 15 Aug 1993) + * + * msdos mmap handling + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Fill in the supplied page for mmap + */ +static unsigned long msdos_file_mmap_nopage( + struct vm_area_struct * area, + unsigned long address, + unsigned long page, + int error_code) +{ + struct inode * inode = area->vm_inode; + unsigned int clear; + int pos; + long gap; /* distance from eof to pos */ + + address &= PAGE_MASK; + pos = address - area->vm_start + area->vm_offset; + + clear = 0; + gap = inode->i_size - pos; + if (gap <= 0){ + /* mmaping beyond end of file */ + clear = PAGE_SIZE; + }else{ + int cur_read; + int need_read; + struct file filp; + if (gap < PAGE_SIZE){ + clear = PAGE_SIZE - gap; + } + filp.f_reada = 0; + filp.f_pos = pos; + need_read = PAGE_SIZE - clear; + { + unsigned long cur_fs = get_fs(); + set_fs (KERNEL_DS); + cur_read = msdos_file_read (inode,&filp,(char*)page + ,need_read); + set_fs (cur_fs); + } + if (cur_read != need_read){ + printk ("MSDOS: Error while reading an mmap file %d <> %d\n" + ,cur_read,need_read); + } + } + if (clear > 0){ + memset ((char*)page+PAGE_SIZE-clear,0,clear); + } + return page; +} + +struct vm_operations_struct msdos_file_mmap = { + NULL, /* open */ + NULL, /* close */ + NULL, /* unmap */ + NULL, /* protect */ + NULL, /* sync */ + NULL, /* advise */ + msdos_file_mmap_nopage, /* nopage */ + NULL, /* wppage */ + NULL, /* swapout */ + NULL, /* swapin */ +}; + +/* + * This is used for a general mmap of an msdos file + * Returns 0 if ok, or a negative error code if not. + */ +int msdos_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) +{ + if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported now */ + return -EINVAL; + if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) + return -EINVAL; + if (!inode->i_sb || !S_ISREG(inode->i_mode)) + return -EACCES; + if (!IS_RDONLY(inode)) { + inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + } + + vma->vm_inode = inode; + inode->i_count++; + vma->vm_ops = &msdos_file_mmap; + return 0; +} + diff --git a/fs/msdos/msbuffer.h b/fs/msdos/msbuffer.h new file mode 100644 index 000000000000..50d62d7fd858 --- /dev/null +++ b/fs/msdos/msbuffer.h @@ -0,0 +1,22 @@ +/* buffer.c 13/12/94 20.19.10 */ +struct buffer_head *msdos_bread (struct super_block *sb, int block); +struct buffer_head *msdos_getblk (struct super_block *sb, int block); +void msdos_brelse (struct super_block *sb, struct buffer_head *bh); +void msdos_mark_buffer_dirty (struct super_block *sb, + struct buffer_head *bh, + int dirty_val); +void msdos_set_uptodate (struct super_block *sb, + struct buffer_head *bh, + int val); +int msdos_is_uptodate (struct super_block *sb, struct buffer_head *bh); +void msdos_ll_rw_block (struct super_block *sb, int opr, + int nbreq, struct buffer_head *bh[32]); + +/* These macros exist to avoid modifying all the code */ +/* They should be removed one day I guess */ + +#define brelse(b) msdos_brelse(sb,b) +#define bread(d,b,s) msdos_bread(sb,b) +#define getblk(d,b,s) msdos_getblk(sb,b) +#define mark_buffer_dirty(b,v) msdos_mark_buffer_dirty(sb,b,v) + diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index ad3b9c8bc528..0ce78f1e4fd9 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -13,6 +13,8 @@ #include #include +#include "msbuffer.h" + #define PRINTK(x) /* MS-DOS "device special files" */ @@ -107,6 +109,7 @@ static int msdos_find(struct inode *dir,const char *name,int len, int msdos_lookup(struct inode *dir,const char *name,int len, struct inode **result) { + struct super_block *sb = dir->i_sb; int ino,res; struct msdos_dir_entry *de; struct buffer_head *bh; @@ -173,6 +176,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len, static int msdos_create_entry(struct inode *dir,char *name,int is_dir, struct inode **result) { + struct super_block *sb = dir->i_sb; struct buffer_head *bh; struct msdos_dir_entry *de; int res,ino; @@ -209,6 +213,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir, int msdos_create(struct inode *dir,const char *name,int len,int mode, struct inode **result) { + struct super_block *sb = dir->i_sb; struct buffer_head *bh; struct msdos_dir_entry *de; char msdos_name[MSDOS_NAME]; @@ -256,6 +261,7 @@ static void dump_fat(struct super_block *sb,int start) int msdos_mkdir(struct inode *dir,const char *name,int len,int mode) { + struct super_block *sb = dir->i_sb; struct buffer_head *bh; struct msdos_dir_entry *de; struct inode *inode,*dot; @@ -313,6 +319,7 @@ mkdir_error: static int msdos_empty(struct inode *dir) { + struct super_block *sb = dir->i_sb; loff_t pos; struct buffer_head *bh; struct msdos_dir_entry *de; @@ -338,6 +345,7 @@ static int msdos_empty(struct inode *dir) int msdos_rmdir(struct inode *dir,const char *name,int len) { + struct super_block *sb = dir->i_sb; int res,ino; struct buffer_head *bh; struct msdos_dir_entry *de; @@ -379,6 +387,7 @@ static int msdos_unlinkx( int len, int nospc) /* Flag special file ? */ { + struct super_block *sb = dir->i_sb; int res,ino; struct buffer_head *bh; struct msdos_dir_entry *de; @@ -425,6 +434,7 @@ static int rename_same_dir(struct inode *old_dir,char *old_name, struct inode *new_dir,char *new_name,struct buffer_head *old_bh, struct msdos_dir_entry *old_de,int old_ino) { + struct super_block *sb = old_dir->i_sb; struct buffer_head *new_bh; struct msdos_dir_entry *new_de; struct inode *new_inode,*old_inode; @@ -476,6 +486,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name, struct inode *new_dir,char *new_name,struct buffer_head *old_bh, struct msdos_dir_entry *old_de,int old_ino) { + struct super_block *sb = old_dir->i_sb; struct buffer_head *new_bh,*free_bh,*dotdot_bh; struct msdos_dir_entry *new_de,*free_de,*dotdot_de; struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk; @@ -594,6 +605,7 @@ rename_done: int msdos_rename(struct inode *old_dir,const char *old_name,int old_len, struct inode *new_dir,const char *new_name,int new_len) { + struct super_block *sb = old_dir->i_sb; char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME]; struct buffer_head *old_bh; struct msdos_dir_entry *old_de; diff --git a/fs/proc/array.c b/fs/proc/array.c index 8458d40bc927..4499bbd0dc4d 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -243,17 +243,16 @@ static int get_version(char * buffer) static int get_cpuinfo(char * buffer) { - /* to conserve memory, we define the strins yes and no in - advance */ - char *yes="yes"; - char *no="no"; char *model[2][9]={{"DX","SX","DX/2","4","SX/2","6", "7","DX/4"}, {"Pentium 60/66","Pentium 90/100","3", "4","5","6","7","8"}}; + char mask[2]; + mask[0] = x86_mask+'@'; + mask[1] = '\0'; return sprintf(buffer,"cpu\t\t: %c86\n" "model\t\t: %s\n" - "mask\t\t: %c\n" + "mask\t\t: %s\n" "vid\t\t: %s\n" "fdiv_bug\t: %s\n" "math\t\t: %s\n" @@ -269,20 +268,20 @@ static int get_cpuinfo(char * buffer) "CMPXCHGB8B\t: %s\n", x86+'0', x86_model ? model[x86-4][x86_model-1] : "Unknown", - x86_mask+'@', + x86_mask ? mask : "Unknown", x86_vendor_id, - fdiv_bug ? yes : no, - hard_math ? yes : no, - hlt_works_ok ? yes : no, - wp_works_ok ? yes : no, - x86_capability & 1 ? yes : no, - x86_capability & 2 ? yes : no, - x86_capability & 4 ? yes : no, - x86_capability & 8 ? yes : no, - x86_capability & 16 ? yes : no, - x86_capability & 32 ? yes : no, - x86_capability & 128 ? yes : no, - x86_capability & 256 ? yes : no + fdiv_bug ? "yes" : "no", + hard_math ? "yes" : "no", + hlt_works_ok ? "yes" : "no", + wp_works_ok ? "yes" : "no", + x86_capability & 1 ? "yes" : "no", + x86_capability & 2 ? "yes" : "no", + x86_capability & 4 ? "yes" : "no", + x86_capability & 8 ? "yes" : "no", + x86_capability & 16 ? "yes" : "no", + x86_capability & 32 ? "yes" : "no", + x86_capability & 128 ? "yes" : "no", + x86_capability & 256 ? "yes" : "no" ); } @@ -431,7 +430,7 @@ static int get_stat(int pid, char * buffer) else tty_pgrp = -1; return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ -%lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %u %lu %lu %lu %lu %lu %lu \ +%lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \ %lu %lu %lu %lu\n", pid, (*p)->comm, diff --git a/fs/umsdos/file.c b/fs/umsdos/file.c index d292ea3c23ec..224d976ba494 100644 --- a/fs/umsdos/file.c +++ b/fs/umsdos/file.c @@ -58,16 +58,8 @@ static void UMSDOS_truncate(struct inode *inode) inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_dirt = 1; } -/* - See inode.c - - Some entry point are filled dynamically with function pointers - from the msdos file_operations and file_inode_operations. - - The idea is to have the code as independent as possible from - the msdos file system. -*/ +/* Function for normal file system (512 bytes hardware sector size) */ struct file_operations umsdos_file_operations = { NULL, /* lseek - default */ UMSDOS_file_read, /* read */ @@ -94,10 +86,41 @@ struct inode_operations umsdos_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* bmap */ + msdos_bmap, /* bmap */ UMSDOS_truncate,/* truncate */ NULL, /* permission */ msdos_smap /* smap */ }; +/* For other with larger and unaligned file system */ +struct file_operations umsdos_file_operations_no_bmap = { + NULL, /* lseek - default */ + UMSDOS_file_read, /* read */ + UMSDOS_file_write, /* write */ + NULL, /* readdir - bad */ + NULL, /* select - default */ + NULL, /* ioctl - default */ + msdos_mmap, /* mmap */ + NULL, /* no special open is needed */ + NULL, /* release */ + file_fsync /* fsync */ +}; +struct inode_operations umsdos_file_inode_operations_no_bmap = { + &umsdos_file_operations_no_bmap, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + UMSDOS_truncate,/* truncate */ + NULL, /* permission */ + NULL, /* smap */ +}; diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index aa01c3d58e81..d639b8f6e3e4 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -45,6 +45,9 @@ void UMSDOS_put_inode(struct inode *inode) PRINTK (("put inode %x owner %x pos %d dir %x\n",inode ,inode->u.umsdos_i.i_emd_owner,inode->u.umsdos_i.pos ,inode->u.umsdos_i.i_emd_dir)); + if (inode != NULL && inode == pseudo_root){ + printk ("Umsdos: Oops releasing pseudo_root. Notify jacques@solucorp.qc.ca\n"); + } msdos_put_inode(inode); } @@ -152,18 +155,11 @@ void umsdos_patch_inode ( if (!umsdos_isinit(inode)){ inode->u.umsdos_i.i_emd_dir = 0; if (S_ISREG(inode->i_mode)){ - static char is_init = 0; - if (!is_init){ - /* - I don't want to change the msdos file system code - so I get the address of some subroutine dynamically - once. - */ - umsdos_file_inode_operations.bmap = inode->i_op->bmap; + if (inode->i_op->bmap != NULL){ inode->i_op = &umsdos_file_inode_operations; - is_init = 1; + }else{ + inode->i_op = &umsdos_file_inode_operations_no_bmap; } - inode->i_op = &umsdos_file_inode_operations; }else if (S_ISDIR(inode->i_mode)){ if (dir != NULL){ umsdos_setup_dir_inode(inode); @@ -409,7 +405,7 @@ struct super_block *UMSDOS_read_super( msdos directory, with all limitation of msdos. */ struct super_block *sb = msdos_read_super(s,data,silent); - printk ("UMSDOS Alpha 0.5a (compatibility level %d.%d, fast msdos)\n" + printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n" ,UMSDOS_VERSION,UMSDOS_RELEASE); if (sb != NULL){ sb->s_op = &umsdos_sops; diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c index 1f59447e94b1..0fe3b5464423 100644 --- a/fs/umsdos/mangle.c +++ b/fs/umsdos/mangle.c @@ -222,13 +222,15 @@ int umsdos_parse ( with a special character as the first character of the extension will be mangled. This solve the following problem: - + + # touch FILE # FILE is invalid for DOS, so mangling is applied # file.{_1 is created in the DOS directory touch file.{_1 # To UMSDOS file point to a single DOS entry. # So file.{_1 has to be mangled. + # */ static char special[]={ SPECIAL_MANGLING,'\0' @@ -270,7 +272,9 @@ int umsdos_parse ( Control character are converted to #. Space are converted to #. The following character are also converted to #. + # " * + , / : ; < = > ? [ \ ] | ~ + # Sometime, the problem is not in MsDOS itself but in command.com. @@ -316,10 +320,12 @@ int umsdos_parse ( Here is the list of DOS pseudo devices: + # "prn","con","aux","nul", "lpt1","lpt2","lpt3","lpt4", "com1","com2","com3","com4", "clock$" + # and some standard ones for common DOS programs diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index 567039e144f7..2a59bf813a8f 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -483,6 +483,7 @@ int UMSDOS_link ( Given a file /foo/file + # ln /foo/file /tmp/file2 become internally @@ -490,6 +491,7 @@ int UMSDOS_link ( mv /foo/file /foo/-LINK1 ln -s /foo/-LINK1 /foo/file ln -s /foo/-LINK1 /tmp/file2 + # Using this strategy, we can operate on /foo/file or /foo/file2. We can remove one and keep the other, like a normal Unix hard link. @@ -502,6 +504,7 @@ int UMSDOS_link ( The strategy for hard link introduces a side effect that may or may not be acceptable. Here is the sequence + # mkdir subdir1 touch subdir1/file mkdir subdir2 @@ -509,6 +512,7 @@ int UMSDOS_link ( rm subdir1/file rmdir subdir1 rmdir: subdir1: Directory not empty + # This happen because there is an invisible file (--link) in subdir1 which is referenced by subdir2/file. @@ -519,12 +523,14 @@ int UMSDOS_link ( Another weakness of hard link come from the fact that it is based on hidden symbolic links. Here is an example. + # mkdir /subdir1 touch /subdir1/file mkdir /subdir2 ln /subdir1/file subdir2/file mv /subdir1 subdir3 ls -l /subdir2/file + # Since /subdir2/file is a hidden symbolic link to /subdir1/..hlinkNNN, accessing it will fail since @@ -765,6 +771,7 @@ int UMSDOS_rmdir( but you rapidly get iput() all around. Here is an exemple of what I am trying to avoid. + # if (a){ ... if(b){ @@ -783,10 +790,12 @@ int UMSDOS_rmdir( } // Was iput finally done ? return status; + # Here is the style I am using. Still sometime I do the first when things are very simple (or very complicated :-( ) + # if (a){ if (b){ ... @@ -797,6 +806,7 @@ int UMSDOS_rmdir( ... } return status; + # Again, while this help clarifying the code, I often get a lot of iput(), unlike the first style, where I can place few @@ -812,6 +822,7 @@ int UMSDOS_rmdir( where an iput() is done, the inode is simply nulled, disabling the last one. + # if (a){ if (b){ ... @@ -824,6 +835,7 @@ int UMSDOS_rmdir( } iput (dir); return status; + # Note that the umsdos_lockcreate() and umsdos_unlockcreate() function pair goes against this practice of "forgetting" the inode as soon diff --git a/include/asm-alpha/bugs.h b/include/asm-alpha/bugs.h new file mode 100644 index 000000000000..78030d1c7e7e --- /dev/null +++ b/include/asm-alpha/bugs.h @@ -0,0 +1,20 @@ +/* + * include/asm-alpha/bugs.h + * + * Copyright (C) 1994 Linus Torvalds + */ + +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Needs: + * void check_bugs(void); + */ + +/* + * I don't know of any alpha bugs yet.. Nice chip + */ + +static void check_bugs(void) +{ +} diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h new file mode 100644 index 000000000000..b9d29d90ed56 --- /dev/null +++ b/include/asm-alpha/processor.h @@ -0,0 +1,33 @@ +/* + * include/asm-i386/processor.h + * + * Copyright (C) 1994 Linus Torvalds + */ + +#ifndef __ASM_I386_PROCESSOR_H +#define __ASM_I386_PROCESSOR_H + +/* + * Bus types + */ +extern int EISA_bus; +#define MCA_bus 0 + +struct thread_struct { + unsigned long ksp; + unsigned long usp; + unsigned long ptbr; + unsigned int pcc; + unsigned int asn; + unsigned long unique; + unsigned long flags; + unsigned long res1, res2; +}; + +#define INIT_TSS { \ + 0, 0, 0, \ + 0, 0, 0, \ + 0, 0, 0, \ +} + +#endif /* __ASM_I386_PROCESSOR_H */ diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index 54a83bdb3541..a83952d2591b 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -62,6 +62,10 @@ #define PAL_rtsys 61 #define PAL_rti 63 +#define halt() __asm__ __volatile__(".long 0"); +#define move_to_user_mode() halt() +#define switch_to(x) halt() + #ifndef mb #define mb() __asm__ __volatile__("mb": : :"memory") #endif @@ -77,4 +81,44 @@ __asm__ __volatile__( \ : "$0", "$1", "$16", "$22", "$23", "$24", "$25"); \ __old_ipl; }) +#define cli() swpipl(7) +#define sti() swpipl(0) +#define save_flags(flags) do { flags = swpipl(7); } while (0) +#define restore_flags(flags) swpipl(flags) + +extern inline unsigned long xchg_u32(int * m, unsigned long val) +{ + unsigned long dummy, dummy2; + + __asm__ __volatile__( + "\n1:\t" + "ldl_l %0,%1\n\t" + "bis %2,%2,%3\n\t" + "stl_c %3,%1\n\t" + "beq %3,1b\n" + : "=r" (val), "=m" (*m), "=r" (dummy), "=r" (dummy2) + : "1" (*m), "2" (val)); + return val; +} + +extern inline unsigned long xchg_u64(long * m, unsigned long val) +{ + unsigned long dummy, dummy2; + + __asm__ __volatile__( + "\n1:\t" + "ldq_l %0,%1\n\t" + "bis %2,%2,%3\n\t" + "stq_c %3,%1\n\t" + "beq %3,1b\n" + : "=r" (val), "=m" (*m), "=r" (dummy), "=r" (dummy2) + : "1" (*m), "2" (val)); + return val; +} + +extern inline void * xchg_ptr(void *m, void *val) +{ + return (void *) xchg_u64((long *) m, (unsigned long) val); +} + #endif diff --git a/include/asm-alpha/types.h b/include/asm-alpha/types.h index 602747914ea0..6a4098ab1aee 100644 --- a/include/asm-alpha/types.h +++ b/include/asm-alpha/types.h @@ -21,13 +21,13 @@ typedef long ptrdiff_t; * header files exported to user space */ -typedef signed char __s8; +typedef __signed__ char __s8; typedef unsigned char __u8; -typedef signed short __s16; +typedef __signed__ short __s16; typedef unsigned short __u16; -typedef signed int __s32; +typedef __signed__ int __s32; typedef unsigned int __u32; /* @@ -35,14 +35,14 @@ typedef unsigned int __u32; */ #if ((~0UL) == 0xffffffff) -#ifndef __STRICT_ANSI__ -typedef signed long long __s64; +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; typedef unsigned long long __u64; #endif #else -typedef signed long __s64; +typedef __signed__ long __s64; typedef unsigned long __u64; #endif diff --git a/include/asm-generic/string.h b/include/asm-generic/string.h deleted file mode 100644 index 03fd6321f980..000000000000 --- a/include/asm-generic/string.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * include/asm-generic/string.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_GENERIC_STRING_H_ -#define _ASM_GENERIC_STRING_H_ - -/* - * Portable string functions. These are not complete: - * memcpy() and memmove() are still missing. - */ - -#ifdef __USE_PORTABLE_strcpy -extern inline char * strcpy(char * dest,const char *src) -{ - char *xdest = dest; - - while(*dest++ = *src++); - - return xdest; -} -#endif - -#ifdef __USE_PORTABLE_strncpy -extern inline char * strncpy(char * dest,const char *src,size_t count) -{ - char *xdest = dest; - - while((*dest++ = *src++) && --count); - - return dest; -} -#endif - -#ifdef __USE_PORTABLE_strcat -extern inline char * strcat(char * dest, const char * src) -{ - char *tmp = dest; - - while (*dest) - dest++; - while ((*dest++ = *src++)) - ; - - return tmp; -} -#endif - -#ifdef __USE_PORTABLE_strncat -extern inline char * strncat(char *dest, const char *src, size_t count) -{ - char *tmp = dest; - - if (count) { - while (*dest) - dest++; - while ((*dest++ = *src++)) { - if (--count == 0) - break; - } - } - - return tmp; -} -#endif - -#ifdef __USE_PORTABLE_strcmp -extern int strcmp(const char * cs,const char * ct) -{ - register char __res; - - while(1) { - if(__res = *cs - *ct++ && *cs++) - break; - } - - return __res; -} -#endif - -#ifdef __USE_PORTABLE_strncmp -extern inline int strncmp(const char * cs,const char * ct,size_t count) -{ - register char __res; - - while(count) { - if(__res = *cs - *ct++ || !*cs++) - break; - count--; - } - - return __res; -} -#endif - -#ifdef __USE_PORTABLE_strchr -extern inline char * strchr(const char * s,char c) -{ - const char ch = c; - - for(; *s != ch; ++s) - if (*s == '\0') - return( NULL ); - return( (char *) s); -} -#endif - -#ifdef __USE_PORTABLE_strlen -extern inline size_t strlen(const char * s) -{ - const char *sc; - for (sc = s; *sc != '\0'; ++sc) ; - return(sc - s); -} -#endif - -#ifdef __USE_PORTABLE_strspn -extern inline size_t strspn(const char *s, const char *accept) -{ - const char *p; - const char *a; - size_t count = 0; - - for (p = s; *p != '\0'; ++p) - { - for (a = accept; *a != '\0'; ++a) - if (*p == *a) - break; - if (*a == '\0') - return count; - else - ++count; - } - - return count; -} -#endif - -#ifdef __USE_PORTABLE_strpbrk -extern inline char * strpbrk(const char * cs,const char * ct) -{ - const char *sc1,*sc2; - - for( sc1 = cs; *sc1 != '\0'; ++sc1) - for( sc2 = ct; *sc2 != '\0'; ++sc2) - if (*sc1 == *sc2) - return((char *) sc1); - return( NULL ); -} -#endif - -#ifdef __USE_PORTABLE_strtok -extern inline char * strtok(char * s,const char * ct) -{ - char *sbegin, *send; - static char *ssave = NULL; - - sbegin = s ? s : ssave; - if (!sbegin) { - return NULL; - } - sbegin += strspn(sbegin,ct); - if (*sbegin == '\0') { - ssave = NULL; - return( NULL ); - } - send = strpbrk( sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - ssave = send; - return (sbegin); -} -#endif - -#ifdef __USE_PORTABLE_memset -extern inline void * memset(void * s,char c,size_t count) -{ - void *xs = s; - - while(n--) - *s++ = c; - - return xs; -} -#endif - -#ifdef __USE_PORTABLE_memcpy -#error "Portable memcpy() not implemented yet" -#endif - -#ifdef __USE_PORTABLE_memmove -#error "Portable memmove() not implemented yet" -#endif - -#ifdef __USE_PORTABLE_memcmp -extern inline int memcmp(const void * cs,const void * ct,size_t count) -{ - const unsigned char *su1, *su2; - - for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) - if (*su1 != *su2) - return((*su1 < *su2) ? -1 : +1); - return(0); -} -#endif - -#endif /* _ASM_GENERIC_STRING_H_ */ diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h new file mode 100644 index 000000000000..f0382690dcc3 --- /dev/null +++ b/include/asm-i386/bugs.h @@ -0,0 +1,116 @@ +/* + * include/asm-i386/bugs.h + * + * Copyright (C) 1994 Linus Torvalds + */ + +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Needs: + * void check_bugs(void); + */ + +#define CONFIG_BUGi386 + +static void no_halt(char *s, int *ints) +{ + hlt_works_ok = 0; +} + +static void no_387(char *s, int *ints) +{ + hard_math = 0; + __asm__("movl %%cr0,%%eax\n\t" + "orl $0xE,%%eax\n\t" + "movl %%eax,%%cr0\n\t" : : : "ax"); +} + +static char fpu_error = 0; + +static void copro_timeout(void) +{ + fpu_error = 1; + timer_table[COPRO_TIMER].expires = jiffies+100; + timer_active |= 1<debugreg[register]) \ + :"dx"); + + +/* + * switch_to(n) should switch tasks to task nr n, first + * checking that n isn't the current task, in which case it does nothing. + * This also clears the TS-flag if the task we switched to has used + * the math co-processor latest. + * + * It also reloads the debug regs if necessary.. + */ +#define switch_to(tsk) do { \ +__asm__("cli\n\t" \ + "xchgl %%ecx,_current\n\t" \ + "ljmp %0\n\t" \ + "sti\n\t" \ + "cmpl %%ecx,_last_task_used_math\n\t" \ + "jne 1f\n\t" \ + "clts\n" \ + "1:" \ + : /* no output */ \ + :"m" (*(((char *)&tsk->tss.tr)-4)), \ + "c" (tsk) \ + :"cx"); \ + /* Now maybe reload the debug registers */ \ + if(current->debugreg[7]){ \ + loaddebug(0); \ + loaddebug(1); \ + loaddebug(2); \ + loaddebug(3); \ + loaddebug(6); \ + } \ +} while (0) + +#define _set_base(addr,base) \ +__asm__("movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %%dl,%1\n\t" \ + "movb %%dh,%2" \ + : /* no output */ \ + :"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7)), \ + "d" (base) \ + :"dx") + +#define _set_limit(addr,limit) \ +__asm__("movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %1,%%dh\n\t" \ + "andb $0xf0,%%dh\n\t" \ + "orb %%dh,%%dl\n\t" \ + "movb %%dl,%1" \ + : /* no output */ \ + :"m" (*(addr)), \ + "m" (*((addr)+6)), \ + "d" (limit) \ + :"dx") + +#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base ) +#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) + +static inline unsigned long _get_base(char * addr) +{ + unsigned long __base; + __asm__("movb %3,%%dh\n\t" + "movb %2,%%dl\n\t" + "shll $16,%%edx\n\t" + "movw %1,%%dx" + :"=&d" (__base) + :"m" (*((addr)+2)), + "m" (*((addr)+4)), + "m" (*((addr)+7))); + return __base; +} + +#define get_base(ldt) _get_base( ((char *)&(ldt)) ) + +static inline unsigned long get_limit(unsigned long segment) +{ + unsigned long __limit; + __asm__("lsll %1,%0" + :"=r" (__limit):"r" (segment)); + return __limit+1; +} + #define nop() __asm__ __volatile__ ("nop") /* @@ -34,12 +153,32 @@ __asm__ __volatile__ ( \ :"ax") +extern inline unsigned long xchg_u8(char * m, unsigned long val) +{ + __asm__("xchgb %b0,%1":"=q" (val),"=m" (*m):"0" (val):"memory"); + return val; +} + +extern inline unsigned long xchg_u16(short * m, unsigned long val) +{ + __asm__("xchgw %w0,%1":"=r" (val),"=m" (*m):"0" (val):"memory"); + return val; +} + +extern inline unsigned long xchg_u32(long * m, unsigned long val) +{ + __asm__("xchgl %0,%1":"=r" (val),"=m" (*m):"0" (val):"memory"); + return val; +} + extern inline int tas(char * m) { - char res; + return xchg_u8(m,1); +} - __asm__("xchgb %0,%1":"=q" (res),"=m" (*m):"0" (0x1)); - return res; +extern inline void * xchg_ptr(void * m, void * val) +{ + return (void *) xchg_u32(m, (unsigned long) val); } #define sti() __asm__ __volatile__ ("sti": : :"memory") @@ -104,5 +243,10 @@ __asm__ __volatile__ ("movw $" #limit ",%1\n\t" \ #define set_ldt_desc(n,addr,size) \ _set_tssldt_desc(((char *) (n)),((int)(addr)),((size << 3) - 1),"0x82") +/* + * This is the ldt that every process will get unless we need + * something other than this. + */ +extern struct desc_struct default_ldt; #endif diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h index 1f26e39f5d02..ba25ec4a06af 100644 --- a/include/asm-i386/types.h +++ b/include/asm-i386/types.h @@ -30,7 +30,7 @@ typedef unsigned short __u16; typedef __signed__ long __s32; typedef unsigned long __u32; -#ifndef __STRICT_ANSI__ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef __signed__ long long __s64; typedef unsigned long long __u64; #endif diff --git a/include/asm-sparc/bugs.h b/include/asm-sparc/bugs.h new file mode 100644 index 000000000000..c3349544377f --- /dev/null +++ b/include/asm-sparc/bugs.h @@ -0,0 +1,46 @@ +/* include/asm-sparc/bugs.h: Sparc probes for various bugs. + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ + +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Needs: + * void check_bugs(void); + */ + +#define CONFIG_BUGSPARC + +#include + +extern struct promvec *romvec; +extern int tbase_needs_unmapping; /* We do the bug workaround in pagetables.c */ + +static void check_mmu() +{ + register struct promvec *romvec; + register int root_node; + register unsigned int present; + + root_node = (*(romvec->pv_nodeops->no_nextnode))(0); + tbase_needs_unmapping=0; + + present = 0; + (*(romvec->pv_nodeops->no_getprop))(root_node, "buserr-type", + (char *) &present); + if(present == 1) + { + tbase_needs_unmapping=1; + printk("MMU bug found: not allowing trapbase to be cached\n"); + } + + return; +} + + +static void +check_bugs(void) +{ + check_mmu(); +} diff --git a/include/asm-sparc/openprom.h b/include/asm-sparc/openprom.h index c90c3b366b6d..a810167112ce 100644 --- a/include/asm-sparc/openprom.h +++ b/include/asm-sparc/openprom.h @@ -1,3 +1,6 @@ +#ifndef _SPARC_OPENPROM_H +#define _SPARC_OPENPROM_H + /* openprom.h: Prom structures and defines for access to the OPENBOOT prom routines and data areas. @@ -16,7 +19,7 @@ #define LINUX_OPPROM_MAGIC 0x10010407 /* The device functions structure for the v0 prom. Nice and neat, open, - close, read & write divied up between net + block + char devices. We + close, read & write divvied up between net + block + char devices. We also have a seek routine only usable for block devices. The divide and conquer strategy of this struct becomes unnecessary for v2. @@ -51,7 +54,7 @@ struct linux_dev_v0_funcs { the time can be a pain in the rear after a while. Why v2 has memory allocations in here are beyond me. Perhaps they figure that if you are going to use only the prom's device drivers then your memory - management is either non-existant or pretty sad. :-) + management is either non-existent or pretty sad. :-) */ struct linux_dev_v2_funcs { @@ -64,7 +67,7 @@ struct linux_dev_v2_funcs { caddr_t (*v2_dumb_mem_alloc)(caddr_t va, unsigned sz); void (*v2_dumb_mem_free)(caddr_t va, unsigned sz); - /* "dumb" mmap() munmap(), copy on write? whats that? */ + /* "dumb" mmap() munmap(), copy on write? what's that? */ caddr_t (*v2_dumb_mmap)(caddr_t virta, int asi, unsigned prot, unsigned sz); void (*v2_dumb_munmap)(caddr_t virta, unsigned size); @@ -103,7 +106,7 @@ struct linux_mem_v0 { struct linux_mlist_v0 **v0_available; /* what phys. is left over */ }; -/* Arguements sent to the kernel from the boot prompt. */ +/* Arguments sent to the kernel from the boot prompt. */ struct linux_arguments_v0 { char *argv[8]; /* argv format for boot string */ @@ -260,3 +263,5 @@ struct nodeops { int (*no_setprop)(int node, caddr_t name, caddr_t val, int len); caddr_t (*no_nextprop)(int node, caddr_t name); }; + +#endif /* !(_SPARC_OPENPROM_H) */ diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h index 8b7c794b86fb..51868e24ac10 100644 --- a/include/asm-sparc/types.h +++ b/include/asm-sparc/types.h @@ -10,19 +10,21 @@ * however this won't be for a while. */ -typedef signed char __s8; +typedef __signed__ char __s8; typedef unsigned char __u8; -typedef signed short __s16; +typedef __signed__ short __s16; typedef unsigned short __u16; -typedef signed int __s32; +typedef __signed__ int __s32; typedef unsigned int __u32; /* Only 32-bit sparcs for now so.... */ -typedef signed long long __s64; +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; typedef unsigned long long __s64; +#endif #ifdef __KERNEL__ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 84b48d93c82d..1e0b17c8168a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -44,4 +44,6 @@ extern int * blk_size[MAX_BLKDEV]; extern int * blksize_size[MAX_BLKDEV]; +extern int * hardsect_size[MAX_BLKDEV]; + #endif diff --git a/include/linux/config.h b/include/linux/config.h index a22241e91229..b830c00a2d7a 100644 --- a/include/linux/config.h +++ b/include/linux/config.h @@ -9,12 +9,13 @@ #ifndef UTS_SYSNAME #define UTS_SYSNAME "Linux" #endif -#ifndef UTS_NODENAME -#define UTS_NODENAME "(none)" /* set by sethostname() */ -#endif #ifndef UTS_MACHINE -#define UTS_MACHINE "i386" /* hardware type */ +#define UTS_MACHINE "unknown" +#endif + +#ifndef UTS_NODENAME +#define UTS_NODENAME "(none)" /* set by sethostname() */ #endif #ifndef UTS_DOMAINNAME diff --git a/include/linux/in.h b/include/linux/in.h index 96910e971306..16cbe03b842e 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -124,6 +124,11 @@ extern unsigned short int ntohs(unsigned short int); extern unsigned long int htonl(unsigned long int); extern unsigned short int htons(unsigned short int); +extern unsigned long int __ntohl(unsigned long int); +extern unsigned short int __ntohs(unsigned short int); +extern unsigned long int __constant_ntohl(unsigned long int); +extern unsigned short int __constant_ntohs(unsigned short int); + extern __inline__ unsigned long int __ntohl(unsigned long int x) { diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 4fd8585c4511..8bc7b4fcf83a 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -2,6 +2,8 @@ #ifndef _LINUX_INTERRUPT_H #define _LINUX_INTERRUPT_H +#include + struct bh_struct { void (*routine)(void *); void *data; @@ -27,17 +29,17 @@ enum { extern inline void mark_bh(int nr) { - __asm__ __volatile__("orl %1,%0":"=m" (bh_active):"ir" (1<>1)) struct rlimit { - int rlim_cur; - int rlim_max; + long rlim_cur; + long rlim_max; }; #define PRIO_MIN (-99) diff --git a/include/linux/sched.h b/include/linux/sched.h index a6fc83cfcdca..0030c80c0bee 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -11,52 +11,14 @@ #define HZ 100 -/* - * System setup and hardware bug flags.. - */ -extern char hard_math; -extern char x86; /* lower 4 bits */ -extern char x86_vendor_id[13]; -extern char x86_model; /* lower 4 bits */ -extern char x86_mask; /* lower 4 bits */ -extern int x86_capability; /* field of flags */ -extern int fdiv_bug; -extern char ignore_irq13; -extern char wp_works_ok; /* doesn't work on a 386 */ -extern char hlt_works_ok; /* problems on some 486Dx4's and old 386's */ - extern unsigned long intr_count; extern unsigned long event; -#define start_bh_atomic() \ -__asm__ __volatile__("incl _intr_count") - -#define end_bh_atomic() \ -__asm__ __volatile__("decl _intr_count") - -/* - * Bus types (default is ISA, but people can check others with these..) - * MCA_bus hardcoded to 0 for now. - */ -extern int EISA_bus; -#define MCA_bus 0 - #include #include #include #include -/* - * User space process size: 3GB. This is hardcoded into a few places, - * so don't change it unless you know what you are doing. - */ -#define TASK_SIZE 0xc0000000 - -/* - * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. - */ -#define IO_BITMAP_SIZE 32 - /* * These are the constant used to fake the fixed-point load-average * counting. Some notes: @@ -98,6 +60,8 @@ extern unsigned long avenrun[]; /* Load averages */ #include #include +#include + #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 @@ -119,82 +83,6 @@ asmlinkage void schedule(void); #endif /* __KERNEL__ */ -struct i387_hard_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ -}; - -struct i387_soft_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long top; - struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 bytes */ - unsigned char lookahead; - struct info *info; - unsigned long entry_eip; -}; - -union i387_union { - struct i387_hard_struct hard; - struct i387_soft_struct soft; -}; - -struct tss_struct { - unsigned short back_link,__blh; - unsigned long esp0; - unsigned short ss0,__ss0h; - unsigned long esp1; - unsigned short ss1,__ss1h; - unsigned long esp2; - unsigned short ss2,__ss2h; - unsigned long cr3; - unsigned long eip; - unsigned long eflags; - unsigned long eax,ecx,edx,ebx; - unsigned long esp; - unsigned long ebp; - unsigned long esi; - unsigned long edi; - unsigned short es, __esh; - unsigned short cs, __csh; - unsigned short ss, __ssh; - unsigned short ds, __dsh; - unsigned short fs, __fsh; - unsigned short gs, __gsh; - unsigned short ldt, __ldth; - unsigned short trace, bitmap; - unsigned long io_bitmap[IO_BITMAP_SIZE+1]; - unsigned long tr; - unsigned long cr2, trap_no, error_code; - union i387_union i387; -}; - -#define INIT_TSS { \ - 0,0, \ - sizeof(init_kernel_stack) + (long) &init_kernel_stack, \ - KERNEL_DS, 0, \ - 0,0,0,0,0,0, \ - (long) &swapper_pg_dir, \ - 0,0,0,0,0,0,0,0,0,0, \ - USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0, \ - _LDT(0),0, \ - 0, 0x8000, \ - {~0, }, /* ioperm */ \ - _TSS(0), 0, 0,0, \ - { { 0, }, } /* 387 state */ \ -} - struct files_struct { int count; fd_set close_on_exec; @@ -286,10 +174,6 @@ struct task_struct { struct rlimit rlim[RLIM_NLIMITS]; unsigned short used_math; char comm[16]; -/* virtual 86 mode stuff */ - struct vm86_struct * vm86_info; - unsigned long screen_bitmap; - unsigned long v86flags, v86mask, v86mode; /* file system info */ int link_count; struct tty_struct *tty; /* NULL if no tty */ @@ -298,7 +182,7 @@ struct task_struct { /* ldt for this task - used by Wine. If NULL, default_ldt is used */ struct desc_struct *ldt; /* tss for this task */ - struct tss_struct tss; + struct thread_struct tss; /* filesystem information */ struct fs_struct fs[1]; /* open file information */ @@ -345,7 +229,6 @@ struct task_struct { { 0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \ /* math */ 0, \ /* comm */ "swapper", \ -/* vm86_info */ NULL, 0, 0, 0, 0, \ /* fs info */ 0,NULL, \ /* ipc */ NULL, \ /* ldt */ NULL, \ @@ -381,79 +264,6 @@ extern int in_group_p(gid_t grp); extern int request_irq(unsigned int irq,void (*handler)(int), unsigned long flags, const char *device); extern void free_irq(unsigned int irq); -/* - * Entry into gdt where to find first TSS. GDT layout: - * 0 - nul - * 1 - kernel code segment - * 2 - kernel data segment - * 3 - user code segment - * 4 - user data segment - * ... - * 8 - TSS #0 - * 9 - LDT #0 - * 10 - TSS #1 - * 11 - LDT #1 - */ -#define FIRST_TSS_ENTRY 8 -#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1) -#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) -#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3)) -#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n))) -#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n))) -#define store_TR(n) \ -__asm__("str %%ax\n\t" \ - "subl %2,%%eax\n\t" \ - "shrl $4,%%eax" \ - :"=a" (n) \ - :"0" (0),"i" (FIRST_TSS_ENTRY<<3)) -/* - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - * This also clears the TS-flag if the task we switched to has used - * tha math co-processor latest. - */ -#define switch_to(tsk) \ -__asm__("cli\n\t" \ - "xchgl %%ecx,_current\n\t" \ - "ljmp %0\n\t" \ - "sti\n\t" \ - "cmpl %%ecx,_last_task_used_math\n\t" \ - "jne 1f\n\t" \ - "clts\n" \ - "1:" \ - : /* no output */ \ - :"m" (*(((char *)&tsk->tss.tr)-4)), \ - "c" (tsk) \ - :"cx") - -#define _set_base(addr,base) \ -__asm__("movw %%dx,%0\n\t" \ - "rorl $16,%%edx\n\t" \ - "movb %%dl,%1\n\t" \ - "movb %%dh,%2" \ - : /* no output */ \ - :"m" (*((addr)+2)), \ - "m" (*((addr)+4)), \ - "m" (*((addr)+7)), \ - "d" (base) \ - :"dx") - -#define _set_limit(addr,limit) \ -__asm__("movw %%dx,%0\n\t" \ - "rorl $16,%%edx\n\t" \ - "movb %1,%%dh\n\t" \ - "andb $0xf0,%%dh\n\t" \ - "orb %%dh,%%dl\n\t" \ - "movb %%dl,%1" \ - : /* no output */ \ - :"m" (*(addr)), \ - "m" (*((addr)+6)), \ - "d" (limit) \ - :"dx") - -#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base ) -#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) - /* * The wait-queues are circular lists, and you have to be *very* sure * to keep them correct. Use only these two functions to add/remove @@ -556,30 +366,6 @@ extern inline void up(struct semaphore * sem) wake_up(&sem->wait); } -static inline unsigned long _get_base(char * addr) -{ - unsigned long __base; - __asm__("movb %3,%%dh\n\t" - "movb %2,%%dl\n\t" - "shll $16,%%edx\n\t" - "movw %1,%%dx" - :"=&d" (__base) - :"m" (*((addr)+2)), - "m" (*((addr)+4)), - "m" (*((addr)+7))); - return __base; -} - -#define get_base(ldt) _get_base( ((char *)&(ldt)) ) - -static inline unsigned long get_limit(unsigned long segment) -{ - unsigned long __limit; - __asm__("lsll %1,%0" - :"=r" (__limit):"r" (segment)); - return __limit+1; -} - #define REMOVE_LINKS(p) do { unsigned long flags; \ save_flags(flags) ; cli(); \ (p)->next_task->prev_task = (p)->prev_task; \ @@ -609,21 +395,6 @@ static inline unsigned long get_limit(unsigned long segment) #define for_each_task(p) \ for (p = &init_task ; (p = p->next_task) != &init_task ; ) -/* - * This is the ldt that every process will get unless we need - * something other than this. - */ -extern struct desc_struct default_ldt; - -/* This special macro can be used to load a debugging register */ - -#define loaddebug(register) \ - __asm__("movl %0,%%edx\n\t" \ - "movl %%edx,%%db" #register "\n\t" \ - : /* no output */ \ - :"m" (current->debugreg[register]) \ - :"dx"); - #endif /* __KERNEL__ */ #endif diff --git a/include/linux/string.h b/include/linux/string.h index 13e8da56e2cf..81c6a76a8650 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -11,19 +11,28 @@ extern "C" { #endif +extern char * strcpy(char *,const char *); +extern char * strncpy(char *,const char *,size_t); +extern char * strcat(char *, const char *); +extern char * strncat(char *, const char *, size_t); +extern char * strchr(const char *,char); +extern char * strpbrk(const char *,const char *); +extern char * strtok(char *,const char *); +extern size_t strlen(const char *); +extern size_t strspn(const char *,const char *); +extern int strcmp(const char *,const char *); +extern int strncmp(const char *,const char *,size_t); + +extern void * memset(void *,char,size_t); +extern void * memcpy(void *,const void *,size_t); +extern void * memmove(void *,const void *,size_t); +extern int memcmp(const void *,const void *,size_t); + /* * Include machine specific inline routines */ #include -#ifdef __USE_PORTABLE_STRINGS_H_ -/* - * include/generic/string.h imports all the string functions, - * for which no appropriate assembler replacements have been provided. - */ -#include -#endif - #ifdef __cplusplus } #endif diff --git a/include/linux/tqueue.h b/include/linux/tqueue.h index d264495e3a78..593af79b3f29 100644 --- a/include/linux/tqueue.h +++ b/include/linux/tqueue.h @@ -143,9 +143,7 @@ _INLINE_ void run_task_queue(task_queue *list) void (*f) (void *); while(1) { - p = &tq_last; - __asm__ __volatile__("xchgl %0,%2" : "=r" (p) : - "0" (p), "m" (*list) : "memory"); + p = xchg_ptr(list,&tq_last); if(p == &tq_last) break; diff --git a/include/linux/types.h b/include/linux/types.h index f780f09b9c1e..d0dc03c117d1 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -28,7 +28,7 @@ typedef unsigned short nlink_t; typedef int daddr_t; typedef long off_t; -#ifndef __STRICT_ANSI__ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #define _LOFF_T typedef long long loff_t; #endif diff --git a/init/main.c b/init/main.c index 7b0c9830ed23..e571dd3f8b8f 100644 --- a/init/main.c +++ b/init/main.c @@ -24,12 +24,12 @@ #include #include +#include + extern unsigned long * prof_buffer; extern unsigned long prof_len; extern char etext, end; extern char *linux_banner; -asmlinkage void lcall7(void); -struct desc_struct default_ldt; /* * we need this inline - forking from kernel space will result @@ -159,8 +159,6 @@ unsigned char aux_device_present; int ramdisk_size; int root_mountflags = 0; -static char fpu_error = 0; - static char command_line[COMMAND_LINE_SIZE] = { 0, }; char *get_options(char *str, int *ints) @@ -183,6 +181,10 @@ struct { } bootsetups[] = { { "reserve=", reserve_setup }, { "ramdisk=", ramdisk_setup }, +#ifdef CONFIG_BUGi386 + { "no-hlt", no_halt }, + { "no387", no_387 }, +#endif #ifdef CONFIG_INET { "ether=", eth_setup }, #endif @@ -352,17 +354,6 @@ static void parse_options(char *line) console_loglevel = 10; continue; } - if (!strcmp(line,"no-hlt")) { - hlt_works_ok = 0; - continue; - } - if (!strcmp(line,"no387")) { - hard_math = 0; - __asm__("movl %%cr0,%%eax\n\t" - "orl $0xE,%%eax\n\t" - "movl %%eax,%%cr0\n\t" : : : "ax"); - continue; - } if (checksetup(line)) continue; /* @@ -409,91 +400,7 @@ static void copy_options(char * to, char * from) *to = '\0'; } -static void copro_timeout(void) -{ - fpu_error = 1; - timer_table[COPRO_TIMER].expires = jiffies+100; - timer_active |= 1<ldt != NULL) memcpy(p->ldt, current->ldt, LDT_ENTRIES*LDT_ENTRY_SIZE); } - p->tss.bitmap = offsetof(struct tss_struct,io_bitmap); + p->tss.bitmap = offsetof(struct thread_struct,io_bitmap); for (i = 0; i < IO_BITMAP_SIZE+1 ; i++) /* IO bitmap is actually SIZE+1 */ p->tss.io_bitmap[i] = ~0; if (last_task_used_math == current) diff --git a/kernel/ksyms.c b/kernel/ksyms.c index c499cd229d5b..9e222d77404b 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -144,6 +144,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ X(block_fsync), X(wait_for_request), X(blksize_size), + X(hardsect_size), X(blk_size), X(blk_dev), X(is_read_only), diff --git a/kernel/sched.c b/kernel/sched.c index 1f3c0f7b010a..c9285844f0c4 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -95,9 +95,9 @@ unsigned long prof_len = 0; extern void mem_use(void); extern int timer_interrupt(void); -asmlinkage int system_call(void); - + static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; +unsigned long init_user_stack[1024] = { STACK_MAGIC, }; static struct vm_area_struct init_mmap = INIT_MMAP; struct task_struct init_task = INIT_TASK; @@ -108,55 +108,8 @@ struct task_struct *last_task_used_math = NULL; struct task_struct * task[NR_TASKS] = {&init_task, }; -long user_stack [ PAGE_SIZE>>2 ] = { STACK_MAGIC, }; - -struct { - long * a; - short b; - } stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS }; - struct kernel_stat kstat = { 0 }; -/* - * 'math_state_restore()' saves the current math information in the - * old math state array, and gets the new ones from the current task - * - * Careful.. There are problems with IBM-designed IRQ13 behaviour. - * Don't touch unless you *really* know how it works. - */ -asmlinkage void math_state_restore(void) -{ - __asm__ __volatile__("clts"); - if (last_task_used_math == current) - return; - timer_table[COPRO_TIMER].expires = jiffies+50; - timer_active |= 1<tss.i387)); - else - __asm__("fnclex"); - last_task_used_math = current; - if (current->used_math) { - __asm__("frstor %0": :"m" (current->tss.i387)); - } else { - __asm__("fninit"); - current->used_math=1; - } - timer_active &= ~(1<comm); - send_sig(SIGFPE,current,1); - schedule(); -} - -#endif /* CONFIG_MATH_EMULATION */ - unsigned long itimer_ticks = 0; unsigned long itimer_next = ~0; @@ -252,14 +205,6 @@ confuse_gcc2: return; kstat.context_swtch++; switch_to(next); - /* Now maybe reload the debug registers */ - if(current->debugreg[7]){ - loaddebug(0); - loaddebug(1); - loaddebug(2); - loaddebug(3); - loaddebug(6); - }; } asmlinkage int sys_pause(void) @@ -801,10 +746,12 @@ static void show_task(int nr,struct task_struct * p) printk(stat_nam[p->state]); else printk(" "); +#ifdef __i386__ if (p == current) printk(" current "); else printk(" %08lX ", ((unsigned long *)p->tss.esp)[3]); +#endif for (free = 1; free < 1024 ; free++) { if (((unsigned long *)p->kernel_stack_page)[free]) break; @@ -837,29 +784,11 @@ void show_state(void) void sched_init(void) { - int i; - struct desc_struct * p; - bh_base[TIMER_BH].routine = timer_bh; bh_base[TQUEUE_BH].routine = tqueue_bh; bh_base[IMMEDIATE_BH].routine = immediate_bh; if (sizeof(struct sigaction) != 16) panic("Struct sigaction MUST be 16 bytes"); - set_tss_desc(gdt+FIRST_TSS_ENTRY,&init_task.tss); - set_ldt_desc(gdt+FIRST_LDT_ENTRY,&default_ldt,1); - set_system_gate(0x80,&system_call); - p = gdt+2+FIRST_TSS_ENTRY; - for(i=1 ; ia=p->b=0; - p++; - p->a=p->b=0; - p++; - } -/* Clear NT, so that we won't have troubles with that later on */ - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - load_TR(0); - load_ldt(0); outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ diff --git a/kernel/traps.c b/kernel/traps.c index 150b702b3214..c19fa33fcba6 100644 --- a/kernel/traps.c +++ b/kernel/traps.c @@ -16,11 +16,17 @@ #include #include #include +#include +#include #include #include #include +asmlinkage int system_call(void); +asmlinkage void lcall7(void); +struct desc_struct default_ldt; + static inline void console_verbose(void) { extern int console_loglevel; @@ -218,10 +224,52 @@ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) math_error(); } +/* + * 'math_state_restore()' saves the current math information in the + * old math state array, and gets the new ones from the current task + * + * Careful.. There are problems with IBM-designed IRQ13 behaviour. + * Don't touch unless you *really* know how it works. + */ +asmlinkage void math_state_restore(void) +{ + __asm__ __volatile__("clts"); + if (last_task_used_math == current) + return; + timer_table[COPRO_TIMER].expires = jiffies+50; + timer_active |= 1<tss.i387)); + else + __asm__("fnclex"); + last_task_used_math = current; + if (current->used_math) { + __asm__("frstor %0": :"m" (current->tss.i387)); + } else { + __asm__("fninit"); + current->used_math=1; + } + timer_active &= ~(1<comm); + send_sig(SIGFPE,current,1); + schedule(); +} + +#endif /* CONFIG_MATH_EMULATION */ + void trap_init(void) { int i; + struct desc_struct * p; + set_call_gate(&default_ldt,lcall7); set_trap_gate(0,÷_error); set_trap_gate(1,&debug); set_trap_gate(2,&nmi); @@ -242,4 +290,21 @@ void trap_init(void) set_trap_gate(17,&alignment_check); for (i=18;i<48;i++) set_trap_gate(i,&reserved); + set_system_gate(0x80,&system_call); +/* set up GDT task & ldt entries */ + p = gdt+FIRST_TSS_ENTRY; + set_tss_desc(p, &init_task.tss); + p++; + set_ldt_desc(p, &default_ldt, 1); + p++; + for(i=1 ; ia=p->b=0; + p++; + p->a=p->b=0; + p++; + } +/* Clear NT, so that we won't have troubles with that later on */ + __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); + load_TR(0); + load_ldt(0); } diff --git a/kernel/vm86.c b/kernel/vm86.c index 144d93a024c7..f1c78ecf7614 100644 --- a/kernel/vm86.c +++ b/kernel/vm86.c @@ -39,8 +39,8 @@ /* * virtual flags (16 and 32-bit versions) */ -#define VFLAGS (*(unsigned short *)&(current->v86flags)) -#define VEFLAGS (current->v86flags) +#define VFLAGS (*(unsigned short *)&(current->tss.v86flags)) +#define VEFLAGS (current->tss.v86flags) #define set_flags(X,new,mask) \ ((X) = ((X) & ~(mask)) | ((new) & (mask))) @@ -52,13 +52,13 @@ asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs) { unsigned long tmp; - if (!current->vm86_info) { + if (!current->tss.vm86_info) { printk("no vm86_info: BAD\n"); do_exit(SIGSEGV); } - set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->v86mask); - memcpy_tofs(¤t->vm86_info->regs,regs,sizeof(*regs)); - put_fs_long(current->screen_bitmap,¤t->vm86_info->screen_bitmap); + set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->tss.v86mask); + memcpy_tofs(¤t->tss.vm86_info->regs,regs,sizeof(*regs)); + put_fs_long(current->tss.screen_bitmap,¤t->tss.vm86_info->screen_bitmap); tmp = current->tss.esp0; current->tss.esp0 = current->saved_kernel_stack; current->saved_kernel_stack = 0; @@ -117,16 +117,16 @@ asmlinkage int sys_vm86(struct vm86_struct * v86) switch (info.cpu_type) { case CPU_286: - current->v86mask = 0; + current->tss.v86mask = 0; break; case CPU_386: - current->v86mask = NT_MASK | IOPL_MASK; + current->tss.v86mask = NT_MASK | IOPL_MASK; break; case CPU_486: - current->v86mask = AC_MASK | NT_MASK | IOPL_MASK; + current->tss.v86mask = AC_MASK | NT_MASK | IOPL_MASK; break; default: - current->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; + current->tss.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; break; } @@ -136,9 +136,9 @@ asmlinkage int sys_vm86(struct vm86_struct * v86) pt_regs->eax = 0; current->saved_kernel_stack = current->tss.esp0; current->tss.esp0 = (unsigned long) pt_regs; - current->vm86_info = v86; + current->tss.vm86_info = v86; - current->screen_bitmap = info.screen_bitmap; + current->tss.screen_bitmap = info.screen_bitmap; if (info.flags & VM86_SCREEN_BITMAP) mark_screen_rdonly(current); __asm__ __volatile__("movl %0,%%esp\n\t" @@ -178,7 +178,7 @@ static inline void clear_TF(struct vm86_regs * regs) static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs) { - set_flags(VEFLAGS, eflags, current->v86mask); + set_flags(VEFLAGS, eflags, current->tss.v86mask); set_flags(regs->eflags, eflags, SAFE_MASK); if (eflags & IF_MASK) set_IF(regs); @@ -186,7 +186,7 @@ static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs static inline void set_vflags_short(unsigned short flags, struct vm86_regs * regs) { - set_flags(VFLAGS, flags, current->v86mask); + set_flags(VFLAGS, flags, current->tss.v86mask); set_flags(regs->eflags, flags, SAFE_MASK); if (flags & IF_MASK) set_IF(regs); @@ -198,7 +198,7 @@ static inline unsigned long get_vflags(struct vm86_regs * regs) if (VEFLAGS & VIF_MASK) flags |= IF_MASK; - return flags | (VEFLAGS & current->v86mask); + return flags | (VEFLAGS & current->tss.v86mask); } static inline int is_revectored(int nr, struct revectored_struct * bitmap) @@ -287,9 +287,9 @@ static void do_int(struct vm86_regs *regs, int i, unsigned char * ssp, unsigned unsigned short seg = get_fs_word((void *) ((i<<2)+2)); if (seg == BIOSSEG || regs->cs == BIOSSEG || - is_revectored(i, ¤t->vm86_info->int_revectored)) + is_revectored(i, ¤t->tss.vm86_info->int_revectored)) return_to_32bit(regs, VM86_INTx + (i << 8)); - if (i==0x21 && is_revectored(AH(regs),¤t->vm86_info->int21_revectored)) + if (i==0x21 && is_revectored(AH(regs),¤t->tss.vm86_info->int21_revectored)) return_to_32bit(regs, VM86_INTx + (i << 8)); pushw(ssp, sp, get_vflags(regs)); pushw(ssp, sp, regs->cs); diff --git a/lib/string.c b/lib/string.c index 8c69ff0c39f5..700330269dab 100644 --- a/lib/string.c +++ b/lib/string.c @@ -4,8 +4,196 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#include - -/* all the actual functions should be inline anyway, so.. */ +/* + * stupid library routines.. The optimized versions should generally be found + * as inline code in + * + * These are buggy as well.. + */ + +#include char * ___strtok = NULL; + +char * strcpy(char * dest,const char *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') + /* nothing */; + return tmp; +} + +char * strncpy(char * dest,const char *src,size_t count) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0' && --count) + /* nothing */; + + return tmp; +} + +char * strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} + +char * strncat(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + if (count) { + while (*dest) + dest++; + while ((*dest++ = *src++)) { + if (--count == 0) + break; + } + } + + return tmp; +} + +int strcmp(const char * cs,const char * ct) +{ + register char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 && *cs++) + break; + } + + return __res; +} + +int strncmp(const char * cs,const char * ct,size_t count) +{ + register char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} + +char * strchr(const char * s,char c) +{ + const char ch = c; + + for(; *s != ch; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} + +size_t strlen(const char * s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + +size_t strspn(const char *s, const char *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (a = accept; *a != '\0'; ++a) { + if (*p == *a) + break; + } + if (*a == '\0') + return count; + ++count; + } + + return count; +} + +char * strpbrk(const char * cs,const char * ct) +{ + const char *sc1,*sc2; + + for( sc1 = cs; *sc1 != '\0'; ++sc1) { + for( sc2 = ct; *sc2 != '\0'; ++sc2) { + if (*sc1 == *sc2) + return (char *) sc1; + } + } + return NULL; +} + +char * strtok(char * s,const char * ct) +{ + char *sbegin, *send; + + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return( NULL ); + } + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + return (sbegin); +} + +void * memset(void * s,char c,size_t count) +{ + char *xs = (char *) s; + + while (count--) + *xs++ = c; + + return s; +} + +void * memcpy(void * dest,const void *src,size_t count) +{ + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; +} + +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; +} + +int memcmp(const void * cs,const void * ct,size_t count) +{ + const unsigned char *su1, *su2; + + for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if (*su1 != *su2) + return((*su1 < *su2) ? -1 : +1); + return(0); +} diff --git a/mm/memory.c b/mm/memory.c index b85d81ea057d..8d435a232789 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1001,7 +1001,7 @@ good_area: if (regs->eflags & VM_MASK) { unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT; if (bit < 32) - current->screen_bitmap |= 1 << bit; + current->tss.screen_bitmap |= 1 << bit; } if (!(vma->vm_page_prot & PAGE_USER)) goto bad_area; diff --git a/net/inet/ip.c b/net/inet/ip.c index 8ca59b4ff6c1..6c76eb9dbf8a 100644 --- a/net/inet/ip.c +++ b/net/inet/ip.c @@ -2118,6 +2118,16 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt return 0; } #endif + case IP_MULTICAST_LOOP: + { + unsigned char ucval; + + ucval=get_fs_byte((unsigned char *)optval); + if(ucval!=0 && ucval!=1) + return -EINVAL; + sk->ip_mc_loop=(int)ucval; + return 0; + } case IP_MULTICAST_IF: { /* Not fully tested */ @@ -2357,6 +2367,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op case IP_MULTICAST_TTL: val=sk->ip_mc_ttl; break; + case IP_MULTICAST_LOOP: + val=sk->ip_mc_loop; + break; case IP_MULTICAST_IF: err=verify_area(VERIFY_WRITE, optlen, sizeof(int)); if(err) diff --git a/net/inet/proc.c b/net/inet/proc.c index c143924bd04b..78173fce7633 100644 --- a/net/inet/proc.c +++ b/net/inet/proc.c @@ -90,12 +90,13 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of timer_active = del_timer(&sp->timer); if (!timer_active) sp->timer.expires = 0; - len+=sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n", + len+=sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d %d\n", i, src, srcp, dest, destp, sp->state, format==0?sp->write_seq-sp->rcv_ack_seq:sp->rmem_alloc, format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc, timer_active, sp->timer.expires, (unsigned) sp->retransmits, - sp->socket?SOCK_INODE(sp->socket)->i_uid:0); + sp->socket?SOCK_INODE(sp->socket)->i_uid:0, + timer_active?sp->timeout:0); if (timer_active) add_timer(&sp->timer); /* diff --git a/net/inet/tcp.c b/net/inet/tcp.c index cb8aef93857b..20dbdcf4b964 100644 --- a/net/inet/tcp.c +++ b/net/inet/tcp.c @@ -241,7 +241,7 @@ static __inline__ void tcp_set_state(struct sock *sk, int state) if(sk->debug) printk("TCP sk=%p, State %s -> %s\n",sk, statename[sk->state],statename[state]); #endif - /* This is a hack but it doesnt occur often and its going to + /* This is a hack but it doesn't occur often and its going to be a real to fix nicely */ if(state==TCP_ESTABLISHED && sk->state==TCP_SYN_RECV) @@ -602,7 +602,7 @@ static int tcp_readable(struct sock *sk) return(0); } - counted = sk->copied_seq+1; /* Where we are at the moment */ + counted = sk->copied_seq; /* Where we are at the moment */ amount = 0; /* Do until a push or until we are out of data. */ @@ -655,43 +655,29 @@ static int tcp_readable(struct sock *sk) * listening socket has a receive queue of sockets to accept. */ -static int tcp_select(struct sock *sk, int sel_type, select_table *wait) +static int do_tcp_select(struct sock *sk, int sel_type, select_table *wait) { - sk->inuse = 1; - switch(sel_type) { case SEL_IN: - select_wait(sk->sleep, wait); - if(sk->state==TCP_LISTEN) + if (sk->err) + return 1; + if (sk->state == TCP_LISTEN) { select_wait(&master_select_wakeup,wait); - if (skb_peek(&sk->receive_queue) != NULL) - { - if ((sk->state == TCP_LISTEN && tcp_find_established(sk)) || tcp_readable(sk)) - { - release_sock(sk); - return(1); - } + return (tcp_find_established(sk) != NULL); } - if (sk->err != 0) /* Receiver error */ - { - release_sock(sk); - return(1); - } - if (sk->shutdown & RCV_SHUTDOWN) - { - release_sock(sk); - return(1); - } - release_sock(sk); - return(0); + if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) + return 0; + if (sk->acked_seq != sk->copied_seq) + return 1; + if (sk->shutdown & RCV_SHUTDOWN) + return 1; + return 0; + case SEL_OUT: - select_wait(sk->sleep, wait); - if (sk->shutdown & SEND_SHUTDOWN) - { + if (sk->shutdown & SEND_SHUTDOWN) { /* FIXME: should this return an error? */ - release_sock(sk); - return(0); + return 0; } /* @@ -701,29 +687,31 @@ static int tcp_select(struct sock *sk, int sel_type, select_table *wait) if (sk->prot->wspace(sk) >= sk->mtu+128+sk->prot->max_header) { - release_sock(sk); /* This should cause connect to work ok. */ if (sk->state == TCP_SYN_RECV || - sk->state == TCP_SYN_SENT) return(0); - return(1); + sk->state == TCP_SYN_SENT) return 0; + return 1; } - release_sock(sk); - return(0); + return 0; + case SEL_EX: - select_wait(sk->sleep,wait); - if (sk->err || sk->urg_data) - { - release_sock(sk); - return(1); - } - release_sock(sk); - return(0); + if (sk->err || sk->urg_data) + return 1; + return 0; } - - release_sock(sk); - return(0); + return 0; } +static int tcp_select(struct sock *sk, int sel_type, select_table *wait) +{ + int retval; + + sk->inuse = 1; + select_wait(sk->sleep, wait); + retval = do_tcp_select(sk, sel_type, wait); + release_sock(sk); + return retval; +} int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) { @@ -753,7 +741,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) } case SIOCATMARK: { - int answ = sk->urg_data && sk->urg_seq == sk->copied_seq+1; + int answ = sk->urg_data && sk->urg_seq == sk->copied_seq; err = verify_area(VERIFY_WRITE,(void *) arg, sizeof(unsigned long)); @@ -1702,7 +1690,7 @@ static int tcp_read(struct sock *sk, unsigned char *to, /* * are we at urgent data? Stop if we have read anything. */ - if (copied && sk->urg_data && sk->urg_seq == 1+*seq) + if (copied && sk->urg_data && sk->urg_seq == *seq) break; current->state = TASK_INTERRUPTIBLE; @@ -1712,13 +1700,15 @@ static int tcp_read(struct sock *sk, unsigned char *to, { if (!skb) break; - if (before(1+*seq, skb->h.th->seq)) + if (before(*seq, skb->h.th->seq)) break; - offset = 1 + *seq - skb->h.th->seq; + offset = *seq - skb->h.th->seq; if (skb->h.th->syn) offset--; if (offset < skb->len) goto found_ok_skb; + if (skb->h.th->fin) + goto found_fin_ok; if (!(flags & MSG_PEEK)) skb->used = 1; skb = skb->next; @@ -1778,7 +1768,7 @@ static int tcp_read(struct sock *sk, unsigned char *to, /* do we have urgent data here? */ if (sk->urg_data) { - unsigned long urg_offset = sk->urg_seq - (1 + *seq); + unsigned long urg_offset = sk->urg_seq - *seq; if (urg_offset < used) { if (!urg_offset) @@ -1801,10 +1791,25 @@ static int tcp_read(struct sock *sk, unsigned char *to, len -= used; to += used; *seq += used; - if (after(sk->copied_seq+1,sk->urg_seq)) + if (after(sk->copied_seq,sk->urg_seq)) sk->urg_data = 0; - if (!(flags & MSG_PEEK) && (used + offset >= skb->len)) - skb->used = 1; + if (used + offset < skb->len) + continue; + if (skb->h.th->fin) + goto found_fin_ok; + if (flags & MSG_PEEK) + continue; + skb->used = 1; + continue; + + found_fin_ok: + ++*seq; + if (flags & MSG_PEEK) + break; + skb->used = 1; + sk->shutdown |= RCV_SHUTDOWN; + break; + } remove_wait_queue(sk->sleep, &wait); current->state = TASK_RUNNING; @@ -2256,8 +2261,8 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, newsk->shutdown = 0; newsk->ack_backlog = 0; newsk->acked_seq = skb->h.th->seq+1; + newsk->copied_seq = skb->h.th->seq+1; newsk->fin_seq = skb->h.th->seq; - newsk->copied_seq = skb->h.th->seq; newsk->state = TCP_SYN_RECV; newsk->timeout = 0; newsk->write_seq = seq; @@ -2291,7 +2296,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, newsk->dummy_th.urg = 0; newsk->dummy_th.res2 = 0; newsk->acked_seq = skb->h.th->seq + 1; - newsk->copied_seq = skb->h.th->seq; + newsk->copied_seq = skb->h.th->seq + 1; newsk->socket = NULL; /* @@ -2780,7 +2785,7 @@ extern __inline__ int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long sk->send_tail = NULL; /* - * This is an artefact of a flawed concept. We want one + * This is an artifact of a flawed concept. We want one * queue and a smarter send routine when we send all. */ @@ -3175,7 +3180,7 @@ extern __inline__ int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long tcp_set_state(sk, TCP_ESTABLISHED); tcp_options(sk,th); sk->dummy_th.dest=th->source; - sk->copied_seq=sk->acked_seq-1; + sk->copied_seq = sk->acked_seq; if(!sk->dead) sk->state_change(sk); if(sk->max_window==0) @@ -3373,7 +3378,7 @@ extern __inline__ int tcp_data(struct sk_buff *skb, struct sock *sk, { /* * FIXME: BSD has some magic to avoid sending resets to - * broken 4.2 BSD keepalives. Much to my suprise a few none + * broken 4.2 BSD keepalives. Much to my surprise a few non * BSD stacks still have broken keepalives so we want to * cope with it. */ @@ -3529,15 +3534,12 @@ extern __inline__ int tcp_data(struct sk_buff *skb, struct sock *sk, skb->acked = 1; /* - * When we ack the fin, we turn on the RCV_SHUTDOWN flag. Also do the FIN + * When we ack the fin, we do the FIN * processing. */ if (skb->h.th->fin) { - if (!sk->dead) - sk->state_change(sk); - sk->shutdown |= RCV_SHUTDOWN; tcp_fin(skb,sk,skb->h.th); } @@ -3558,14 +3560,11 @@ extern __inline__ int tcp_data(struct sk_buff *skb, struct sock *sk, } skb2->acked = 1; /* - * When we ack the fin, we turn on - * the RCV_SHUTDOWN flag. + * When we ack the fin, we do + * the fin handling. */ if (skb2->h.th->fin) { - sk->shutdown |= RCV_SHUTDOWN; - if (!sk->dead) - sk->state_change(sk); tcp_fin(skb,sk,skb->h.th); } @@ -3676,7 +3675,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) ptr += th->seq; /* ignore urgent data that we've already seen and read */ - if (after(sk->copied_seq+1, ptr)) + if (after(sk->copied_seq, ptr)) return; /* do we already have a newer (or duplicate) urgent pointer? */ @@ -4174,7 +4173,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, /* * This basically follows the flow suggested by RFC793, with the corrections in RFC1122. We * don't implement precedence and we process URG incorrectly (deliberately so) for BSD bug - * compatibility. We also set up variables more throughroughly [Karn notes in the + * compatibility. We also set up variables more thoroughly [Karn notes in the * KA9Q code the RFC793 incoming segment rules don't initialise the variables for all paths]. */ @@ -4223,12 +4222,20 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, return 0; } + /* retransmitted SYN? */ + if (sk->state == TCP_SYN_RECV && th->syn && th->seq+1 == sk->acked_seq) + { + kfree_skb(skb, FREE_READ); + release_sock(sk); + return 0; + } + /* * SYN sent means we have to look for a suitable ack and either reset * for bad matches or go to connected */ - else if(sk->state==TCP_SYN_SENT) + if(sk->state==TCP_SYN_SENT) { /* Crossed SYN or previous junk segment */ if(th->ack) @@ -4266,7 +4273,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, tcp_set_state(sk, TCP_ESTABLISHED); tcp_options(sk,th); sk->dummy_th.dest=th->source; - sk->copied_seq=sk->acked_seq-1; + sk->copied_seq = sk->acked_seq; if(!sk->dead) sk->state_change(sk); if(sk->max_window==0) @@ -4306,51 +4313,50 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, */ goto rfc_step6; } - - } - - /* BSD has a funny hack with TIME_WAIT and fast reuse of a port. We - don't use it, we don't need it and its not in the spec. There is + + /* BSD has a funny hack with TIME_WAIT and fast reuse of a port. There is a more complex suggestion for fixing these reuse issues in RFC1644 but not yet ready for general use. Also see RFC1379.*/ - /* We are now in normal data flow (see the step list in the RFC) */ - /* Note most of these are inline now. I'll inline the lot when - I have time to test it hard and look at what gcc outputs */ - #define BSD_TIME_WAIT #ifdef BSD_TIME_WAIT - if (sk->state == TCP_TIME_WAIT && th->syn && sk->dead && - after(th->seq, sk->acked_seq) && !th->rst) - { - long seq=sk->write_seq; - if(sk->debug) - printk("Doing a BSD time wait\n"); - tcp_statistics.TcpEstabResets++; - sk->rmem_alloc -= skb->mem_len; - skb->sk = NULL; - sk->err=ECONNRESET; - tcp_set_state(sk, TCP_CLOSE); - sk->shutdown = SHUTDOWN_MASK; - release_sock(sk); - sk=get_sock(&tcp_prot, th->dest, saddr, th->source, daddr); - if(sk && sk->state==TCP_LISTEN) + if (sk->state == TCP_TIME_WAIT && th->syn && sk->dead && + after(th->seq, sk->acked_seq) && !th->rst) { - sk->inuse=1; - skb->sk = sk; - sk->rmem_alloc += skb->mem_len; - tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000); + long seq=sk->write_seq; + if(sk->debug) + printk("Doing a BSD time wait\n"); + tcp_statistics.TcpEstabResets++; + sk->rmem_alloc -= skb->mem_len; + skb->sk = NULL; + sk->err=ECONNRESET; + tcp_set_state(sk, TCP_CLOSE); + sk->shutdown = SHUTDOWN_MASK; release_sock(sk); + sk=get_sock(&tcp_prot, th->dest, saddr, th->source, daddr); + if (sk && sk->state==TCP_LISTEN) + { + sk->inuse=1; + skb->sk = sk; + sk->rmem_alloc += skb->mem_len; + tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000); + release_sock(sk); + return 0; + } + kfree_skb(skb, FREE_READ); return 0; } - kfree_skb(skb, FREE_READ); - return 0; - } #endif + } + + /* We are now in normal data flow (see the step list in the RFC) */ + /* Note most of these are inline now. I'll inline the lot when + I have time to test it hard and look at what gcc outputs */ - if(/*sk->state!=TCP_SYN_RECV &&*/ !tcp_sequence(sk,th,len,opt,saddr,dev)) + if(!tcp_sequence(sk,th,len,opt,saddr,dev)) { kfree_skb(skb, FREE_READ); + release_sock(sk); return 0; } @@ -4501,7 +4507,7 @@ static void tcp_write_wakeup(struct sock *sk) } /* - * A window probe timeout has occured. + * A window probe timeout has occurred. */ void tcp_send_probe0(struct sock *sk)