diff -u --recursive --new-file v1.1.36/linux/Makefile linux/Makefile --- v1.1.36/linux/Makefile Tue Jul 26 21:39:44 1994 +++ linux/Makefile Tue Jul 26 21:36:58 1994 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 36 +SUBLEVEL = 37 all: Version zImage @@ -127,7 +127,7 @@ .c.s: $(CC) $(CFLAGS) -S -o $*.s $< .s.o: - $(AS) -c -o $*.o $< + $(AS) -o $*.o $< .c.o: $(CC) $(CFLAGS) -c -o $*.o $< diff -u --recursive --new-file v1.1.36/linux/drivers/block/README.hd linux/drivers/block/README.hd --- v1.1.36/linux/drivers/block/README.hd Thu Jul 21 08:18:00 1994 +++ linux/drivers/block/README.hd Wed Jul 27 11:10:18 1994 @@ -1,6 +1,13 @@ -IDE Performance Enhancements Version 2.0 +IDE Performance Enhancements Version 2.1 ============================ =========== +What's new in version 2.1: + -- Support added for E-IDE BIOSs, for systems with IDE drives + that "have more than 16 logical heads" (according the BIOS). + -- the HDIO_SETUNMASKINTR and HDIO_SETMULTCOUNT now permit + only the superuser to change settings, and no longer permit + minor device numbers to be used. + This version of hd.c includes support for two optional features: (1) The disk I/O routines can now run with interrupts unmasked @@ -22,9 +29,8 @@ Drives which support "Multiple Sector Mode" are identified by the kernel at boot time, and a message is displayed indicating the -largest possible setting for "MaxMult". I recommend using settings -of 8, 16, or 32. Many drives also support non-powers of two, -but many other drives do not -- try strange values at your own risk! +largest possible setting for "MaxMult" (max sector count for +"Multiple Sector Mode"). For more detailed boot-time information about your drive, change the definition of VERBOSE_DRIVE_INFO from 0 to 1 near the top @@ -34,12 +40,16 @@ correctly, and data corruption may occur.. but if you wait long enough the error recovery logic *should* be able to recover eventually. +I recommend using settings of 8, 16, or 32. Many drives also support +non-powers of two, but other drives do not -- try strange values at +your own risk! + To try this out more safely, mount the drive's partitions read-only before using hdparm (see below) for the first time. If it doesn't work, email me (mlord@bnr.ca) with the drive name as displayed at boot time, so I can warn others and possibly add a hook to the code. -To enable the features, a small program is included: hdparm.c +To enable the features, a small program is included below: hdparm.c This one is *different* from previous versions -- be sure to recompile it! Compile this using cc -O -o /usr/bin/hdparm hdparm.c @@ -96,3 +106,54 @@ Enjoy, mlord@bnr.ca + +**** CUT HERE for hdparm.c **** + +/* make using: cc -O -o /usr/bin/hdparm hdparm.c */ + +#include +#include +#include +#include +#include +#include + +/* extern int hd_ioctl(struct inode * inode, struct file * file, + * unsigned int cmd, unsigned long arg); + */ + + +void main (int argc, char *argv[]) +{ + int fd, mrc, irc; + static long mcount, irqmode; + + if (argc != 4 && argc != 2) { + fprintf(stderr,"Usage: %s " + " [ ]\n", *argv); + exit (1); + } + + fd = open (*++argv, O_RDONLY); + if (fd < 0) { + printf ("open failed - '%s' - %d\n", *argv, fd); + exit(1); + } + if (argc == 4) { + mcount = atoi(*++argv); + mrc = ioctl (fd, HDIO_SETMULTCOUNT, &mcount); + /* note that the new mcount does not take effect + until the next disk I/O operation, so if we were + to query it before then, the old value will show. + Also, the drive may reject the new value, which will + result in multiple mode being turned OFF completely! */ + irqmode = atoi(*++argv); + irc = ioctl (fd, HDIO_SETUNMASKINTR, &irqmode); + } + else { + mrc = ioctl (fd, HDIO_GETMULTCOUNT, &mcount); + irc = ioctl (fd, HDIO_GETUNMASKINTR, &irqmode); + } + printf("MultModeCount=%d, rc=%d\n", mcount, mrc); + printf("unmask=%d, rc=%d\n", irqmode, irc); +} diff -u --recursive --new-file v1.1.36/linux/drivers/block/blk.h linux/drivers/block/blk.h --- v1.1.36/linux/drivers/block/blk.h Mon Jul 18 14:48:28 1994 +++ linux/drivers/block/blk.h Tue Jul 26 21:25:31 1994 @@ -287,7 +287,8 @@ if ((bh = req->bh) != NULL) { req->bh = bh->b_reqnext; bh->b_reqnext = NULL; - bh->b_uptodate = uptodate; + bh->b_uptodate = uptodate; + if (!uptodate) bh->b_req = 0; /* So no "Weird" errors */ unlock_buffer(bh); if ((bh = req->bh) != NULL) { req->current_nr_sectors = bh->b_size >> 9; diff -u --recursive --new-file v1.1.36/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v1.1.36/linux/drivers/block/hd.c Fri Jul 22 16:41:00 1994 +++ linux/drivers/block/hd.c Wed Jul 27 11:10:18 1994 @@ -16,6 +16,9 @@ * in the early extended-partition checks and added DM partitions * * IDE IRQ-unmask & drive-id & multiple-mode code added by Mark Lord. + * + * Support for E-IDE BIOS drive geometry translation added by Mark Lord. + * -- hd.c no longer chokes on E-IDE drives with "more than 16 heads". */ #define DEFAULT_MULT_COUNT 0 /* set to 0 to disable multiple mode at boot */ @@ -80,10 +83,12 @@ unsigned int head,sect,cyl,wpcom,lzone,ctl; }; #ifdef HD_TYPE -struct hd_i_struct hd_info[] = { HD_TYPE }; +static struct hd_i_struct hd_info[] = { HD_TYPE }; +struct hd_i_struct bios_info[] = { HD_TYPE }; static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); #else -struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; +static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; +struct hd_i_struct bios_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; static int NR_HD = 0; #endif @@ -113,14 +118,14 @@ if (ints[0] != 3) return; - if (hd_info[0].head != 0) + if (bios_info[0].head != 0) hdind=1; - hd_info[hdind].head = ints[2]; - hd_info[hdind].sect = ints[3]; - hd_info[hdind].cyl = ints[1]; - hd_info[hdind].wpcom = 0; - hd_info[hdind].lzone = ints[1]; - hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); + bios_info[hdind].head = hd_info[hdind].head = ints[2]; + bios_info[hdind].sect = hd_info[hdind].sect = ints[3]; + bios_info[hdind].cyl = hd_info[hdind].cyl = ints[1]; + bios_info[hdind].wpcom = hd_info[hdind].wpcom = 0; + bios_info[hdind].lzone = hd_info[hdind].lzone = ints[1]; + bios_info[hdind].ctl = hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); NR_HD = hdind+1; } @@ -270,7 +275,7 @@ printk ("\n Config={"); for (i=0; i<=15; i++) if (ib[0] & (1<>1, max_mult[dev]); + if (ib[53]&1 && ib[54] && ib[55] && ib[56]) { + /* + * Extract the physical drive geometry for our use. + * Note that we purposely do *not* update the bios_info. + * This way, programs that use it (like fdisk) will + * still have the same logical view as the BIOS does, + * which keeps the partition table from being screwed. + */ + hd_info[dev].cyl = ib[54]; + hd_info[dev].head = ib[55]; + hd_info[dev].sect = ib[56]; + } + printk (" (%dMB IDE w/%dKB Cache, MaxMult=%d, CHS=%d/%d/%d)\n", + ib[1]*ib[3]*ib[6] / 2048, ib[21]>>1, max_mult[dev], + hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect); insw(HD_DATA,(char *)ib,64); /* flush remaining 384 ID bytes */ insw(HD_DATA,(char *)ib,64); insw(HD_DATA,(char *)ib,64); @@ -449,10 +467,11 @@ static void read_intr(void) { unsigned int dev = DEVICE_NR(CURRENT->dev); - int i, retries = 100000, msect, nsect; + int i, retries = 100000, msect = mult_count[dev], nsect; if (unmask_intr[dev]) sti(); /* permit other IRQs during xfer */ +read_next: do { i = (unsigned) inb_p(HD_STATUS); if (i & BUSY_STAT) @@ -473,8 +492,6 @@ hd_request(); return; ok_to_read: - msect = mult_count[dev]; -read_next: if (msect) { if ((nsect = CURRENT->current_nr_sectors) > msect) nsect = msect; @@ -717,6 +734,11 @@ goto repeat; return; } + if (hd_info[dev].head > 16) { + printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); + end_request(0); + goto repeat; + } if (CURRENT->cmd == READ) { unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ; hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr); @@ -781,11 +803,11 @@ err = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); if (err) return err; - put_fs_byte(hd_info[dev].head, + put_fs_byte(bios_info[dev].head, (char *) &loc->heads); - put_fs_byte(hd_info[dev].sect, + put_fs_byte(bios_info[dev].sect, (char *) &loc->sectors); - put_fs_word(hd_info[dev].cyl, + put_fs_word(bios_info[dev].cyl, (short *) &loc->cylinders); put_fs_long(hd[MINOR(inode->i_rdev)].start_sect, (long *) &loc->start); @@ -815,6 +837,8 @@ return revalidate_hddisk(inode->i_rdev, 1); case HDIO_SETUNMASKINTR: + if (!suser()) return -EACCES; + if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL; if (!arg) return -EINVAL; err = verify_area(VERIFY_READ, (long *) arg, sizeof(long)); if (err) @@ -841,7 +865,9 @@ case HDIO_SETMULTCOUNT: { unsigned long flags; + if (!suser()) return -EACCES; if (!arg) return -EINVAL; + if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL; err = verify_area(VERIFY_READ, (long *) arg, sizeof(long)); if (err) return err; @@ -903,7 +929,7 @@ hd, /* hd struct */ hd_sizes, /* block sizes */ 0, /* number */ - (void *) hd_info, /* internal */ + (void *) bios_info, /* internal */ NULL /* next */ }; @@ -944,12 +970,12 @@ if (!NR_HD) { for (drive=0 ; drive<2 ; drive++) { - hd_info[drive].cyl = *(unsigned short *) BIOS; - hd_info[drive].head = *(2+BIOS); - hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); - hd_info[drive].ctl = *(8+BIOS); - hd_info[drive].lzone = *(unsigned short *) (12+BIOS); - hd_info[drive].sect = *(14+BIOS); + bios_info[drive].cyl = hd_info[drive].cyl = *(unsigned short *) BIOS; + bios_info[drive].head = hd_info[drive].head = *(2+BIOS); + bios_info[drive].wpcom = hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); + bios_info[drive].ctl = hd_info[drive].ctl = *(8+BIOS); + bios_info[drive].lzone = hd_info[drive].lzone = *(unsigned short *) (12+BIOS); + bios_info[drive].sect = hd_info[drive].sect = *(14+BIOS); #ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp if (hd_info[drive].cyl && NR_HD == drive) NR_HD++; @@ -988,19 +1014,23 @@ i = NR_HD; while (i-- > 0) { hd[i<<6].nr_sects = 0; - if (hd_info[i].head > 16) { - printk("hd.c: ST-506 interface disk with more than 16 heads detected,\n"); - printk(" probably due to non-standard sector translation. Giving up.\n"); - printk(" (disk %d: cyl=%d, sect=%d, head=%d)\n", i, - hd_info[i].cyl, - hd_info[i].sect, - hd_info[i].head); - if (i+1 == NR_HD) - NR_HD--; - continue; + if (bios_info[i].head > 16) { + /* + * The newer E-IDE BIOSs handle drives larger than 1024 + * cylinders by increasing the number of logical heads + * to keep the number of logical cylinders below the + * sacred INT13 limit of 1024 (10 bits). If that is + * what's happening here, we'll find out and correct + * it later when "identifying" the drive. + */ + printk("hd.c: IDE/ST-506 disk with more than 16 heads detected.\n"); + printk(" (hd%c: cyl=%d, sect=%d, head=%d)\n", i+'a', + bios_info[i].cyl, + bios_info[i].sect, + bios_info[i].head); } - hd[i<<6].nr_sects = hd_info[i].head* - hd_info[i].sect*hd_info[i].cyl; + hd[i<<6].nr_sects = bios_info[i].head * + bios_info[i].sect * bios_info[i].cyl; } if (NR_HD) { if (irqaction(HD_IRQ,&hd_sigaction)) { @@ -1043,7 +1073,7 @@ #define DEVICE_BUSY busy[target] #define USAGE access_count[target] -#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl) +#define CAPACITY (bios_info[target].head*bios_info[target].sect*bios_info[target].cyl) /* We assume that the the bios parameters do not change, so the disk capacity will not change */ #undef MAYBE_REINIT diff -u --recursive --new-file v1.1.36/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v1.1.36/linux/drivers/char/mem.c Tue Jul 26 21:39:44 1994 +++ linux/drivers/char/mem.c Thu Jul 28 09:04:21 1994 @@ -93,8 +93,6 @@ return -EAGAIN; vma->vm_inode = inode; inode->i_count++; - insert_vm_struct(current, vma); - merge_segments(current->mm->mmap); return 0; } @@ -167,8 +165,6 @@ return -EINVAL; if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; - insert_vm_struct(current, vma); - merge_segments(current->mm->mmap); return 0; } diff -u --recursive --new-file v1.1.36/linux/drivers/char/psaux.c linux/drivers/char/psaux.c --- v1.1.36/linux/drivers/char/psaux.c Thu Feb 17 09:15:19 1994 +++ linux/drivers/char/psaux.c Tue Jul 26 20:59:12 1994 @@ -25,11 +25,11 @@ /* #define INITIALIZE_DEVICE */ -#include #include #include #include #include +#include #include #include diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v1.1.36/linux/drivers/scsi/aha1542.c Thu Jul 14 00:48:22 1994 +++ linux/drivers/scsi/aha1542.c Tue Jul 26 21:25:33 1994 @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -90,6 +92,20 @@ } \ } +/* Similar to WAIT, except we use the udelay call to regulate the + amount of time we wait. */ +#define WAITd(port, mask, allof, noneof, timeout) \ + { register WAITbits; \ + register WAITtimeout = timeout; \ + while (1) { \ + WAITbits = inb(port) & (mask); \ + if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ + break; \ + udelay(1000); \ + if (--WAITtimeout == 0) goto fail; \ + } \ + } + static void aha1542_stat(void) { /* int s = inb(STATUS), i = inb(INTRFLAGS); @@ -145,6 +161,24 @@ return 1; } +/* Similar to aha1542_in, except that we wait a very short period of time. + We use this if we know the board is alive and awake, but we are not sure + if the board will respond the the command we are about to send or not */ +static int aha1542_in1(unsigned int base, unchar *cmdp, int len) +{ + cli(); + while (len--) + { + WAITd(STATUS(base), DF, DF, 0, 100); + *cmdp++ = inb(DATA(base)); + } + sti(); + return 0; + fail: + sti(); + return 1; +} + static int makecode(unsigned hosterr, unsigned scsierr) { switch (hosterr) { @@ -718,8 +752,9 @@ mbenable_cmd[0]=CMD_EXTBIOS; aha1542_out(base,mbenable_cmd,1); - aha1542_in(base,mbenable_result,2); - WAIT(INTRFLAGS(base),INTRMASK,HACC,0); + if(aha1542_in1(base,mbenable_result,2)) + return retval; + WAITd(INTRFLAGS(base),INTRMASK,HACC,0,100); aha1542_intr_reset(base); if ((mbenable_result[0] & 0x08) || mbenable_result[1]) { @@ -770,11 +805,11 @@ return 1; }; - /* 1542C returns 0x44, 1542CF returns 0x45 */ - if (inquiry_result[0] == 0x44 || inquiry_result[0] == 0x45) - { /* Detect 1542C */ - *transl = aha1542_mbenable(base_io); - }; + /* Always call this - boards that do not support extended bios translation + will ignore the command, and we will set the proper default */ + + *transl = aha1542_mbenable(base_io); + return 0; } diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c --- v1.1.36/linux/drivers/scsi/g_NCR5380.c Thu Jul 14 00:48:23 1994 +++ linux/drivers/scsi/g_NCR5380.c Tue Jul 26 21:25:32 1994 @@ -55,9 +55,6 @@ * $Log: generic_NCR5380.c,v $ */ -#include -#if defined(CONFIG_SCSI_GENERIC_NCR5380) -/* Standard option */ #define AUTOPROBE_IRQ #include @@ -175,5 +172,3 @@ } #include "NCR5380.c" - -#endif /* defined(CONFIG_SCSI_GENERIC_NCR5380) */ diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v1.1.36/linux/drivers/scsi/hosts.c Thu Jul 14 00:48:23 1994 +++ linux/drivers/scsi/hosts.c Tue Jul 26 21:25:31 1994 @@ -161,6 +161,7 @@ */ struct Scsi_Host * scsi_hostlist = NULL; +struct Scsi_Device_Template * scsi_devicelist; int max_scsi_hosts = 0; static int next_host = 0; @@ -223,6 +224,15 @@ return retval; } +int +scsi_register_device(struct Scsi_Device_Template * sdpnt) +{ + if(sdpnt->next) panic("Device already registered"); + sdpnt->next = scsi_devicelist; + scsi_devicelist = sdpnt; + return 0; +} + unsigned int scsi_init() { static int called = 0; @@ -263,60 +273,20 @@ } printk ("scsi : %d hosts.\n", count); - max_scsi_hosts = count; - return 0; -} - -#ifndef CONFIG_BLK_DEV_SD -unsigned long sd_init(unsigned long memory_start, unsigned long memory_end){ - return memory_start; -}; -void sd_init1(){ - return; -}; -void sd_attach(Scsi_Device * SDp){ -}; -int NR_SD=-1; -int MAX_SD=0; + /* Now attach the high level drivers */ +#ifdef CONFIG_BLK_DEV_SD + scsi_register_device(&sd_template); #endif - - -#ifndef CONFIG_BLK_DEV_SR -unsigned long sr_init(unsigned long memory_start, unsigned long memory_end){ - return memory_start; -}; -void sr_init1(){ - return; -}; -void sr_attach(Scsi_Device * SDp){ -}; -int NR_SR=-1; -int MAX_SR=0; +#ifdef CONFIG_BLK_DEV_SR + scsi_register_device(&sr_template); #endif - - -#ifndef CONFIG_CHR_DEV_ST -unsigned long st_init(unsigned long memory_start, unsigned long memory_end){ - return memory_start; -}; -void st_init1(){ - return; -}; -void st_attach(Scsi_Device * SDp){ -}; -int NR_ST=-1; -int MAX_ST=0; +#ifdef CONFIG_CHR_DEV_ST + scsi_register_device(&st_template); #endif - -#ifndef CONFIG_CHR_DEV_SG -unsigned long sg_init(unsigned long memory_start, unsigned long memory_end){ - return memory_start; -}; -void sg_init1(){ - return; -}; -void sg_attach(Scsi_Device * SDp){ -}; -int NR_SG=-1; -int MAX_SG=0; +#ifdef CONFIG_CHR_DEV_SG + scsi_register_device(&sg_template); #endif + + max_scsi_hosts = count; + return 0; +} diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- v1.1.36/linux/drivers/scsi/hosts.h Thu Jul 14 00:48:23 1994 +++ linux/drivers/scsi/hosts.h Tue Jul 26 21:25:31 1994 @@ -254,6 +254,7 @@ }; extern struct Scsi_Host * scsi_hostlist; +extern struct Scsi_Device_Template * scsi_devicelist; extern Scsi_Host_Template * scsi_hosts; @@ -278,3 +279,28 @@ #define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #endif + +struct Scsi_Device_Template +{ + struct Scsi_Device_Template * next; + char * name; + char * tag; + unsigned char scsi_type; + unsigned char major; + unsigned char nr_dev; /* Number currently attached */ + unsigned char dev_noticed; /* Number of devices detected. */ + unsigned char dev_max; /* Current size of arrays */ + unsigned blk:1; /* 0 if character device */ + int (*detect)(Scsi_Device *); /* Returns 1 if we can attach this device */ + void (*init)(void); /* Sizes arrays based upon number of devices detected */ + void (*finish)(void); /* Perform initialization after attachment */ + void (*attach)(Scsi_Device *); /* Attach devices to arrays */ + void (*detach)(Scsi_Device *); +}; + +extern struct Scsi_Device_Template sd_template; +extern struct Scsi_Device_Template st_template; +extern struct Scsi_Device_Template sr_template; +extern struct Scsi_Device_Template sg_template; + +int scsi_register_device(struct Scsi_Device_Template * sdpnt); diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.1.36/linux/drivers/scsi/scsi.c Mon Jul 18 14:48:29 1994 +++ linux/drivers/scsi/scsi.c Tue Jul 26 21:25:33 1994 @@ -64,13 +64,10 @@ /* global variables : - NR_SCSI_DEVICES is the number of SCSI devices we have detected, scsi_devices an array of these specifing the address for each (host, id, LUN) */ -int NR_SCSI_DEVICES=0; - Scsi_Device * scsi_devices = NULL; static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0}; @@ -221,6 +218,7 @@ unsigned char scsi_cmd [12]; unsigned char scsi_result [256]; Scsi_Device * SDpnt, *SDtail; + struct Scsi_Device_Template * sdtpnt; Scsi_Cmnd SCmd; ++in_scan; @@ -249,6 +247,7 @@ SDpnt->lun = lun; SDpnt->device_wait = NULL; SDpnt->next = NULL; + SDpnt->attached = 0; /* * Assume that the device will have handshaking problems, and then * fix this field later if it turns out it doesn't. @@ -381,30 +380,13 @@ if (type != -1) { + struct Scsi_Device_Template * sdtpnt; print_inquiry(scsi_result); - switch(type){ - case TYPE_TAPE: - printk("Detected scsi tape st%d at scsi%d, id %d, lun %d\n", MAX_ST, - shpnt->host_no , dev, lun); - if(NR_ST != -1) ++MAX_ST; - break; - case TYPE_ROM: - printk("Detected scsi CD-ROM sr%d at scsi%d, id %d, lun %d\n", MAX_SR, - shpnt->host_no , dev, lun); - if(NR_SR != -1) ++MAX_SR; - break; - case TYPE_DISK: - case TYPE_MOD: - printk("Detected scsi disk sd%c at scsi%d, id %d, lun %d\n", 'a'+MAX_SD, - shpnt->host_no , dev, lun); - if(NR_SD != -1) ++MAX_SD; - break; - default: - break; - }; - - if(NR_SG != -1) ++MAX_SG; - + + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->detect) SDpnt->attached += + (*sdtpnt->detect)(SDpnt); + SDpnt->scsi_level = scsi_result[2] & 0x07; if (SDpnt->scsi_level >= 2 || (SDpnt->scsi_level == 1 && @@ -483,7 +465,6 @@ scsi_devices = SDpnt; SDtail = SDpnt; - ++NR_SCSI_DEVICES; SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device)); /* Some scsi devices cannot be polled for lun != 0 due to firmware bugs */ @@ -501,15 +482,11 @@ shpnt->host_queue = NULL; /* No longer needed here */ printk("scsi : detected "); - if(NR_SD != -1) - printk("%d SCSI disk%s ", MAX_SD, (MAX_SD != 1) ? "s" : ""); - - if(NR_ST != -1) - printk("%d tape%s ", MAX_ST, (MAX_ST != 1) ? "s" : ""); - - if(NR_SR != -1) - printk("%d CD-ROM drive%s ", MAX_SR, (MAX_SR != 1) ? "s" : ""); - + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->dev_noticed && sdtpnt->name) + printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name, + (sdtpnt->dev_noticed != 1) ? "s" : ""); + printk("total.\n"); /* Last device block does not exist. Free memory. */ @@ -1756,6 +1733,7 @@ struct Scsi_Host * host = NULL; Scsi_Device * SDpnt; struct Scsi_Host * shpnt; + struct Scsi_Device_Template * sdtpnt; Scsi_Cmnd * SCpnt; #ifdef FOO_ON_YOU return; @@ -1776,29 +1754,14 @@ for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) scan_scsis(shpnt); /* scan for scsi devices */ - sd_init1(); - st_init1(); - sr_init1(); - sg_init1(); + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) { int j; SDpnt->scsi_request_fn = NULL; - switch (SDpnt->type) - { - case TYPE_TAPE : - st_attach(SDpnt); - break; - case TYPE_ROM: - sr_attach(SDpnt); - break; - case TYPE_DISK: - case TYPE_MOD: - sd_attach(SDpnt); - default: - break; - }; - sg_attach(SDpnt); + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); if(SDpnt->type != -1){ for(j=0;jhost->hostt->cmd_per_lun;j++){ SCpnt = (Scsi_Cmnd *) scsi_init_malloc(sizeof(Scsi_Cmnd)); @@ -1822,8 +1785,7 @@ }; }; - memory_start = scsi_init_memory_start; - if (NR_SD > 0 || NR_SR > 0 || NR_ST > 0) + if (scsi_devicelist) dma_sectors = 16; /* Base value we use */ for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) { @@ -1846,23 +1808,25 @@ dma_sectors = (dma_sectors + 15) & 0xfff0; dma_free_sectors = dma_sectors; /* This must be a multiple of 16 */ - memory_start = (memory_start + 3) & 0xfffffffc; - dma_malloc_freelist = (unsigned short *) memory_start; - memory_start += dma_sectors >> 3; + scsi_init_memory_start = (scsi_init_memory_start + 3) & 0xfffffffc; + dma_malloc_freelist = (unsigned short *) + scsi_init_malloc(dma_sectors >> 3); memset(dma_malloc_freelist, 0, dma_sectors >> 3); - if(memory_start & 1) memory_start++; /* Some host adapters require - buffers to be word aligned */ - dma_malloc_buffer = (unsigned char *) memory_start; - memory_start += dma_sectors << 9; - - memory_start = sd_init(memory_start, memory_end); /* init scsi disks */ - memory_start = st_init(memory_start, memory_end); /* init scsi tapes */ - memory_start = sr_init(memory_start, memory_end); /* init scsi CDROMs */ - memory_start = sg_init(memory_start, memory_end); /* init scsi generic */ + /* Some host adapters require buffers to be word aligned */ + if(scsi_init_memory_start & 1) scsi_init_memory_start++; + + dma_malloc_buffer = (unsigned char *) + scsi_init_malloc(dma_sectors << 9); + + /* OK, now we finish the initialization by doing spin-up, read + capacity, etc, etc */ + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->finish && sdtpnt->nr_dev) + (*sdtpnt->finish)(); scsi_loadable_module_flag = 1; - return memory_start; + return scsi_init_memory_start; } static void print_inquiry(unsigned char *data) diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v1.1.36/linux/drivers/scsi/scsi.h Mon Jul 18 14:48:29 1994 +++ linux/drivers/scsi/scsi.h Tue Jul 26 21:25:31 1994 @@ -260,6 +260,7 @@ typedef struct scsi_device { struct scsi_device * next; /* Used for linked list */ unsigned char id, lun; + int attached; /* # of high level drivers attached to this */ int access_count; /* Count of open channels/mounts */ struct wait_queue * device_wait; /* Used to wait if device is busy */ struct Scsi_Host * host; @@ -298,7 +299,6 @@ These are the SCSI devices available on the system. */ -extern int NR_SCSI_DEVICES; extern Scsi_Device * scsi_devices; /* Initializes all SCSI devices. This scans all scsi busses. @@ -500,22 +500,6 @@ extern int scsi_reset (Scsi_Cmnd *); extern int max_scsi_hosts; -extern int MAX_SD, NR_SD, MAX_ST, NR_ST, MAX_SR, NR_SR, NR_SG, MAX_SG; -extern unsigned long sd_init(unsigned long, unsigned long); -extern void sd_init1(void); -extern void sd_attach(Scsi_Device *); - -extern unsigned long sr_init(unsigned long, unsigned long); -extern void sr_init1(void); -extern void sr_attach(Scsi_Device *); - -extern unsigned long st_init(unsigned long, unsigned long); -extern void st_init1(void); -extern void st_attach(Scsi_Device *); - -extern unsigned long sg_init(unsigned long, unsigned long); -extern void sg_init1(void); -extern void sg_attach(Scsi_Device *); #if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR) static void end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v1.1.36/linux/drivers/scsi/sd.c Tue Jul 19 10:18:54 1994 +++ linux/drivers/scsi/sd.c Tue Jul 26 21:25:32 1994 @@ -46,8 +46,6 @@ struct hd_struct * sd; -int NR_SD=0; -int MAX_SD=0; Scsi_Disk * rscsi_disks; static int * sd_sizes; static int * sd_blocksizes; @@ -61,12 +59,22 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt); +static void sd_init(void); +static void sd_finish(void); +static void sd_attach(Scsi_Device *); +static int sd_detect(Scsi_Device *); + +struct Scsi_Device_Template sd_template = {NULL, "disk", "sd", TYPE_DISK, + SCSI_DISK_MAJOR, 0, 0, 0, 1, + sd_detect, sd_init, + sd_finish, sd_attach, NULL}; + static int sd_open(struct inode * inode, struct file * filp) { int target; target = DEVICE_NR(MINOR(inode->i_rdev)); - if(target >= NR_SD || !rscsi_disks[target].device) + if(target >= sd_template.dev_max || !rscsi_disks[target].device) return -ENXIO; /* No such device */ /* Make sure that only one process can do a check_change_disk at one time. @@ -135,9 +143,10 @@ { int i; - for (i = 0; i < NR_SD; ++i) - sd[i << 4].nr_sects = rscsi_disks[i].capacity; - sd_gendisk.nr_real = NR_SD; + for (i = 0; i < sd_template.dev_max; ++i) + if(rscsi_disks[i].device) + sd[i << 4].nr_sects = rscsi_disks[i].capacity; + sd_gendisk.nr_real = sd_template.dev_max; } /* @@ -358,7 +367,7 @@ to have the interrupts off when monkeying with the request list, because otherwise the kernel might try and slip in a request inbetween somewhere. */ - if (!SCpnt && NR_SD > 1){ + if (!SCpnt && sd_template.nr_dev > 1){ struct request *req1; req1 = NULL; cli(); @@ -410,7 +419,9 @@ printk("Doing sd request, dev = %d, block = %d\n", dev, block); #endif - if (dev >= (NR_SD << 4) || block + SCpnt->request.nr_sectors > sd[dev].nr_sects) + if (dev >= (sd_template.dev_max << 4) || + !rscsi_disks[DEVICE_NR(dev)].device || + block + SCpnt->request.nr_sectors > sd[dev].nr_sects) { end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; @@ -747,7 +758,8 @@ target = DEVICE_NR(MINOR(full_dev)); - if (target >= NR_SD) { + if (target >= sd_template.dev_max || + !rscsi_disks[target].device) { printk("SCSI disk request error: invalid device.\n"); return 0; }; @@ -957,11 +969,8 @@ rscsi_disks[i].capacity = 0; } else { printk ("scsi : deleting disk entry.\n"); - for (j=i; j < NR_SD - 1;) - rscsi_disks[j] = rscsi_disks[++j]; - --i; - --NR_SD; - scsi_free(buffer, 512); + rscsi_disks[j].device = NULL; + sd_template.nr_dev--; return i; }; } @@ -983,35 +992,55 @@ */ -unsigned long sd_init(unsigned long memory_start, unsigned long memory_end) +static void sd_init() { int i; + static int sd_registered = 0; + + if (sd_template.dev_noticed == 0) return; - if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) { - printk("Unable to get major %d for SCSI disk\n",MAJOR_NR); - return memory_start; + if(!sd_registered) { + if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) { + printk("Unable to get major %d for SCSI disk\n",MAJOR_NR); + return; + } + sd_registered++; } - if (MAX_SD == 0) return memory_start; + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; + + sd_template.dev_max = sd_template.dev_noticed; + + rscsi_disks = (Scsi_Disk *) + scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk)); - sd_sizes = (int *) memory_start; - memory_start += (MAX_SD << 4) * sizeof(int); - memset(sd_sizes, 0, (MAX_SD << 4) * sizeof(int)); - - sd_blocksizes = (int *) memory_start; - memory_start += (MAX_SD << 4) * sizeof(int); - for(i=0;i<(MAX_SD << 4);i++) sd_blocksizes[i] = 1024; + sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * + sizeof(int)); + memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int)); + + 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; blksize_size[MAJOR_NR] = sd_blocksizes; - sd = (struct hd_struct *) memory_start; - memory_start += (MAX_SD << 4) * sizeof(struct hd_struct); + sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) * + sizeof(struct hd_struct)); + - sd_gendisk.max_nr = MAX_SD; + sd_gendisk.max_nr = sd_template.dev_max; sd_gendisk.part = sd; sd_gendisk.sizes = sd_sizes; sd_gendisk.real_devices = (void *) rscsi_disks; - for (i = 0; i < NR_SD; ++i) - i = sd_init_onedisk(i); +} + +static void sd_finish() +{ + int i; + + for (i = 0; i < sd_template.dev_max; ++i) + if (rscsi_disks[i].device) i = sd_init_onedisk(i); blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; @@ -1026,17 +1055,41 @@ sd_gendisk.next = gendisk_head; gendisk_head = &sd_gendisk; - return memory_start; + return; } -void sd_init1(){ - rscsi_disks = (Scsi_Disk *) scsi_init_malloc(MAX_SD * sizeof(Scsi_Disk)); -}; +static int sd_detect(Scsi_Device * SDp){ + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return 0; + if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; + + printk("Detected scsi disk sd%c at scsi%d, id %d, lun %d\n", + 'a'+ (sd_template.dev_noticed++), + SDp->host->host_no , SDp->id, SDp->lun); + + return 1; + +} + +static void sd_attach(Scsi_Device * SDp){ + Scsi_Disk * dpnt; + int i; + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; + if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return; + + if(sd_template.nr_dev >= sd_template.dev_max) + panic ("scsi_devices corrupt (sd)"); + + for(dpnt = rscsi_disks, i=0; idevice) break; + + if(i >= sd_template.dev_max) panic ("scsi_devices corrupt (sd)"); -void sd_attach(Scsi_Device * SDp){ - SDp->scsi_request_fn = do_sd_request; - rscsi_disks[NR_SD++].device = SDp; - if(NR_SD > MAX_SD) panic ("scsi_devices corrupt (sd)"); + SDp->scsi_request_fn = do_sd_request; + rscsi_disks[i].device = SDp; + sd_template.nr_dev++; }; #define DEVICE_BUSY rscsi_disks[target].device->busy diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v1.1.36/linux/drivers/scsi/seagate.c Thu Jul 14 00:48:24 1994 +++ linux/drivers/scsi/seagate.c Tue Jul 26 21:25:32 1994 @@ -46,9 +46,7 @@ * transfer rate if handshaking isn't working correctly. */ -#include -#if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_8xx) #include #include #include @@ -1697,5 +1695,3 @@ return result; } -#endif /* defined(CONFIG_SCSI_SEGATE) */ - diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v1.1.36/linux/drivers/scsi/sg.c Thu Jul 14 00:48:25 1994 +++ linux/drivers/scsi/sg.c Tue Jul 26 21:25:31 1994 @@ -21,12 +21,20 @@ #include "../block/blk.h" #include "scsi.h" +#include "hosts.h" #include "scsi_ioctl.h" #include "sg.h" -int NR_SG=0; -int MAX_SG=0; +static void sg_init(void); +static void sg_attach(Scsi_Device *); +static int sg_detect(Scsi_Device *); + +struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", 0xff, + SCSI_GENERIC_MAJOR, 0, 0, 0, 0, + sg_detect, sg_init, + NULL, sg_attach, NULL}; + #ifdef SG_BIG_BUFF static char *big_buff; static struct wait_queue *big_wait; /* wait for buffer available */ @@ -55,7 +63,7 @@ unsigned int cmd_in, unsigned long arg) { int dev = MINOR(inode->i_rdev); - if ((dev<0) || (dev>=NR_SG)) + if ((dev<0) || (dev>=sg_template.dev_max)) return -ENXIO; switch(cmd_in) { @@ -73,7 +81,7 @@ { int dev=MINOR(inode->i_rdev); int flags=filp->f_flags; - if (dev>=NR_SG) + if (dev>=sg_template.dev_max || !scsi_generics[dev].device) return -ENXIO; if (O_RDWR!=(flags & O_ACCMODE)) return -EACCES; @@ -295,45 +303,70 @@ }; +static int sg_detect(Scsi_Device * SDp){ + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return 0; + + ++sg_template.dev_noticed; + return 1; +} + /* Driver initialization */ -unsigned long sg_init(unsigned long mem_start, unsigned long mem_end) +static void sg_init() { - if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) - { - printk("Unable to get major %d for generic SCSI device\n", - SCSI_GENERIC_MAJOR); - return mem_start; + static int sg_registered = 0; + + if (sg_template.dev_noticed == 0) return; + + if(!sg_registered) { + if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) + { + printk("Unable to get major %d for generic SCSI device\n", + SCSI_GENERIC_MAJOR); + return; + } + sg_registered++; } - if (NR_SG == 0) return mem_start; + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; #ifdef DEBUG printk("sg: Init generic device.\n"); #endif #ifdef SG_BIG_BUFF - big_buff= (char *) mem_start; - mem_start+=SG_BIG_BUFF; + big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF); #endif - return mem_start; + + scsi_generics = (struct scsi_generic *) + scsi_init_malloc(sg_template.dev_noticed * sizeof(struct scsi_generic)); + + sg_template.dev_max = sg_template.dev_noticed; } -void sg_init1() +static void sg_attach(Scsi_Device * SDp) { - scsi_generics = (struct scsi_generic *) - scsi_init_malloc(MAX_SG * sizeof(struct scsi_generic)); - }; + struct scsi_generic * gpnt; + int i; -void sg_attach(Scsi_Device * SDp) - { - if(NR_SG >= MAX_SG) - panic ("scsi_devices corrupt (sg)"); - scsi_generics[NR_SG].device=SDp; - scsi_generics[NR_SG].users=0; - scsi_generics[NR_SG].generic_wait=NULL; - scsi_generics[NR_SG].read_wait=NULL; - scsi_generics[NR_SG].write_wait=NULL; - scsi_generics[NR_SG].exclude=0; - scsi_generics[NR_SG].pending=0; - scsi_generics[NR_SG].timeout=SG_DEFAULT_TIMEOUT; - NR_SG++; + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; + + if(sg_template.nr_dev >= sg_template.dev_max) + panic ("scsi_devices corrupt (sg)"); + + for(gpnt = scsi_generics, i=0; idevice) break; + + if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)"); + + scsi_generics[i].device=SDp; + scsi_generics[i].users=0; + scsi_generics[i].generic_wait=NULL; + scsi_generics[i].read_wait=NULL; + scsi_generics[i].write_wait=NULL; + scsi_generics[i].exclude=0; + scsi_generics[i].pending=0; + scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT; + sg_template.nr_dev++; }; diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.1.36/linux/drivers/scsi/sr.c Fri Jul 22 16:41:01 1994 +++ linux/drivers/scsi/sr.c Tue Jul 26 21:25:32 1994 @@ -29,11 +29,19 @@ #include "scsi_ioctl.h" /* For the door lock/unlock commands */ #include "constants.h" -#define MAX_RETRIES 1 -#define SR_TIMEOUT 500 +#define MAX_RETRIES 3 +#define SR_TIMEOUT 5000 -int NR_SR=0; -int MAX_SR=0; +static void sr_init(void); +static void sr_finish(void); +static void sr_attach(Scsi_Device *); +static int sr_detect(Scsi_Device *); + +struct Scsi_Device_Template sr_template = {NULL, "cdrom", "sr", TYPE_ROM, + SCSI_CDROM_MAJOR, 0, 0, 0, 1, + sr_detect, sr_init, + sr_finish, sr_attach, NULL}; + Scsi_CD * scsi_CDs; static int * sr_sizes; @@ -88,7 +96,7 @@ target = MINOR(full_dev); - if (target >= NR_SR) { + if (target >= sr_template.nr_dev) { printk("CD-ROM request error: invalid device.\n"); return 0; }; @@ -265,7 +273,7 @@ static int sr_open(struct inode * inode, struct file * filp) { - if(MINOR(inode->i_rdev) >= NR_SR || + if(MINOR(inode->i_rdev) >= sr_template.nr_dev || !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENXIO; /* No such device */ if (filp->f_mode & 2) @@ -305,7 +313,7 @@ sti(); return; }; - + INIT_SCSI_REQUEST; if (flag++ == 0) @@ -321,7 +329,7 @@ to have the interrupts off when monkeying with the request list, because otherwise the kernel might try and slip in a request inbetween somewhere. */ - if (!SCpnt && NR_SR > 1){ + if (!SCpnt && sr_template.nr_dev > 1){ struct request *req1; req1 = NULL; cli(); @@ -371,7 +379,7 @@ buffer = NULL; this_count = 0; - if (dev >= NR_SR) + if (dev >= sr_template.nr_dev) { /* printk("CD-ROM request error: invalid device.\n"); */ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); @@ -596,45 +604,73 @@ } else { - if (realcount > 0xff) - { - realcount = 0xff; - this_count = realcount * (scsi_CDs[dev].sector_size >> 9); - } - - cmd[1] |= (unsigned char) ((block >> 16) & 0x1f); - cmd[2] = (unsigned char) ((block >> 8) & 0xff); - cmd[3] = (unsigned char) block & 0xff; - cmd[4] = (unsigned char) realcount; - cmd[5] = 0; + if (realcount > 0xff) + { + realcount = 0xff; + this_count = realcount * (scsi_CDs[dev].sector_size >> 9); + } + + cmd[1] |= (unsigned char) ((block >> 16) & 0x1f); + cmd[2] = (unsigned char) ((block >> 8) & 0xff); + cmd[3] = (unsigned char) block & 0xff; + cmd[4] = (unsigned char) realcount; + cmd[5] = 0; } #ifdef DEBUG -{ - int i; - printk("ReadCD: %d %d %d %d\n",block, realcount, buffer, this_count); - printk("Use sg: %d\n", SCpnt->use_sg); - printk("Dumping command: "); - for(i=0; i<12; i++) printk("%2.2x ", cmd[i]); - printk("\n"); -}; + { + int i; + printk("ReadCD: %d %d %d %d\n",block, realcount, buffer, this_count); + printk("Use sg: %d\n", SCpnt->use_sg); + printk("Dumping command: "); + for(i=0; i<12; i++) printk("%2.2x ", cmd[i]); + printk("\n"); + }; #endif - + SCpnt->this_count = this_count; scsi_do_cmd (SCpnt, (void *) cmd, buffer, realcount * scsi_CDs[dev].sector_size, rw_intr, SR_TIMEOUT, MAX_RETRIES); } -void sr_init1(){ - scsi_CDs = (Scsi_CD *) scsi_init_malloc(MAX_SR * sizeof(Scsi_CD)); -}; +static int sr_detect(Scsi_Device * SDp){ + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return 0; + if(SDp->type != TYPE_ROM && SDp->type != TYPE_WORM) return 0; + + printk("Detected scsi CD-ROM sr%d at scsi%d, id %d, lun %d\n", + ++sr_template.dev_noticed, + SDp->host->host_no , SDp->id, SDp->lun); + + return 1; +} -void sr_attach(Scsi_Device * SDp){ +static void sr_attach(Scsi_Device * SDp){ + Scsi_CD * cpnt; + int i; + + /* We do not support attaching loadable devices yet. */ + + if(scsi_loadable_module_flag) return; + if(SDp->type != TYPE_ROM && SDp->type != TYPE_WORM) return; + + if (sr_template.nr_dev >= sr_template.dev_max) + panic ("scsi_devices corrupt (sr)"); + + for(cpnt = scsi_CDs, i=0; idevice) break; + + if(i >= sr_template.dev_max) panic ("scsi_devices corrupt (sr)"); + SDp->scsi_request_fn = do_sr_request; - scsi_CDs[NR_SR++].device = SDp; - if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)"); -}; + scsi_CDs[i].device = SDp; + sr_template.nr_dev++; + if(sr_template.nr_dev > sr_template.dev_max) + panic ("scsi_devices corrupt (sr)"); +} + static void sr_init_done (Scsi_Cmnd * SCpnt) { @@ -713,26 +749,41 @@ }; } -unsigned long sr_init(unsigned long memory_start, unsigned long memory_end) +static void sr_init() { int i; + static int sr_registered = 0; - if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) { - printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR); - return memory_start; + if(sr_template.dev_noticed == 0) return; + + if(!sr_registered) { + if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) { + printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR); + return; + } } - if(MAX_SR == 0) return memory_start; + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; + + sr_template.dev_max = sr_template.dev_noticed; + scsi_CDs = (Scsi_CD *) scsi_init_malloc(sr_template.dev_max * sizeof(Scsi_CD)); + + sr_sizes = (int *) scsi_init_malloc(sr_template.dev_max * sizeof(int)); + memset(sr_sizes, 0, sr_template.dev_max * sizeof(int)); - sr_sizes = (int *) memory_start; - memory_start += MAX_SR * sizeof(int); - memset(sr_sizes, 0, MAX_SR * sizeof(int)); - - sr_blocksizes = (int *) memory_start; - memory_start += MAX_SR * sizeof(int); - for(i=0;i= NR_SR) return -ENXIO; + + if (target >= sr_template.nr_dev || + !scsi_CDs[target].device) return -ENXIO; switch (cmd) { diff -u --recursive --new-file v1.1.36/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v1.1.36/linux/drivers/scsi/st.c Thu Jul 14 00:48:25 1994 +++ linux/drivers/scsi/st.c Tue Jul 26 21:25:32 1994 @@ -28,6 +28,7 @@ #define MAJOR_NR SCSI_TAPE_MAJOR #include "../block/blk.h" #include "scsi.h" +#include "hosts.h" #include "scsi_ioctl.h" #include "st.h" #include "constants.h" @@ -83,9 +84,16 @@ static int st_max_buffers = ST_MAX_BUFFERS; static Scsi_Tape * scsi_tapes; -int NR_ST=0; -int MAX_ST=0; +static void st_init(void); +static void st_attach(Scsi_Device *); +static int st_detect(Scsi_Device *); + +struct Scsi_Device_Template st_template = {NULL, "tape", "st", TYPE_TAPE, + SCSI_TAPE_MAJOR, 0, 0, 0, 0, + st_detect, st_init, + NULL, st_attach, NULL}; + static int st_int_ioctl(struct inode * inode,struct file * file, unsigned int cmd_in, unsigned long arg); @@ -146,7 +154,7 @@ int st_nbr, remainder; Scsi_Tape * STp; - if ((st_nbr = SCpnt->request.dev) < NR_ST && st_nbr >= 0) { + if ((st_nbr = SCpnt->request.dev) < st_template.nr_dev && st_nbr >= 0) { STp = &(scsi_tapes[st_nbr]); if ((STp->buffer)->writing && (SCpnt->sense_buffer[0] & 0x70) == 0x70 && @@ -381,7 +389,7 @@ Scsi_Tape * STp; dev = MINOR(inode->i_rdev) & 127; - if (dev >= NR_ST) + if (dev >= st_template.dev_max || !scsi_tapes[dev].device) return (-ENXIO); STp = &(scsi_tapes[dev]); if (STp->in_use) { @@ -1677,34 +1685,70 @@ NULL /* fsync */ }; -void st_attach(Scsi_Device * SDp){ - scsi_tapes[NR_ST++].device = SDp; - if(NR_ST > MAX_ST) panic ("scsi_devices corrupt (st)"); -}; +static void st_attach(Scsi_Device * SDp){ + Scsi_Tape * tpnt; + int i; + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; + if(SDp->type != TYPE_TAPE) return; + + if(st_template.nr_dev >= st_template.dev_max) + panic ("scsi_devices corrupt (st)"); -void st_init1(){ - scsi_tapes = (Scsi_Tape *) scsi_init_malloc(MAX_ST * sizeof(Scsi_Tape)); + for(tpnt = scsi_tapes, i=0; idevice) break; + + if(i >= st_template.dev_max) panic ("scsi_devices corrupt (st)"); + + scsi_tapes[i].device = SDp; + st_template.nr_dev++; }; +static int st_detect(Scsi_Device * SDp){ + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return 0; + if(SDp->type != TYPE_TAPE) return 0; + + printk("Detected scsi tape st%d at scsi%d, id %d, lun %d\n", + ++st_template.dev_noticed, + SDp->host->host_no , SDp->id, SDp->lun); + + return 1; +} + /* Driver initialization */ -unsigned long st_init(unsigned long mem_start, unsigned long mem_end) +static void st_init() { int i; Scsi_Tape * STp; Scsi_Device * SDp; + static int st_registered = 0; + + if (st_template.dev_noticed == 0) return; - if (register_chrdev(MAJOR_NR,"st",&st_fops)) { - printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR); - return mem_start; + if(!st_registered) { + if (register_chrdev(MAJOR_NR,"st",&st_fops)) { + printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR); + return; + } + st_registered++; } - if (NR_ST == 0) return mem_start; + + /* We do not support attaching loadable devices yet. */ + if(scsi_loadable_module_flag) return; + scsi_tapes = (Scsi_Tape *) scsi_init_malloc(st_template.dev_noticed * + sizeof(Scsi_Tape)); + st_template.dev_max = st_template.dev_noticed; + #ifdef DEBUG printk("st: Buffer size %d bytes, write threshold %d bytes.\n", st_buffer_size, st_write_threshold); #endif - for (i=0, SDp = scsi_devices; i < NR_ST; ++i) { + for (i=0, SDp = scsi_devices; i < st_template.dev_noticed; ++i) { STp = &(scsi_tapes[i]); STp->capacity = 0xfffff; STp->dirty = 0; @@ -1721,8 +1765,7 @@ STp->write_threshold = st_write_threshold; STp->drv_block = 0; STp->moves_after_eof = 1; - STp->mt_status = (struct mtget *) mem_start; - mem_start += sizeof(struct mtget); + STp->mt_status = (struct mtget *) scsi_init_malloc(sizeof(struct mtget)); /* Initialize status */ memset((void *) scsi_tapes[i].mt_status, 0, sizeof(struct mtget)); for (; SDp; SDp = SDp->next) @@ -1740,20 +1783,19 @@ } /* Allocate the buffers */ - st_nbr_buffers = NR_ST; + st_nbr_buffers = st_template.dev_noticed; if (st_nbr_buffers > st_max_buffers) st_nbr_buffers = st_max_buffers; - st_buffers = (ST_buffer **)mem_start; - mem_start += st_nbr_buffers * sizeof(ST_buffer *); + st_buffers = (ST_buffer **) scsi_init_malloc(st_nbr_buffers * + sizeof(ST_buffer *)); for (i=0; i < st_nbr_buffers; i++) { - st_buffers[i] = (ST_buffer *) mem_start; + st_buffers[i] = (ST_buffer *) scsi_init_malloc(sizeof(ST_buffer) - + 1 + st_buffer_size); #ifdef DEBUG /* printk("st: Buffer address: %p\n", st_buffers[i]); */ #endif - mem_start += sizeof(ST_buffer) - 1 + st_buffer_size; st_buffers[i]->in_use = 0; st_buffers[i]->writing = 0; } - - return mem_start; + return; } diff -u --recursive --new-file v1.1.36/linux/fs/Makefile linux/fs/Makefile --- v1.1.36/linux/fs/Makefile Mon Jul 25 17:56:39 1994 +++ linux/fs/Makefile Thu Jul 28 15:56:35 1994 @@ -52,7 +52,7 @@ OBJS= open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \ block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \ - select.o fifo.o locks.o filesystems.o $(BINFMTS) + select.o fifo.o locks.o filesystems.o dcache.o $(BINFMTS) all: fs.o filesystems.a diff -u --recursive --new-file v1.1.36/linux/fs/dcache.c linux/fs/dcache.c --- v1.1.36/linux/fs/dcache.c Thu Jan 1 02:00:00 1970 +++ linux/fs/dcache.c Fri Jul 29 15:25:33 1994 @@ -0,0 +1,251 @@ +/* + * linux/fs/dcache.c + * + * (C) Copyright 1994 Linus Torvalds + */ + +/* + * The directory cache is a "two-level" cache, each level doing LRU on + * its entries. Adding new entries puts them at the end of the LRU + * queue on the first-level cache, while the second-level cache is + * fed by any cache hits. + * + * The idea is that new additions (from readdir(), for example) will not + * flush the cache of entries that have really been used. + * + * There is a global hash-table over both caches that hashes the entries + * based on the directory inode number and device as well as on a + * string-hash computed over the name. + */ + +#include + +#include +#include + +/* + * Don't bother caching long names.. They just take up space in the cache, and + * for a name cache you just want to cache the "normal" names anyway which tend + * to be short. + */ +#define DCACHE_NAME_LEN 15 +#define DCACHE_SIZE 64 + +struct hash_list { + struct dir_cache_entry * next; + struct dir_cache_entry * prev; +}; + +/* + * The dir_cache_entry must be in this order: we do ugly things with the pointers + */ +struct dir_cache_entry { + struct hash_list h; + unsigned long dev; + unsigned long dir; + unsigned long version; + unsigned long ino; + unsigned char name_len; + char name[DCACHE_NAME_LEN]; + struct dir_cache_entry ** lru_head; + struct dir_cache_entry * next_lru, * prev_lru; +}; + +#define COPYDATA(de, newde) \ +memcpy((void *) &newde->dev, (void *) &de->dev, \ +4*sizeof(unsigned long) + 1 + DCACHE_NAME_LEN) + +static struct dir_cache_entry level1_cache[DCACHE_SIZE]; +static struct dir_cache_entry level2_cache[DCACHE_SIZE]; + +/* + * The LRU-lists are doubly-linked circular lists, and do not change in size + * so these pointers always have something to point to (after _init) + */ +static struct dir_cache_entry * level1_head; +static struct dir_cache_entry * level2_head; + +/* + * The hash-queues are also doubly-linked circular lists, but the head is + * itself on the doubly-linked list, not just a pointer to the first entry. + */ +#define DCACHE_HASH_QUEUES 19 +#define hash_fn(dev,dir,namehash) (((dev) ^ (dir) ^ (namehash)) % DCACHE_HASH_QUEUES) + +static struct hash_list hash_table[DCACHE_HASH_QUEUES]; + +static inline void remove_lru(struct dir_cache_entry * de) +{ + de->next_lru->prev_lru = de->prev_lru; + de->prev_lru->next_lru = de->next_lru; +} + +static inline void add_lru(struct dir_cache_entry * de, struct dir_cache_entry *head) +{ + de->next_lru = head; + de->prev_lru = head->prev_lru; + de->prev_lru->next_lru = de; + head->prev_lru = de; +} + +static inline void update_lru(struct dir_cache_entry * de) +{ + if (de == *de->lru_head) + *de->lru_head = de->next_lru; + else { + remove_lru(de); + add_lru(de,*de->lru_head); + } +} + +/* + * Stupid name"hash" algorithm. Write something better if you want to, + * but I doubt it matters that much + */ +static inline unsigned long namehash(const char * name, int len) +{ + return len * *(unsigned char *) name; +} + +/* + * Hash queue manipulation. Look out for the casts.. + */ +static inline void remove_hash(struct dir_cache_entry * de) +{ + if (de->h.next) { + de->h.next->h.prev = de->h.prev; + de->h.prev->h.next = de->h.next; + de->h.next = NULL; + } +} + +static inline void add_hash(struct dir_cache_entry * de, struct hash_list * hash) +{ + de->h.next = hash->next; + de->h.prev = (struct dir_cache_entry *) hash; + hash->next->h.prev = de; + hash->next = de; +} + +/* + * Find a directory cache entry given all the necessary info. + */ +static struct dir_cache_entry * find_entry(struct inode * dir, const char * name, int len, struct hash_list * hash) +{ + struct dir_cache_entry * de = hash->next; + + for (de = hash->next ; de != (struct dir_cache_entry *) hash ; de = de->h.next) { + if (de->dev != dir->i_dev) + continue; + if (de->dir != dir->i_ino) + continue; + if (de->version != dir->i_version) + continue; + if (de->name_len != len) + continue; + if (memcmp(de->name, name, len)) + continue; + return de; + } + return NULL; +} + +/* + * Move a successfully used entry to level2. If already at level2, + * move it to the end of the LRU queue.. + */ +static inline void move_to_level2(struct dir_cache_entry * old_de, struct hash_list * hash) +{ + struct dir_cache_entry * de; + + if (old_de->lru_head == &level2_head) { + update_lru(old_de); + return; + } + de = level2_head; + level2_head = de->next_lru; + remove_hash(de); + COPYDATA(old_de, de); + add_hash(de, hash); +} + +unsigned long dcache_lookup(struct inode * dir, const char * name, int len) +{ + struct hash_list * hash; + struct dir_cache_entry *de; + + if (len > DCACHE_NAME_LEN) + return 0; + hash = hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name,len)); + de = find_entry(dir, name, len, hash); + if (!de) + return 0; + move_to_level2(de, hash); + return de->ino; +} + +void dcache_add(struct inode * dir, const char * name, int len, unsigned long ino) +{ + struct hash_list * hash; + struct dir_cache_entry *de; + + if (len > DCACHE_NAME_LEN) + return; + hash = hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name,len)); + if ((de = find_entry(dir, name, len, hash)) != NULL) { + update_lru(de); + return; + } + de = level1_head; + level1_head = de->next_lru; + remove_hash(de); + de->dev = dir->i_dev; + de->dir = dir->i_ino; + de->version = dir->i_version; + de->ino = ino; + de->name_len = len; + memcpy(de->name, name, len); + add_hash(de, hash); +} + +unsigned long name_cache_init(unsigned long mem_start, unsigned long mem_end) +{ + int i; + struct dir_cache_entry * p; + + /* + * Init level1 LRU lists.. + */ + p = level1_cache; + do { + p[1].prev_lru = p; + p[0].next_lru = p+1; + p[0].lru_head = &level1_head; + } while (++p < level1_cache + DCACHE_SIZE-1); + level1_cache[0].prev_lru = p; + p[0].next_lru = &level1_cache[0]; + p[0].lru_head = &level1_head; + level1_head = level1_cache; + + /* + * Init level2 LRU lists.. + */ + p = level2_cache; + do { + p[1].prev_lru = p; + p[0].next_lru = p+1; + p[0].lru_head = &level2_head; + } while (++p < level2_cache + DCACHE_SIZE-1); + level2_cache[0].prev_lru = p; + p[0].next_lru = &level2_cache[0]; + p[0].lru_head = &level2_head; + level2_head = level2_cache; + + /* + * Empty hash queues.. + */ + for (i = 0 ; i < DCACHE_HASH_QUEUES ; i++) + hash_table[i].next = hash_table[i].next = + (struct dir_cache_entry *) &hash_table[i]; + return mem_start; +} diff -u --recursive --new-file v1.1.36/linux/fs/ext2/Makefile linux/fs/ext2/Makefile --- v1.1.36/linux/fs/ext2/Makefile Wed Dec 1 14:44:15 1993 +++ linux/fs/ext2/Makefile Fri Jul 29 14:35:03 1994 @@ -14,8 +14,8 @@ .s.o: $(AS) -o $*.o $< -OBJS= acl.o balloc.o bitmap.o dcache.o dir.o file.o fsync.o \ - ialloc.o inode.o ioctl.o namei.o super.o symlink.o truncate.o +OBJS= acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o \ + inode.o ioctl.o namei.o super.o symlink.o truncate.o ext2.o: $(OBJS) $(LD) -r -o ext2.o $(OBJS) Only in v1.1.36/linux/fs/ext2: dcache.c diff -u --recursive --new-file v1.1.36/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v1.1.36/linux/fs/ext2/dir.c Sun Jan 9 16:47:21 1994 +++ linux/fs/ext2/dir.c Fri Jul 29 11:54:43 1994 @@ -144,11 +144,8 @@ put_fs_long (de->inode, &dirent->d_ino); put_fs_byte (0, de->name_len + dirent->d_name); put_fs_word (de->name_len, &dirent->d_reclen); -#ifndef DONT_USE_DCACHE - ext2_dcache_add (inode->i_dev, inode->i_ino, - de->name, de->name_len, + dcache_add(inode, de->name, de->name_len, de->inode); -#endif i = de->name_len; brelse (bh); if (!IS_RDONLY(inode)) { diff -u --recursive --new-file v1.1.36/linux/fs/ext2/inode.c linux/fs/ext2/inode.c --- v1.1.36/linux/fs/ext2/inode.c Tue Apr 19 10:53:22 1994 +++ linux/fs/ext2/inode.c Fri Jul 29 12:36:17 1994 @@ -538,6 +538,7 @@ inode->u.ext2_i.i_dtime = raw_inode->i_dtime; inode->i_blksize = inode->i_sb->s_blocksize; inode->i_blocks = raw_inode->i_blocks; + inode->i_version = ++event; inode->u.ext2_i.i_flags = raw_inode->i_flags; inode->u.ext2_i.i_faddr = raw_inode->i_faddr; inode->u.ext2_i.i_frag = raw_inode->i_frag; diff -u --recursive --new-file v1.1.36/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v1.1.36/linux/fs/ext2/namei.c Tue Jul 19 10:19:13 1994 +++ linux/fs/ext2/namei.c Fri Jul 29 14:35:40 1994 @@ -181,22 +181,15 @@ iput (dir); return -ENOENT; } -#ifndef DONT_USE_DCACHE - if (!(ino = ext2_dcache_lookup (dir->i_dev, dir->i_ino, name, len))) { -#endif + if (!(ino = dcache_lookup(dir, name, len))) { if (!(bh = ext2_find_entry (dir, name, len, &de))) { iput (dir); return -ENOENT; } ino = de->inode; -#ifndef DONT_USE_DCACHE - ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, - de->name_len, ino); -#endif + dcache_add(dir, de->name, de->name_len, ino); brelse (bh); -#ifndef DONT_USE_DCACHE } -#endif if (!(*result = iget (dir->i_sb, ino))) { iput (dir); return -EACCES; @@ -390,11 +383,8 @@ return err; } de->inode = inode->i_ino; - dir->i_version++; -#ifndef DONT_USE_DCACHE - ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len, - de->inode); -#endif + dir->i_version = ++event; + dcache_add(dir, de->name, de->name_len, de->inode); mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); @@ -457,11 +447,8 @@ return err; } de->inode = inode->i_ino; - dir->i_version++; -#ifndef DONT_USE_DCACHE - ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len, - de->inode); -#endif + dir->i_version = ++event; + dcache_add(dir, de->name, de->name_len, de->inode); mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); @@ -534,11 +521,8 @@ return err; } de->inode = inode->i_ino; - dir->i_version++; -#ifndef DONT_USE_DCACHE - ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len, - de->inode); -#endif + dir->i_version = ++event; + dcache_add(dir, de->name, de->name_len, de->inode); mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); @@ -660,7 +644,7 @@ inode->i_size = 0; } retval = ext2_delete_entry (de, bh); - dir->i_version++; + dir->i_version = ++event; } up(&inode->i_sem); if (retval) @@ -670,17 +654,11 @@ ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } -#ifndef DONT_USE_DCACHE - ext2_dcache_remove(inode->i_dev, inode->i_ino, ".", 1); - ext2_dcache_remove(inode->i_dev, inode->i_ino, "..", 2); -#endif if (inode->i_nlink != 2) ext2_warning (inode->i_sb, "ext2_rmdir", "empty directory has nlink!=2 (%d)", inode->i_nlink); -#ifndef DONT_USE_DCACHE - ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len); -#endif + inode->i_version = ++event; inode->i_nlink = 0; inode->i_dirt = 1; dir->i_nlink--; @@ -733,15 +711,12 @@ retval = ext2_delete_entry (de, bh); if (retval) goto end_unlink; - dir->i_version++; + dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } -#ifndef DONT_USE_DCACHE - ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len); -#endif dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_dirt = 1; inode->i_nlink--; @@ -822,11 +797,8 @@ return err; } de->inode = inode->i_ino; - dir->i_version++; -#ifndef DONT_USE_DCACHE - ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len, - de->inode); -#endif + dir->i_version = ++event; + dcache_add(dir, de->name, de->name_len, de->inode); mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); @@ -869,11 +841,8 @@ return err; } de->inode = oldinode->i_ino; - dir->i_version++; -#ifndef DONT_USE_DCACHE - ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len, - de->inode); -#endif + dir->i_version = ++event; + dcache_add(dir, de->name, de->name_len, de->inode); mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); @@ -1032,19 +1001,14 @@ * ok, that's it */ new_de->inode = old_inode->i_ino; -#ifndef DONT_USE_DCACHE - ext2_dcache_remove (old_dir->i_dev, old_dir->i_ino, old_de->name, - old_de->name_len); - ext2_dcache_add (new_dir->i_dev, new_dir->i_ino, new_de->name, - new_de->name_len, new_de->inode); -#endif + dcache_add(new_dir, new_de->name, new_de->name_len, new_de->inode); retval = ext2_delete_entry (old_de, old_bh); if (retval == -ENOENT) goto try_again; if (retval) goto end_rename; - new_dir->i_version++; - old_dir->i_version++; + new_dir->i_version = ++event; + old_dir->i_version = ++event; if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; diff -u --recursive --new-file v1.1.36/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v1.1.36/linux/fs/ext2/super.c Fri May 27 10:49:13 1994 +++ linux/fs/ext2/super.c Fri Jul 29 14:36:22 1994 @@ -98,9 +98,6 @@ sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state; mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); } -#ifndef DONT_USE_DCACHE - ext2_dcache_invalidate (sb->s_dev); -#endif sb->s_dev = 0; for (i = 0; i < EXT2_MAX_GROUP_DESC; i++) if (sb->u.ext2_sb.s_group_desc[i]) diff -u --recursive --new-file v1.1.36/linux/fs/inode.c linux/fs/inode.c --- v1.1.36/linux/fs/inode.c Mon Apr 25 10:04:34 1994 +++ linux/fs/inode.c Fri Jul 29 14:53:19 1994 @@ -384,6 +384,7 @@ clear_inode(inode); inode->i_count = 1; inode->i_nlink = 1; + inode->i_version = ++event; inode->i_sem.count = 1; nr_free_inodes--; if (nr_free_inodes < 0) { diff -u --recursive --new-file v1.1.36/linux/fs/isofs/rock.c linux/fs/isofs/rock.c --- v1.1.36/linux/fs/isofs/rock.c Tue Apr 19 10:52:58 1994 +++ linux/fs/isofs/rock.c Tue Jul 26 21:25:31 1994 @@ -65,23 +65,28 @@ offset &= 1023; \ if(offset + cont_size >= 1024) { \ bh = bread(DEV->i_dev, block++, ISOFS_BUFFER_SIZE(DEV)); \ - memcpy(buffer, bh->b_data + offset, 1024 - offset); \ - brelse(bh); \ - offset1 = 1024 - offset; \ - offset = 0; \ + if(!bh) {printk("Unable to read continuation Rock Ridge record\n"); \ + kfree(buffer); \ + buffer = NULL; } else { \ + memcpy(buffer, bh->b_data + offset, 1024 - offset); \ + brelse(bh); \ + offset1 = 1024 - offset; \ + offset = 0;} \ } \ }; \ - bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \ - if(bh){ \ - memcpy(buffer + offset1, bh->b_data + offset, cont_size - offset1); \ - brelse(bh); \ - chr = (unsigned char *) buffer; \ - len = cont_size; \ - cont_extent = 0; \ - cont_size = 0; \ - cont_offset = 0; \ - goto LABEL; \ - }; \ + if(buffer) { \ + bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \ + if(bh){ \ + memcpy(buffer + offset1, bh->b_data + offset, cont_size - offset1); \ + brelse(bh); \ + chr = (unsigned char *) buffer; \ + len = cont_size; \ + cont_extent = 0; \ + cont_size = 0; \ + cont_offset = 0; \ + goto LABEL; \ + }; \ + } \ printk("Unable to read rock-ridge attributes\n"); \ }} diff -u --recursive --new-file v1.1.36/linux/fs/msdos/mmap.c linux/fs/msdos/mmap.c --- v1.1.36/linux/fs/msdos/mmap.c Tue Jul 26 21:39:45 1994 +++ linux/fs/msdos/mmap.c Thu Jul 28 09:05:25 1994 @@ -94,12 +94,9 @@ inode->i_dirt = 1; } - unmap_page_range(vma->vm_start, vma->vm_end - vma->vm_start); vma->vm_inode = inode; inode->i_count++; vma->vm_ops = &msdos_file_mmap; - insert_vm_struct(current, vma); - merge_segments(current->mm->mmap); return 0; } diff -u --recursive --new-file v1.1.36/linux/fs/nfs/mmap.c linux/fs/nfs/mmap.c --- v1.1.36/linux/fs/nfs/mmap.c Tue Jul 26 21:39:45 1994 +++ linux/fs/nfs/mmap.c Thu Jul 28 09:05:25 1994 @@ -96,11 +96,8 @@ inode->i_dirt = 1; } - unmap_page_range(vma->vm_start, vma->vm_end - vma->vm_start); vma->vm_inode = inode; inode->i_count++; vma->vm_ops = &nfs_file_mmap; - insert_vm_struct(current, vma); - merge_segments(current->mm->mmap); return 0; } diff -u --recursive --new-file v1.1.36/linux/fs/sysv/Makefile linux/fs/sysv/Makefile --- v1.1.36/linux/fs/sysv/Makefile Tue Nov 30 04:56:57 1993 +++ linux/fs/sysv/Makefile Tue Jul 26 21:34:03 1994 @@ -15,7 +15,7 @@ $(AS) -o $*.o $< OBJS= ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \ - fsync.o truncate.o # mmap.o + fsync.o truncate.o mmap.o sysv.o: $(OBJS) $(LD) -r -o sysv.o $(OBJS) diff -u --recursive --new-file v1.1.36/linux/fs/sysv/README linux/fs/sysv/README --- v1.1.36/linux/fs/sysv/README Thu Jan 13 20:26:20 1994 +++ linux/fs/sysv/README Tue Jul 26 21:34:03 1994 @@ -4,7 +4,7 @@ - SystemV/386 FS, - Coherent FS. -This is version beta 1. +This is version beta 2. To install: * Answer the 'System V and Coherent filesystem support' question with 'y' diff -u --recursive --new-file v1.1.36/linux/fs/sysv/file.c linux/fs/sysv/file.c --- v1.1.36/linux/fs/sysv/file.c Tue Apr 19 10:53:25 1994 +++ linux/fs/sysv/file.c Tue Jul 26 21:34:03 1994 @@ -32,7 +32,6 @@ #include #include -static int sysv_file_read(struct inode *, struct file *, char *, int); static int sysv_file_write(struct inode *, struct file *, char *, int); /* @@ -46,7 +45,7 @@ NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ - NULL, /* mmap */ + sysv_mmap, /* mmap */ NULL, /* no special open is needed */ NULL, /* release */ sysv_sync_file /* fsync */ @@ -106,7 +105,7 @@ char * bh_data; }; -static int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int count) +int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int count) { struct super_block * sb = inode->i_sb; int read,left,chars; diff -u --recursive --new-file v1.1.36/linux/fs/sysv/mmap.c linux/fs/sysv/mmap.c --- v1.1.36/linux/fs/sysv/mmap.c Thu Jan 1 02:00:00 1970 +++ linux/fs/sysv/mmap.c Thu Jul 28 09:04:54 1994 @@ -0,0 +1,85 @@ +/* + * linux/fs/sysv/mmap.c + * + * mm/memory.c, mm/mmap.c + * Copyright (C) 1991, 1992, 1993 Linus Torvalds + * + * nfs/mmap.c + * Copyright (C) 1993 Jon Tombs + * + * fs/msdos/mmap.c + * Copyright (C) 1994 Jacques Gelinas + * + * fs/sysv/mmap.c + * Copyright (C) 1994 Bruno Haible + * + * SystemV/Coherent mmap handling + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Fill in the supplied page for mmap + */ +static unsigned long sysv_file_mmap_nopage (struct vm_area_struct * area, + unsigned long address, unsigned long page, int no_share) +{ + int remaining, count, old_fs; + struct file filp; + + address &= PAGE_MASK; + /* prepare a file pointer */ + filp.f_pos = address - area->vm_start + area->vm_offset; + filp.f_reada = 0; + remaining = area->vm_end - address; + if (remaining > PAGE_SIZE) + remaining = PAGE_SIZE; + /* read from the file. page is in kernel space, not user space. */ + old_fs = get_fs(); set_fs(get_ds()); + count = sysv_file_read (area->vm_inode, &filp, (char *)page, remaining); + set_fs(old_fs); + if (count < 0) + count = 0; /* do nothing on I/O error ?? */ + else + remaining -= count; + if (remaining > 0) + memset((char *)page + count, 0, remaining); + return page; +} + +static struct vm_operations_struct sysv_file_mmap = { + NULL, /* open */ + NULL, /* close */ + sysv_file_mmap_nopage, /* nopage */ + NULL, /* wppage */ + NULL, /* share */ + NULL, /* unmap */ +}; + +int sysv_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 right 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 = &sysv_file_mmap; + return 0; +} diff -u --recursive --new-file v1.1.36/linux/ibcs/binfmt_elf.c linux/ibcs/binfmt_elf.c --- v1.1.36/linux/ibcs/binfmt_elf.c Tue Jun 21 14:16:24 1994 +++ linux/ibcs/binfmt_elf.c Thu Jul 28 12:29:36 1994 @@ -66,12 +66,13 @@ mpnt->vm_start = PAGE_MASK & (unsigned long) p; mpnt->vm_end = TASK_SIZE; mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY; + mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_share = NULL; + mpnt->vm_ops = NULL; mpnt->vm_inode = NULL; mpnt->vm_offset = 0; - mpnt->vm_ops = NULL; + mpnt->vm_pte = 0; insert_vm_struct(current, mpnt); - current->mm->stk_vma = mpnt; } sp = (unsigned long *) (0xfffffffc & (unsigned long) p); if(exec) sp -= DLINFO_ITEMS*2; diff -u --recursive --new-file v1.1.36/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v1.1.36/linux/include/linux/ext2_fs.h Tue Apr 19 10:53:28 1994 +++ linux/include/linux/ext2_fs.h Fri Jul 29 14:37:01 1994 @@ -40,11 +40,6 @@ #undef EXT2FS_PRE_02B_COMPAT /* - * Define DONT_USE_DCACHE to inhibit the directory cache - */ -#define DONT_USE_DCACHE - -/* * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files */ #define EXT2_PREALLOCATE @@ -354,17 +349,6 @@ /* bitmap.c */ extern unsigned long ext2_count_free (struct buffer_head *, unsigned); - -#ifndef DONT_USE_DCACHE -/* dcache.c */ -extern void ext2_dcache_invalidate (unsigned short); -extern unsigned long ext2_dcache_lookup (unsigned short, unsigned long, - const char *, int); -extern void ext2_dcache_add (unsigned short, unsigned long, const char *, - int, unsigned long); -extern void ext2_dcache_remove (unsigned short, unsigned long, const char *, - int); -#endif /* dir.c */ extern int ext2_check_dir_entry (char *, struct inode *, diff -u --recursive --new-file v1.1.36/linux/include/linux/fs.h linux/include/linux/fs.h --- v1.1.36/linux/include/linux/fs.h Tue Jul 26 21:39:46 1994 +++ linux/include/linux/fs.h Fri Jul 29 12:34:17 1994 @@ -45,6 +45,7 @@ extern void buffer_init(void); extern unsigned long inode_init(unsigned long start, unsigned long end); extern unsigned long file_table_init(unsigned long start, unsigned long end); +extern unsigned long name_cache_init(unsigned long start, unsigned long end); #define MAJOR(a) (int)((unsigned short)(a) >> 8) #define MINOR(a) (int)((unsigned short)(a) & 0xFF) @@ -468,6 +469,9 @@ extern int block_fsync(struct inode *, struct file *); extern int file_fsync(struct inode *, struct file *); + +extern void dcache_add(struct inode *, const char *, int, unsigned long); +extern unsigned long dcache_lookup(struct inode *, const char *, int); extern inline struct inode * iget(struct super_block * sb,int nr) { diff -u --recursive --new-file v1.1.36/linux/include/linux/page.h linux/include/linux/page.h --- v1.1.36/linux/include/linux/page.h Wed Dec 1 14:44:15 1993 +++ linux/include/linux/page.h Thu Jul 28 10:57:02 1994 @@ -3,7 +3,9 @@ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 -#define PAGE_SIZE ((unsigned long)1<state == TASK_UNINTERRUPTIBLE) || (p->state == TASK_INTERRUPTIBLE)) { p->state = TASK_RUNNING; - if (p->counter > current->counter) + if (p->counter > current->counter + 3) need_resched = 1; } } @@ -304,7 +305,7 @@ if ((p = tmp->task) != NULL) { if (p->state == TASK_INTERRUPTIBLE) { p->state = TASK_RUNNING; - if (p->counter > current->counter) + if (p->counter > current->counter + 3) need_resched = 1; } } diff -u --recursive --new-file v1.1.36/linux/kernel/sys.c linux/kernel/sys.c --- v1.1.36/linux/kernel/sys.c Tue Jun 21 14:16:26 1994 +++ linux/kernel/sys.c Thu Jul 28 08:44:48 1994 @@ -299,8 +299,8 @@ int old_ruid = current->uid; if (ruid != (uid_t) -1) { - if ((current->euid==ruid) || - (old_ruid == ruid) || + if ((old_ruid == ruid) || + (current->euid==ruid) || suser()) current->uid = ruid; else @@ -309,6 +309,7 @@ if (euid != (uid_t) -1) { if ((old_ruid == euid) || (current->euid == euid) || + (current->suid == euid) || suser()) current->euid = euid; else { diff -u --recursive --new-file v1.1.36/linux/mm/mmap.c linux/mm/mmap.c --- v1.1.36/linux/mm/mmap.c Tue Jul 26 21:39:47 1994 +++ linux/mm/mmap.c Thu Jul 28 09:15:43 1994 @@ -154,13 +154,15 @@ else error = anon_map(NULL, NULL, vma); - if (!error) - return addr; - - kfree(vma); - if (!current->errno) - current->errno = -error; - return -1; + if (error) { + kfree(vma); + if (!current->errno) + current->errno = -error; + return -1; + } + insert_vm_struct(current, vma); + merge_segments(current->mm->mmap); + return addr; } asmlinkage int sys_mmap(unsigned long *buffer) @@ -336,7 +338,6 @@ int generic_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) { extern struct vm_operations_struct file_mmap; - struct buffer_head * bh; if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported right now */ return -EINVAL; @@ -346,54 +347,33 @@ return -EACCES; if (!inode->i_op || !inode->i_op->bmap) return -ENOEXEC; - if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) - return -EACCES; if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } - brelse(bh); - - unmap_page_range(vma->vm_start, vma->vm_end - vma->vm_start); vma->vm_inode = inode; inode->i_count++; vma->vm_ops = &file_mmap; - insert_vm_struct(current, vma); - merge_segments(current->mm->mmap); - return 0; } /* - * Insert vm structure into process list - * This makes sure the list is sorted by start address, and - * some some simple overlap checking. - * JSGF + * Insert vm structure into process list sorted by address. */ void insert_vm_struct(struct task_struct *t, struct vm_area_struct *vmp) { - struct vm_area_struct **nxtpp, *mpnt; + struct vm_area_struct **p, *mpnt; - nxtpp = &t->mm->mmap; - - for(mpnt = t->mm->mmap; mpnt != NULL; mpnt = mpnt->vm_next) - { + p = &t->mm->mmap; + while ((mpnt = *p) != NULL) { if (mpnt->vm_start > vmp->vm_start) break; - nxtpp = &mpnt->vm_next; - - if ((vmp->vm_start >= mpnt->vm_start && - vmp->vm_start < mpnt->vm_end) || - (vmp->vm_end >= mpnt->vm_start && - vmp->vm_end < mpnt->vm_end)) - printk("insert_vm_struct: ins area %lx-%lx in area %lx-%lx\n", - vmp->vm_start, vmp->vm_end, - mpnt->vm_start, vmp->vm_end); + if (mpnt->vm_end > vmp->vm_start) + printk("insert_vm_struct: overlapping memory areas\n"); + p = &mpnt->vm_next; } - vmp->vm_next = mpnt; - - *nxtpp = vmp; + *p = vmp; } /* @@ -456,8 +436,5 @@ { if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -ENOMEM; - - insert_vm_struct(current, vma); - merge_segments(current->mm->mmap); return 0; } diff -u --recursive --new-file v1.1.36/linux/mm/swap.c linux/mm/swap.c --- v1.1.36/linux/mm/swap.c Tue Jul 26 21:39:47 1994 +++ linux/mm/swap.c Thu Jul 28 11:29:03 1994 @@ -353,7 +353,7 @@ * * (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de */ -#ifdef NEW_SWAP + /* * These are the miminum and maximum number of pages to swap from one process, * before proceeding to the next: @@ -367,181 +367,123 @@ */ #define SWAP_RATIO 128 -static int swap_out(unsigned int priority) +static int swap_out_process(struct task_struct * p) { - static int swap_task; - int table; - int page; - long pg_table; - int loop; - int counter = NR_TASKS * 2 >> priority; - struct task_struct *p; - - counter = NR_TASKS * 2 >> priority; - for(; counter >= 0; counter--, swap_task++) { - /* - * Check that swap_task is suitable for swapping. If not, look for - * the next suitable process. - */ - loop = 0; - while(1) { - if(swap_task >= NR_TASKS) { - swap_task = 1; - if(loop) - /* all processes are unswappable or already swapped out */ - return 0; - loop = 1; - } - - p = task[swap_task]; - if(p && p->mm->swappable && p->mm->rss) - break; - - swap_task++; - } - - /* - * Determine the number of pages to swap from this process. - */ - if(! p->mm->swap_cnt) { - p->mm->dec_flt = (p->mm->dec_flt * 3) / 4 + p->mm->maj_flt - p->mm->old_maj_flt; - p->mm->old_maj_flt = p->mm->maj_flt; - - if(p->mm->dec_flt >= SWAP_RATIO / SWAP_MIN) { - p->mm->dec_flt = SWAP_RATIO / SWAP_MIN; - p->mm->swap_cnt = SWAP_MIN; - } else if(p->mm->dec_flt <= SWAP_RATIO / SWAP_MAX) - p->mm->swap_cnt = SWAP_MAX; - else - p->mm->swap_cnt = SWAP_RATIO / p->mm->dec_flt; - } + unsigned long address; + unsigned long offset; + unsigned long *pgdir; + unsigned long pg_table; /* * Go through process' page directory. */ - for(table = p->mm->swap_table; table < 1024; table++) { - pg_table = ((unsigned long *) p->tss.cr3)[table]; - if(pg_table >= high_memory) - continue; - if(mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED) - continue; - if(!(PAGE_PRESENT & pg_table)) { - printk("swap_out: bad page-table at pg_dir[%d]: %08lx\n", - table, pg_table); - ((unsigned long *) p->tss.cr3)[table] = 0; - continue; - } - pg_table &= 0xfffff000; - - /* - * Go through this page table. - */ - for(page = p->mm->swap_page; page < 1024; page++) { - switch(try_to_swap_out(page + (unsigned long *) pg_table)) { - case 0: - break; - - case 1: - p->mm->rss--; - /* continue with the following page the next time */ - p->mm->swap_table = table; - p->mm->swap_page = page + 1; - if((--p->mm->swap_cnt) == 0) - swap_task++; - return 1; - - default: - p->mm->rss--; - break; + address = p->mm->swap_address; + pgdir = (address >> PGDIR_SHIFT) + (unsigned long *) p->tss.cr3; + offset = address & ~PGDIR_MASK; + address &= PGDIR_MASK; + for ( ; address < TASK_SIZE ; + pgdir++, address = address + PGDIR_SIZE, offset = 0) { + pg_table = *pgdir; + if (pg_table >= high_memory) + continue; + if (mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED) + continue; + if (!(PAGE_PRESENT & pg_table)) { + printk("swap_out_process (%s): bad page-table at vm %08lx: %08lx\n", + p->comm, address + offset, pg_table); + *pgdir = 0; + continue; } - } + pg_table &= 0xfffff000; - p->mm->swap_page = 0; + /* + * Go through this page table. + */ + for( ; offset < ~PGDIR_MASK ; offset += PAGE_SIZE) { + switch(try_to_swap_out((unsigned long *) (pg_table + (offset >> 10)))) { + case 0: + break; + + case 1: + p->mm->rss--; + /* continue with the following page the next time */ + p->mm->swap_address = address + offset + PAGE_SIZE; + return 1; + + default: + p->mm->rss--; + break; + } + } } - /* * Finish work with this process, if we reached the end of the page * directory. Mark restart from the beginning the next time. */ - p->mm->swap_table = 0; - } - return 0; + p->mm->swap_address = 0; + return 0; } -#else /* old swapping procedure */ - -/* - * Go through the page tables, searching for a user page that - * we can swap out. - * - * We now check that the process is swappable (normally only 'init' - * is un-swappable), allowing high-priority processes which cannot be - * swapped out (things like user-level device drivers (Not implemented)). - */ static int swap_out(unsigned int priority) { - static int swap_task = 1; - static int swap_table = 0; - static int swap_page = 0; - int counter = NR_TASKS*8; - int pg_table; - struct task_struct * p; - - counter >>= priority; -check_task: - if (counter-- < 0) - return 0; - if (swap_task >= NR_TASKS) { - swap_task = 1; - goto check_task; - } - p = task[swap_task]; - if (!p || !p->mm->swappable) { - swap_task++; - goto check_task; - } -check_dir: - if (swap_table >= PTRS_PER_PAGE) { - swap_table = 0; - swap_task++; - goto check_task; - } - pg_table = ((unsigned long *) p->tss.cr3)[swap_table]; - if (pg_table >= high_memory || (mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED)) { - swap_table++; - goto check_dir; - } - if (!(PAGE_PRESENT & pg_table)) { - printk("bad page-table at pg_dir[%d]: %08x\n", - swap_table,pg_table); - ((unsigned long *) p->tss.cr3)[swap_table] = 0; - swap_table++; - goto check_dir; - } - pg_table &= PAGE_MASK; -check_table: - if (swap_page >= PTRS_PER_PAGE) { - swap_page = 0; - swap_table++; - goto check_dir; - } - switch (try_to_swap_out(swap_page + (unsigned long *) pg_table)) { - case 0: break; - case 1: p->mm->rss--; return 1; - default: p->mm->rss--; + static int swap_task; + int loop; + int counter = NR_TASKS * 2 >> priority; + struct task_struct *p; + + counter = NR_TASKS * 2 >> priority; + for(; counter >= 0; counter--, swap_task++) { + /* + * Check that swap_task is suitable for swapping. If not, look for + * the next suitable process. + */ + loop = 0; + while(1) { + if (swap_task >= NR_TASKS) { + swap_task = 1; + if (loop) + /* all processes are unswappable or already swapped out */ + return 0; + loop = 1; + } + + p = task[swap_task]; + if (p && p->mm->swappable && p->mm->rss) + break; + + swap_task++; + } + + /* + * Determine the number of pages to swap from this process. + */ + if (!p->mm->swap_cnt) { + p->mm->dec_flt = (p->mm->dec_flt * 3) / 4 + p->mm->maj_flt - p->mm->old_maj_flt; + p->mm->old_maj_flt = p->mm->maj_flt; + + if (p->mm->dec_flt >= SWAP_RATIO / SWAP_MIN) { + p->mm->dec_flt = SWAP_RATIO / SWAP_MIN; + p->mm->swap_cnt = SWAP_MIN; + } else if (p->mm->dec_flt <= SWAP_RATIO / SWAP_MAX) + p->mm->swap_cnt = SWAP_MAX; + else + p->mm->swap_cnt = SWAP_RATIO / p->mm->dec_flt; + } + if (swap_out_process(p)) { + if ((--p->mm->swap_cnt) == 0) + swap_task++; + return 1; + } } - swap_page++; - goto check_table; + return 0; } -#endif - static int try_to_free_page(int priority) { int i=6; while (i--) { - if (priority != GFP_NOBUFFER && shrink_buffers(i)) + if (priority != GFP_NOBUFFER && shrink_buffers(i)) return 1; if (shm_swap(i)) return 1; @@ -599,6 +541,21 @@ add_mem_queue(free_area_list+order, (struct mem_list *) addr); } +static inline void check_free_buffers(unsigned long addr) +{ + struct buffer_head * bh; + + bh = buffer_pages[MAP_NR(addr)]; + if (bh) { + struct buffer_head *tmp = bh; + do { + if (tmp->b_list == BUF_SHARED && tmp->b_dev != 0xffff) + refile_buffer(tmp); + tmp = tmp->b_this_page; + } while (tmp != bh); + } +} + void free_pages(unsigned long addr, unsigned long order) { if (addr < high_memory) { @@ -613,17 +570,8 @@ delete_from_swap_cache(addr); } restore_flags(flag); - if(*map == 1) { - int j; - struct buffer_head * bh, *tmp; - - bh = buffer_pages[MAP_NR(addr)]; - if(bh) - for(j = 0, tmp = bh; tmp && (!j || tmp != bh); - tmp = tmp->b_this_page, j++) - if(tmp->b_list == BUF_SHARED && tmp->b_dev != 0xffff) - refile_buffer(tmp); - } + if (*map == 1) + check_free_buffers(addr); } return; } @@ -689,7 +637,7 @@ return 0; } restore_flags(flags); - if (priority != GFP_BUFFER && try_to_free_page(priority)) + if (priority != GFP_BUFFER && try_to_free_page(priority)) goto repeat; return 0; }