]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.55 1.1.55
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:41 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:41 +0000 (15:09 -0500)
23 files changed:
Makefile
drivers/block/floppy.c
drivers/block/hd.c
drivers/char/lp.c
drivers/sound/Makefile
fs/binfmt_elf.c
fs/ext/dir.c
fs/ext2/dir.c
fs/ext2/namei.c
fs/hpfs/hpfs_fs.c
fs/isofs/dir.c
fs/minix/dir.c
fs/minix/namei.c
fs/msdos/dir.c
fs/nfs/dir.c
fs/proc/link.c
fs/read_write.c
fs/sysv/dir.c
fs/xiafs/dir.c
include/linux/hdreg.h
include/linux/tty.h
kernel/ksyms.c
net/inet/tcp.c

index b96bd98725d060b2939cbd468672f87bf1ddc274..94a9695ccf9dca9c4e602250b6ced29ad0d907f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 54
+SUBLEVEL = 55
 
 ARCH = i386
 
index 378369209b7bdb8e22e6d8ed5c4fbaaddbf41213..2ca87e6938f13637220b6496dbf4d977eec865b0 100644 (file)
@@ -25,9 +25,9 @@
 
 
 /* Define the following if you don't like that your drives seek audibly
- * after a disk change
+ * after a disk change (but it may not work correctly for everybody)
  */
-#define SILENT_DC_CLEAR
+/* #define SILENT_DC_CLEAR */
 
 
 /* End of configuration */
@@ -304,7 +304,7 @@ static struct floppy_struct floppy_type[32] = {
        { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"CompaQ"}, /*  9 2.88MB 3.5"   */
 
        { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25"  */
-       { 3360,21,2,80,0,0x1C,0x00,0xCF,0x6C,"H1680" }, /* 11 1.68MB 3.5"   */
+       { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5"   */
        {  820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410"  }, /* 12 410KB 5.25"   */
        { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820"  }, /* 13 820KB 3.5"    */
        { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25"  */
@@ -317,8 +317,8 @@ static struct floppy_struct floppy_type[32] = {
        { 1760,11,2,80,0,0x1C,0x09,0xCF,0x6C,"h880"  }, /* 20 880KB 5.25"   */
        { 2080,13,2,80,0,0x1C,0x01,0xCF,0x6C,"D1040" }, /* 21 1.04MB 3.5"   */
        { 2240,14,2,80,0,0x1C,0x19,0xCF,0x6C,"D1120" }, /* 22 1.12MB 3.5"   */
-       { 3200,20,2,80,0,0x1C,0x20,0xCF,0x6C,"h1600" }, /* 23 1.6MB 5.25"   */
-       { 3520,22,2,80,0,0x1C,0x08,0xCF,0x6C,"H1760" }, /* 24 1.76MB 3.5"   */
+       { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25"   */
+       { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5"   */
        { 3840,24,2,80,0,0x1C,0x20,0xCF,0x6C,"H1920" }, /* 25 1.92MB 3.5"   */
        { 6400,40,2,80,0,0x25,0x5B,0xCF,0x6C,"E3200" }, /* 26 3.20MB 3.5"   */
        { 7040,44,2,80,0,0x25,0x5B,0xCF,0x6C,"E3520" }, /* 27 3.52MB 3.5"   */
@@ -326,7 +326,7 @@ static struct floppy_struct floppy_type[32] = {
 
        { 3680,23,2,80,0,0x1C,0x10,0xCF,0x6C,"H1840" }, /* 29 1.84MB 3.5"   */
        { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800"  }, /* 30 800KB 3.5"    */
-       { 3200,20,2,80,0,0x1C,0x00,0xCF,0x6C,"H1600" }, /* 31 1.6MB 3.5"    */
+       { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5"    */
 };
 
 #define        NUMBER(x)       (sizeof(x) / sizeof(*(x)))
@@ -1278,9 +1278,10 @@ static void recal_interrupt(void)
                        debugt("recal interrupt need 1 recal:");
 #endif
                        /* after a second recalibrate, we still haven't
-                        * reached track 0. Probably no drive */
-                       DRS->track = PROVEN_ABSENT;
-                       cont->done(0);
+                        * reached track 0. Probably no drive. Raise an
+                        * error, as failing immediately might upset 
+                        * computers possessed by the Devil :-) */
+                       cont->error();
                        cont->redo();
                        return;
                case NEED_2_RECAL:
@@ -1691,7 +1692,7 @@ static void setup_format_params(void)
        int count,head_shift,track_shift;
 
        raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
-               FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
+               /*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
        raw_cmd.rate = floppy->rate & 0x3;
        raw_cmd.cmd_count = NR_F;
        COMMAND = FM_MODE(floppy,FD_FORMAT);
index 13a61030462f2c567853c6cb80be648b5725bb49..7964c7d6a6977a00d80910ec42ef28970a5bd68d 100644 (file)
  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
  *  in the early extended-partition checks and added DM partitions
  *
- *  IDE IRQ-unmask & drive-id & multiple-mode code added by Mark Lord.
- *
- *  Support for BIOS drive geometry translation added by Mark Lord.
- *   -- hd.c no longer chokes on drives with "more than 16 heads".
+ *  IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
+ *  and general streamlining by mlord@bnr.ca (Mark Lord).
  */
 
 #define DEFAULT_MULT_COUNT  0  /* set to 0 to disable multiple mode at boot */
@@ -62,6 +60,9 @@ static inline unsigned char CMOS_READ(unsigned char addr)
 #define RECAL_FREQ      4      /* Recalibrate every 4th retry */
 #define MAX_HD         2
 
+#define STAT_OK                (READY_STAT|SEEK_STAT)
+#define OK_STATUS(s)   (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
+
 static void recal_intr(void);
 static void bad_rw_intr(void);
 
@@ -135,12 +136,12 @@ void hd_setup(char *str, int *ints)
 static void dump_status (char *msg, unsigned int stat)
 {
        unsigned long flags;
-       char dev;
+       char devc;
 
-       dev  = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?';
+       devc = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?';
        save_flags (flags);
        sti();
-       printk("hd%c: %s: status=0x%02x { ", dev, msg, stat & 0xff);
+       printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
        if (stat & BUSY_STAT)   printk("Busy ");
        if (stat & READY_STAT)  printk("DriveReady ");
        if (stat & WRERR_STAT)  printk("WriteFault ");
@@ -150,55 +151,48 @@ static void dump_status (char *msg, unsigned int stat)
        if (stat & INDEX_STAT)  printk("Index ");
        if (stat & ERR_STAT)    printk("Error ");
        printk("}\n");
-       if (stat & ERR_STAT) {
-               unsigned int err = inb(HD_ERROR);
-               printk("hd%c: %s: error=0x%02x { ", dev, msg, err & 0xff);
-               if (err & BBD_ERR)      printk("BadSector ");
-               if (err & ECC_ERR)      printk("UncorrectableError ");
-               if (err & ID_ERR)       printk("SectorIdNotFound ");
-               if (err & ABRT_ERR)     printk("DriveStatusError ");
-               if (err & TRK0_ERR)     printk("TrackZeroNotFound ");
-               if (err & MARK_ERR)     printk("AddrMarkNotFound ");
+       if ((stat & ERR_STAT) == 0) {
+               hd_error = 0;
+       } else {
+               hd_error = inb(HD_ERROR);
+               printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
+               if (hd_error & BBD_ERR)         printk("BadSector ");
+               if (hd_error & ECC_ERR)         printk("UncorrectableError ");
+               if (hd_error & ID_ERR)          printk("SectorIdNotFound ");
+               if (hd_error & ABRT_ERR)        printk("DriveStatusError ");
+               if (hd_error & TRK0_ERR)        printk("TrackZeroNotFound ");
+               if (hd_error & MARK_ERR)        printk("AddrMarkNotFound ");
                printk("}");
-               if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
-                       if (CURRENT)
-                               printk(", sector=%ld", CURRENT->sector);
+               if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
                        printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
                                inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
+                       if (CURRENT)
+                               printk(", sector=%ld", CURRENT->sector);
                }
                printk("\n");
        }
        restore_flags (flags);
 }
 
-static int win_result(void)
+void check_status(void)
 {
-       int i=inb_p(HD_STATUS);
+       int i = inb_p(HD_STATUS);
 
-       if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
-               == (READY_STAT | SEEK_STAT)) {
-               hd_error = 0;
-               return 0; /* ok */
+       if (!OK_STATUS(i)) {
+               dump_status("check_status", i);
+               bad_rw_intr();
        }
-       dump_status("win_result", i);
-       return 1;
 }
 
-static int controller_busy(void);
-static int status_ok(void);
-
-static int controller_ready(unsigned int drive, unsigned int head)
+static int controller_busy(void)
 {
-       int retry = 100;
+       int retries = 100000;
+       unsigned char status;
 
        do {
-               if (controller_busy() & BUSY_STAT)
-                       return 0;
-               outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
-               if (status_ok())
-                       return 1;
-       } while (--retry);
-       return 0;
+               status = inb_p(HD_STATUS);
+       } while ((status & BUSY_STAT) && --retries);
+       return status;
 }
 
 static int status_ok(void)
@@ -206,7 +200,7 @@ static int status_ok(void)
        unsigned char status = inb_p(HD_STATUS);
 
        if (status & BUSY_STAT)
-               return 1;
+               return 1;       /* Ancient, but does it make sense??? */
        if (status & WRERR_STAT)
                return 0;
        if (!(status & READY_STAT))
@@ -216,15 +210,18 @@ static int status_ok(void)
        return 1;
 }
 
-static int controller_busy(void)
+static int controller_ready(unsigned int drive, unsigned int head)
 {
-       int retries = 100000;
-       unsigned char status;
+       int retry = 100;
 
        do {
-               status = inb_p(HD_STATUS);
-       } while ((status & BUSY_STAT) && --retries);
-       return status;
+               if (controller_busy() & BUSY_STAT)
+                       return 0;
+               outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
+               if (status_ok())
+                       return 1;
+       } while (--retry);
+       return 0;
 }
 
 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
@@ -233,13 +230,6 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
 {
        unsigned short port;
 
-#ifdef DEBUG
-       if (drive>1 || head>15) {
-               printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n",
-                       drive, cyl, head, sect);
-               panic("harddisk driver problem");
-       }
-#endif
 #if (HD_DELAY > 0)
        while (read_timer() - last_req < HD_DELAY)
                /* nothing */;
@@ -346,7 +336,7 @@ static void identify_intr(void)
                /*
                 * Early model Quantum drives go weird at this point,
                 *   but doing a recalibrate seems to "fix" them.
-                * (Doing a full reset confuses some newer model Quantums)
+                * (Doing a full reset confuses some other model Quantums)
                 */
                if (!strncmp(id->model, "QUANTUM", 7))
                        special_op[dev] = recalibrate[dev] = 1;
@@ -366,7 +356,7 @@ static void set_multmode_intr(void)
                sti();
        if (stat & (BUSY_STAT|ERR_STAT)) {
                mult_req[dev] = mult_count[dev] = 0;
-               dump_status("set multiple mode failed", stat);
+               dump_status("set multmode failed", stat);
        } else {
                if ((mult_count[dev] = mult_req[dev]))
                        printk ("  hd%c: enabled %d-sector multiple mode\n",
@@ -388,8 +378,7 @@ static int drive_busy(void)
 
        for (i = 0; i < 500000 ; i++) {
                c = inb_p(HD_STATUS);
-               c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
-               if (c == (READY_STAT | SEEK_STAT))
+               if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
                        return 0;
        }
        dump_status("reset timed out", c);
@@ -405,9 +394,9 @@ static void reset_controller(void)
        outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
        for(i = 0; i < 1000; i++) nop();
        if (drive_busy())
-               printk("HD-controller still busy\n");
-       if ((hd_error = inb(HD_ERROR)) != 1)
-               printk("HD-controller reset failed: %02x\n",hd_error);
+               printk("hd: controller still busy\n");
+       else if ((hd_error = inb(HD_ERROR)) != 1)
+               printk("hd: controller reset failed: %02x\n",hd_error);
 }
 
 static void reset_hd(void)
@@ -419,12 +408,13 @@ repeat:
                reset = 0;
                i = -1;
                reset_controller();
-       } else if (win_result()) {
-               bad_rw_intr();
+       } else {
+               check_status();
                if (reset)
                        goto repeat;
        }
        if (++i < NR_HD) {
+               special_op[i] = recalibrate[i] = 1;
                if (unmask_intr[i]) {
                        unmask_intr[i] = DEFAULT_UNMASK_INTR;
                        printk("hd%c: reset irq-unmasking to %d\n",i+'a',
@@ -444,7 +434,6 @@ repeat:
                hd_request();
 }
 
-
 /*
  * Ok, don't know what to do with the unexpected interrupts: on some machines
  * doing a reset and a retry seems to result in an eternal loop. Right now I
@@ -478,11 +467,11 @@ static void bad_rw_intr(void)
        dev = DEVICE_NR(CURRENT->dev);
        if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
                end_request(0);
-               special_op[dev] += recalibrate[dev] = 1;
+               special_op[dev] = recalibrate[dev] = 1;
        } else if (CURRENT->errors % RESET_FREQ == 0)
                reset = 1;
        else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
-               special_op[dev] += recalibrate[dev] = 1;
+               special_op[dev] = recalibrate[dev] = 1;
        /* Otherwise just retry */
 }
 
@@ -497,9 +486,6 @@ static inline int wait_DRQ(void)
        return -1;
 }
 
-#define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
-#define STAT_OK (READY_STAT | SEEK_STAT)
-
 static void read_intr(void)
 {
        unsigned int dev = DEVICE_NR(CURRENT->dev);
@@ -511,7 +497,7 @@ static void read_intr(void)
                i = (unsigned) inb_p(HD_STATUS);
                if (i & BUSY_STAT)
                        continue;
-               if ((i & STAT_MASK) != STAT_OK)
+               if (!OK_STATUS(i))
                        break;
                if (i & DRQ_STAT)
                        goto ok_to_read;
@@ -534,9 +520,9 @@ ok_to_read:
        i = (CURRENT->nr_sectors -= nsect);
 
 #ifdef DEBUG
-       printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=%08lx\n",
+       printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=0x%08lx\n",
                dev+'a', CURRENT->sector, CURRENT->sector+nsect,
-               CURRENT->nr_sectors, (long) CURRENT->buffer+(nsect<<9));
+               CURRENT->nr_sectors, (unsigned long) CURRENT->buffer+(nsect<<9));
 #endif
        if ((CURRENT->current_nr_sectors -= nsect) <= 0)
                end_request(1);
@@ -581,7 +567,7 @@ static void multwrite_intr(void)
 
        if (unmask_intr[dev])
                sti();
-       if (((i = inb_p(HD_STATUS)) & STAT_MASK) == STAT_OK) {
+       if (OK_STATUS(i=inb_p(HD_STATUS))) {
                if (i & DRQ_STAT) {
                        if (WCURRENT.nr_sectors) {
                                multwrite(dev);
@@ -619,7 +605,7 @@ static void write_intr(void)
                i = (unsigned) inb_p(HD_STATUS);
                if (i & BUSY_STAT)
                        continue;
-               if ((i & STAT_MASK) != STAT_OK)
+               if (!OK_STATUS(i))
                        break;
                if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
                        goto ok_to_write;
@@ -650,8 +636,7 @@ ok_to_write:
 
 static void recal_intr(void)
 {
-       if (win_result())
-               bad_rw_intr();
+       check_status();
 #if (HD_DELAY > 0)
        last_req = read_timer();
 #endif
@@ -664,116 +649,118 @@ static void recal_intr(void)
  */
 static void hd_times_out(void)
 {
+       unsigned int dev;
+
        DEVICE_INTR = NULL;
-       sti();
        if (!CURRENT)
                return;
+       disable_irq(HD_IRQ);
+       sti();
        reset = 1;
-       printk(KERN_DEBUG "HD timeout\n");
+       dev = DEVICE_NR(CURRENT->dev);
+       printk("hd%c: timeout\n", dev+'a');
        if (++CURRENT->errors >= MAX_ERRORS) {
 #ifdef DEBUG
-               printk("hd : too many errors.\n");
+               printk("hd%c: too many errors\n", dev+'a');
 #endif
                end_request(0);
        }
        cli();
-
        hd_request();
+       enable_irq(HD_IRQ);
+}
+
+int do_special_op (unsigned int dev)
+{
+       if (recalibrate[dev]) {
+               recalibrate[dev] = 0;
+               hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+               return reset;
+       }
+       if (!identified[dev]) {
+               identified[dev]  = 1;
+               unmask_intr[dev] = DEFAULT_UNMASK_INTR;
+               mult_req[dev]    = DEFAULT_MULT_COUNT;
+               hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
+               return reset;
+       }
+       if (mult_req[dev] != mult_count[dev]) {
+               hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
+               return reset;
+       }
+       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);
+       }
+       special_op[dev] = 0;
+       return 1;
 }
 
 /*
- * The driver has been modified to enable interrupts a bit more: in order to
- * do this we first (a) disable the timeout-interrupt and (b) clear the
- * device-interrupt. This way the interrupts won't mess with out code (the
- * worst that can happen is that an unexpected HD-interrupt comes in and
- * sets the "reset" variable and starts the timer)
+ * The driver enables interrupts as much as possible.  In order to do this,
+ * (a) the device-interrupt is disabled before entering hd_request(),
+ * and (b) the timeout-interrupt is disabled before the sti().
+ *
+ * Interrupts are still masked (by default) whenever we are exchanging
+ * data/cmds with a drive, because some drives seem to have very poor
+ * tolerance for latency during I/O.  For devices which don't suffer from
+ * that problem (most don't), the unmask_intr[] flag can be set to unmask
+ * other interrupts during data/cmd transfers (by defining DEFAULT_UNMASK_INTR
+ * to 1, or by using "hdparm -u1 /dev/hd?" from the shell).
  */
 static void hd_request(void)
 {
-       unsigned int block,dev;
-       unsigned int sec,head,cyl,track;
-       unsigned int nsect;
+       unsigned int dev, block, nsect, sec, track, head, cyl;
 
        if (CURRENT && CURRENT->dev < 0) return;
-
        if (DEVICE_INTR)
                return;
 repeat:
        timer_active &= ~(1<<HD_TIMER);
        sti();
        INIT_REQUEST;
+       if (reset) {
+               cli();
+               reset_hd();
+               return;
+       }
        dev = MINOR(CURRENT->dev);
        block = CURRENT->sector;
        nsect = CURRENT->nr_sectors;
-       if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
+       if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
 #ifdef DEBUG
-               printk("hd : attempted read for sector %d past end of device at sector %d.\n",
-                       block, hd[dev].nr_sects);
+               if (dev >= (NR_HD<<6))
+                       printk("hd: bad minor number: device=0x%04x\n", CURRENT->dev);
+               else
+                       printk("hd%c: bad access: block=%d, count=%d\n",
+                               (CURRENT->dev>>6)+'a', block, nsect);
 #endif
                end_request(0);
                goto repeat;
        }
        block += hd[dev].start_sect;
        dev >>= 6;
-       sec = block % hd_info[dev].sect + 1;
+       if (special_op[dev]) {
+               if (do_special_op(dev))
+                       goto repeat;
+               return;
+       }
+       sec   = block % hd_info[dev].sect + 1;
        track = block / hd_info[dev].sect;
-       head = track % hd_info[dev].head;
-       cyl = track / hd_info[dev].head;
+       head  = track % hd_info[dev].head;
+       cyl   = track / hd_info[dev].head;
 #ifdef DEBUG
-       printk("hd%c : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
-               dev+'a', cyl, head, sec, CURRENT->buffer);
+       printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
+               dev+'a', (CURRENT->cmd == READ)?"read":"writ",
+               cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
 #endif
        if (!unmask_intr[dev])
                cli();
-       if (reset) {
-               int i;
-
-               for (i=0; i < NR_HD; i++)
-                       special_op[i] = recalibrate[i] = 1;
-               cli(); /* better play it safe, as resets are the last resort */
-               reset_hd();
-               return;
-       }
-       if (special_op[dev]) {  /* we use "special_op" to reduce overhead on r/w */
-               if (recalibrate[dev]) {
-                       recalibrate[dev] = 0;
-                       hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
-                       if (reset)
-                               goto repeat;
-                       return;
-               }       
-               if (!identified[dev]) {
-                       identified[dev]  = 1;
-                       unmask_intr[dev] = DEFAULT_UNMASK_INTR;
-                       mult_req[dev]    = DEFAULT_MULT_COUNT;
-                       hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
-                       if (reset)
-                               goto repeat;
-                       return;
-               }
-               if (mult_req[dev] != mult_count[dev]) {
-                       hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
-                       if (reset)
-                               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;
-               }
-               --special_op[dev];
-       } /* special_op[dev] */
        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);
                if (reset)
                        goto repeat;
-#ifdef DEBUG
-               printk("hd%c: reading %d sectors(%ld-%ld), buffer=%08lx\n",
-                       dev+'a', nsect, CURRENT->sector,
-                       CURRENT->sector+nsect-1, (long) CURRENT->buffer);
-#endif
                return;
        }
        if (CURRENT->cmd == WRITE) {
@@ -783,11 +770,6 @@ repeat:
                        hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
                if (reset)
                        goto repeat;
-#ifdef DEBUG
-               printk("hd%c: writing %d sectors(%ld-%ld), buffer=%08lx\n",
-                       dev+'a', nsect, CURRENT->sector,
-                       CURRENT->sector+nsect-1, (long) CURRENT->buffer);
-#endif
                if (wait_DRQ()) {
                        bad_rw_intr();
                        goto repeat;
@@ -795,9 +777,8 @@ repeat:
                if (mult_count[dev]) {
                        WCURRENT = *CURRENT;
                        multwrite(dev);
-               } else {
+               } else
                        outsw(HD_DATA,CURRENT->buffer,256);
-               }
                return;
        }
        panic("unknown hd-command");
@@ -905,11 +886,11 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                        if (arg > max_mult[dev])
                                err = -EINVAL;  /* out of range for device */
                        else if (mult_req[dev] != mult_count[dev]) {
-                               ++special_op[dev];
+                               special_op[dev] = 1;
                                err = -EBUSY;   /* busy, try again */
                        } else {
                                mult_req[dev] = arg;
-                               ++special_op[dev];
+                               special_op[dev] = 1;
                                err = 0;
                        }
                        restore_flags(flags);
@@ -1045,22 +1026,14 @@ static void hd_geninit(void)
        }
        i = NR_HD;
        while (i-- > 0) {
-               hd[i<<6].nr_sects = 0;
-               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);
-               }
+               /*
+                * 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.
+                */
                hd[i<<6].nr_sects = bios_info[i].head *
                                bios_info[i].sect * bios_info[i].cyl;
                hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
@@ -1068,7 +1041,7 @@ static void hd_geninit(void)
        }
        if (NR_HD) {
                if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
-                       printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
+                       printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
                        NR_HD = 0;
                }
        }
@@ -1094,7 +1067,7 @@ static struct file_operations hd_fops = {
 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
 {
        if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
-               printk("Unable to get major %d for harddisk\n",MAJOR_NR);
+               printk("hd: unable to get major %d for harddisk\n",MAJOR_NR);
                return mem_start;
        }
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
index d64fe7416297674a3c7e02efbf2dd3f719c653c7..226821056304d7b456808868d643ea68df09a3d5 100644 (file)
@@ -514,4 +514,12 @@ int init_module(void)
        return 0;
 }
 
+void cleanup_module(void)
+{
+       if(MOD_IN_USE)
+               printk("lp: busy - remove delayed\n");
+       else
+               unregister_chrdev(LP_MAJOR,"lp");
+}
+
 #endif
index 46925926d253725bcd62d312c5e215c4230da7d7..128075ffeaac9efb8d0ed7041f7bb44f5ff88e97 100644 (file)
@@ -54,7 +54,11 @@ config: configure /usr/include/sys/soundcard.h
        @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
        @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
        @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h
-       @echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\" >> local.h
+       @if [ -x /bin/dnsdomainname ]; then \
+           echo \#define SOUND_CONFIG_DOMAIN \"`dnsdomainname`\"; \
+         else \
+           echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\"; \
+         fi >> local.h
 
 clrconf:
        rm -f local.h .depend
index 463db21ce53a62582661af67e24f5aa1a021e0e7..03ecf30e5b981bcde7824df9c66c102b6dc18ca8 100644 (file)
@@ -612,8 +612,8 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        current->mm->start_code = start_code;
        current->mm->end_data = end_data;
        current->mm->start_stack = bprm->p;
-       current->suid = current->euid = bprm->e_uid;
-       current->sgid = current->egid = bprm->e_gid;
+       current->suid = current->euid = current->fsuid = bprm->e_uid;
+       current->sgid = current->egid = current->fsgid = bprm->e_gid;
 
        /* Calling sys_brk effectively mmaps the pages that we need for the bss and break
           sections */
index 3c94fa3e2bc4f5579b54b3e682d4c6035092e9b5..10e30fafa8a36daaaf2e32978c6218a8dfdd47d9 100644 (file)
@@ -20,6 +20,9 @@
 #include <linux/ext_fs.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int ext_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
        return -EISDIR;
@@ -65,6 +68,7 @@ static int ext_readdir(struct inode * inode, struct file * filp,
        struct dirent * dirent, int count)
 {
        unsigned int i;
+       unsigned int ret;
        off_t offset;
        char c;
        struct buffer_head * bh;
@@ -74,15 +78,23 @@ static int ext_readdir(struct inode * inode, struct file * filp,
                return -EBADF;
        if ((filp->f_pos & 7) != 0)
                return -EBADF;
-       while (filp->f_pos < inode->i_size) {
+       ret = 0;
+       while (!ret && filp->f_pos < inode->i_size) {
                offset = filp->f_pos & 1023;
                bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
                if (!bh) {
                        filp->f_pos += 1024-offset;
                        continue;
                }
+               for (i = 0; i < 1024 && i < offset; ) {
+                       de = (struct ext_dir_entry *) (bh->b_data + i);
+                       if (!de->rec_len)
+                               break;
+                       i += de->rec_len;
+               }
+               offset = i;
                de = (struct ext_dir_entry *) (offset + bh->b_data);
-               while (offset < 1024 && filp->f_pos < inode->i_size) {
+               while (!ret && offset < 1024 && filp->f_pos < inode->i_size) {
                        if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
                            de->rec_len < de->name_len + 8 ||
                            (de->rec_len + (off_t) filp->f_pos - 1) / 1024 > ((off_t) filp->f_pos / 1024)) {
@@ -106,8 +118,8 @@ static int ext_readdir(struct inode * inode, struct file * filp,
                                        put_fs_long(de->inode,&dirent->d_ino);
                                        put_fs_byte(0,i+dirent->d_name);
                                        put_fs_word(i,&dirent->d_reclen);
-                                       brelse(bh);
-                                       return i;
+                                       ret = ROUND_UP(NAME_OFFSET(dirent)+i+1);
+                                       break;
                                }
                        }
                        de = (struct ext_dir_entry *) ((char *) de 
@@ -115,5 +127,5 @@ static int ext_readdir(struct inode * inode, struct file * filp,
                }
                brelse(bh);
        }
-       return 0;
+       return ret;
 }
index 58cdcc463d2860a2735ab14055dbfee0e46ee703..2bba1b06c02b854e9133d506949031927ac6cc9a 100644 (file)
@@ -22,6 +22,9 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int ext2_dir_read (struct inode * inode, struct file * filp,
                            char * buf, int count)
 {
@@ -98,17 +101,21 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
                         struct dirent * dirent, int count)
 {
        unsigned long offset, blk;
-       int i, num;
+       int i, num, stored, dlen;
        struct buffer_head * bh, * tmp, * bha[16];
        struct ext2_dir_entry * de;
        struct super_block * sb;
-       int err;
-       
+       int err, version;
+
        if (!inode || !S_ISDIR(inode->i_mode))
                return -EBADF;
        sb = inode->i_sb;
-       while (filp->f_pos < inode->i_size) {
-               offset = filp->f_pos & (sb->s_blocksize - 1);
+
+       stored = 0;
+       bh = NULL;
+       offset = filp->f_pos & (sb->s_blocksize - 1);
+
+       while (count > 0 && !stored && filp->f_pos < inode->i_size) {
                blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb);
                bh = ext2_bread (inode, blk, 0, &err);
                if (!bh) {
@@ -135,39 +142,78 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
                        }
                }
                
-               de = (struct ext2_dir_entry *) (offset + bh->b_data);
-               while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) {
+revalidate:
+               /* If the dir block has changed since the last call to
+                  readdir(2), then we might be pointing to an invalid dirent
+                  right now.  Scan from the start of the block to make
+                  sure. */
+               for (i = 0; i < sb->s_blocksize && i < offset; ) {
+                       de = (struct ext2_dir_entry *) (bh->b_data + i);
+                       /* It's too expensive to do a full dirent test
+                        * each time round this loop, but we do have
+                        * to test at least that it is non-zero.  A
+                        * failure will be detected in the dirent test
+                        * below. */
+                       if (de->rec_len < EXT2_DIR_REC_LEN(1))
+                               break;
+                       i += de->rec_len;
+               }
+               offset = i;
+               filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | offset;
+               
+               while (count > 0 && filp->f_pos < inode->i_size 
+                      && offset < sb->s_blocksize) {
+                       de = (struct ext2_dir_entry *) (bh->b_data + offset);
                        if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
                                                   bh, offset)) {
+                               /* On error, skip the f_pos to the next block. */
+                               filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
+                                             + sb->s_blocksize;
                                brelse (bh);
-                               return 0;
+                               return stored;
                        }
-                       offset += de->rec_len;
-                       filp->f_pos += de->rec_len;
                        if (de->inode) {
-                               memcpy_tofs (dirent->d_name, de->name,
-                                            de->name_len);
+                               dlen = ROUND_UP(NAME_OFFSET(dirent) 
+                                               + de->name_len + 1);
+                               /* Old libc libraries always use a count of 1. */
+                               if (count == 1 && !stored)
+                                       count = dlen;
+                               if (count < dlen) {
+                                       count = 0;
+                                       break;
+                               }
+
+                               /* We might block in the next section
+                               * if the data destination is
+                               * currently swapped out.  So, use a
+                               * version stamp to detect whether or
+                               * not the directory has been modified
+                               * during the copy operation. */
+                               version = inode->i_version;
+                               i = de->name_len;
+                               memcpy_tofs (dirent->d_name, de->name, i);
                                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);
+                               put_fs_byte (0, dirent->d_name + i);
+                               put_fs_word (i, &dirent->d_reclen);
+                               put_fs_long (dlen, &dirent->d_off);
+                               if (version != inode->i_version)
+                                       goto revalidate;
                                dcache_add(inode, de->name, de->name_len,
                                                 de->inode);
-                               i = de->name_len;
-                               brelse (bh);
-                               if (!IS_RDONLY(inode)) {
-                                       inode->i_atime = CURRENT_TIME;
-                                       inode->i_dirt = 1;
-                               }
-                               return i;
+
+                               stored += dlen;
+                               count -= dlen;
+                               ((char *) dirent) += dlen;
                        }
-                       de = (struct ext2_dir_entry *) ((char *) de +
-                                                       de->rec_len);
+                       offset += de->rec_len;
+                       filp->f_pos += de->rec_len;
                }
+               offset = 0;
                brelse (bh);
        }
        if (!IS_RDONLY(inode)) {
                inode->i_atime = CURRENT_TIME;
                inode->i_dirt = 1;
        }
-       return 0;
+       return stored;
 }
index d1105202b147b547a485dba5a2f03da36c37e561..f56c5404e2db6cdf96b8557ae2975a10eb3f737a 100644 (file)
@@ -318,6 +318,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                         */
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
                        dir->i_dirt = 1;
+                       dir->i_version = ++event;
                        mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        *err = 0;
@@ -923,8 +924,10 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
 
        goto start_up;
 try_again:
-       if (new_bh && new_de)
+       if (new_bh && new_de) {
                ext2_delete_entry(new_de, new_bh);
+               new_dir->i_version = ++event;
+       }
        brelse (old_bh);
        brelse (new_bh);
        brelse (dir_bh);
@@ -1002,6 +1005,7 @@ start_up:
                                         &retval);
        if (!new_bh)
                goto end_rename;
+       new_dir->i_version = ++event;
        /*
         * sanity checking before doing the rename - avoid races
         */
@@ -1015,7 +1019,6 @@ start_up:
         * ok, that's it
         */
        new_de->inode = old_inode->i_ino;
-       new_dir->i_version = ++event;
        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)
index 36993d898cc465a8e322c5ee24f5d0d868bf0538..c05cf56ab9efbe536d0b70db6a31d16042197ea1 100644 (file)
 \f
 /* notation */
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 #define little_ushort(x) (*(unsigned short *) &(x))
 typedef void nonconst;
 
@@ -1345,13 +1348,13 @@ static int hpfs_readdir(struct inode *inode, struct file *filp,
        case 0:
                write_one_dirent(dirent, ".", 1, inode->i_ino, lc);
                filp->f_pos = -1;
-               return 1;
+               return ROUND_UP(NAME_OFFSET(dirent) + 2);
 
        case -1:
                write_one_dirent(dirent, "..", 2,
                                 inode->i_hpfs_parent_dir, lc);
                filp->f_pos = 1;
-               return 2;
+               return ROUND_UP(NAME_OFFSET(dirent) + 3);
 
        case -2:
                return 0;
@@ -1371,7 +1374,7 @@ static int hpfs_readdir(struct inode *inode, struct file *filp,
                write_one_dirent(dirent, de->name, namelen, ino, lc);
                brelse4(&qbh);
 
-               return namelen;
+               return ROUND_UP(NAME_OFFSET(dirent) + namelen + 1);
        }
 }
 
index 3097b65097f59ec3bf6291e50e427b6ba9843d3e..ab7b2160733836146b2fdb6789fea6e079fb9c7e 100644 (file)
@@ -22,6 +22,9 @@
 #include <linux/sched.h>
 #include <linux/locks.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
 
 static struct file_operations isofs_dir_operations = {
@@ -228,7 +231,7 @@ static int isofs_readdir(struct inode * inode, struct file * filp,
                        put_fs_byte(0,i+dirent->d_name);
                        put_fs_word(i,&dirent->d_reclen);
                        brelse(bh);
-                       return i;
+                       return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
                }
              }
        /* We go here for any condition we cannot handle.  We also drop through
index f32a6837a4f35f642312169d2886f5f46dc4fcd6..2a1134495f9d32b5bb3638e3fa2a921a086b1c8f 100644 (file)
@@ -13,6 +13,9 @@
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int minix_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
        return -EISDIR;
@@ -57,7 +60,8 @@ struct inode_operations minix_dir_inode_operations = {
 static int minix_readdir(struct inode * inode, struct file * filp,
        struct dirent * dirent, int count)
 {
-       unsigned int offset,i;
+       unsigned int offset,i,ret;
+       int version;
        char c;
        struct buffer_head * bh;
        struct minix_dir_entry * de;
@@ -68,17 +72,19 @@ static int minix_readdir(struct inode * inode, struct file * filp,
        info = &inode->i_sb->u.minix_sb;
        if (filp->f_pos & (info->s_dirsize - 1))
                return -EBADF;
-       while (filp->f_pos < inode->i_size) {
+       ret = 0;
+       while (!ret && filp->f_pos < inode->i_size) {
                offset = filp->f_pos & 1023;
                bh = minix_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
                if (!bh) {
                        filp->f_pos += 1024-offset;
                        continue;
                }
-               while (offset < 1024 && filp->f_pos < inode->i_size) {
+               while (!ret && offset < 1024 && filp->f_pos < inode->i_size) {
                        de = (struct minix_dir_entry *) (offset + bh->b_data);
                        offset += info->s_dirsize;
                        filp->f_pos += info->s_dirsize;
+retry:
                        if (de->inode) {
                                for (i = 0; i < info->s_namelen; i++)
                                        if ((c = de->name[i]) != 0)
@@ -86,15 +92,17 @@ static int minix_readdir(struct inode * inode, struct file * filp,
                                        else
                                                break;
                                if (i) {
+                                       version = inode->i_version;
                                        put_fs_long(de->inode,&dirent->d_ino);
                                        put_fs_byte(0,i+dirent->d_name);
                                        put_fs_word(i,&dirent->d_reclen);
-                                       brelse(bh);
-                                       return i;
+                                       if (version != inode->i_version)
+                                               goto retry;
+                                       ret = ROUND_UP(NAME_OFFSET(dirent)+i+1);
                                }
                        }
                }
                brelse(bh);
        }
-       return 0;
+       return ret;
 }
index dcd32db29be9e6ca0d51ae87d6442c3ffab4f7e6..3393aaf84b655f8ede4d0ea722adb7c94deb22b9 100644 (file)
@@ -195,6 +195,7 @@ static int minix_add_entry(struct inode * dir,
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
                        for (i = 0; i < info->s_namelen ; i++)
                                de->name[i] = (i < namelen) ? name[i] : 0;
+                       dir->i_version = ++event;
                        mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        break;
@@ -470,11 +471,12 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
        if (inode->i_nlink != 2)
                printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
        de->inode = 0;
+       dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        inode->i_nlink=0;
        inode->i_dirt=1;
-       dir->i_nlink--;
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       dir->i_nlink--;
        dir->i_dirt=1;
        retval = 0;
 end_rmdir:
@@ -523,6 +525,7 @@ repeat:
                inode->i_nlink=1;
        }
        de->inode = 0;
+       dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        dir->i_dirt = 1;
@@ -768,8 +771,10 @@ start_up:
        new_de->inode = old_inode->i_ino;
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
        old_dir->i_dirt = 1;
+       old_dir->i_version = ++event;
        new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
        new_dir->i_dirt = 1;
+       new_dir->i_version = ++event;
        if (new_inode) {
                new_inode->i_nlink--;
                new_inode->i_ctime = CURRENT_TIME;
index 5051a07d7a4ada0617aa90d8d79349fedea9029e..6aa9c02150417198e5699c045e34184ef3341d05 100644 (file)
@@ -14,6 +14,9 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 
 static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
 {
@@ -73,7 +76,7 @@ int msdos_readdir(
                        put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
                        put_fs_byte(0,dirent->d_name+i);
                        put_fs_word(i,&dirent->d_reclen);
-                       return i;
+                       return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
                }
        }
        if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
@@ -110,7 +113,7 @@ int msdos_readdir(
                                memcpy_tofs(dirent->d_name,bufname,i+1);
                                put_fs_word(i,&dirent->d_reclen);
                                brelse(bh);
-                               return i;
+                               return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
                        }
                }
        }
index d8aa8814100142c901c7821c3cc130694bdd7dc3..62a3e082179b709408ccb03070759fdbb899e8f7 100644 (file)
@@ -18,6 +18,9 @@
 
 #include <asm/segment.h>       /* for fs functions */
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int nfs_dir_read(struct inode *, struct file *filp, char *buf,
                        int count);
 static int nfs_readdir(struct inode *, struct file *, struct dirent *, int);
@@ -153,7 +156,7 @@ static int nfs_readdir(struct inode *inode, struct file *filp,
                put_fs_long(entry->fileid, &dirent->d_ino);
                put_fs_word(i, &dirent->d_reclen);
                filp->f_pos = entry->cookie;
-               return i;
+               return ROUND_UP(NAME_OFFSET(dirent)+i+1);
        }
        return 0;
 }
index c95df78073441ead59de169e7bb23babb13fced8..769014f46da1bfdb947b662938563a27fe6dafa7 100644 (file)
@@ -92,7 +92,8 @@ static int proc_fd_dupf(struct inode * inode, struct file * f)
 
        new_f->f_count++;
        current->files->fd[fd] = new_f;
-       f->f_count--;
+       if (!--f->f_count)
+               iput(f->f_inode);
        return 0;
 }
 
index 48b1177e959e079adfba81381eb50cb6791fae33..c86347e4fef656b9cb11ca29f29bdd85a1ab562e 100644 (file)
 #include <asm/segment.h>
 
 /*
- * Count is not yet used: but we'll probably support reading several entries
- * at once in the future. Use count=1 in the library for future expansions.
+ * Count is now a supported feature, but currently only the ext2fs
+ * uses it.  A count value of 1 is supported for compatibility with
+ * earlier libraries, but larger values are supported: count should
+ * indicate the total buffer space available for filling with dirents.
+ * The d_off entry in the dirents will then indicate the offset from
+ * each dirent to the next, and the return value will indicate the
+ * number of bytes written.  All dirents will be written at
+ * word-aligned addresses.  [sct Oct 1994]
  */
 asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
 {
@@ -62,8 +68,10 @@ asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
        }
        if (tmp < 0)
                return -EINVAL;
-       file->f_pos = tmp;
-       file->f_reada = 0;
+       if (tmp != file->f_pos) {
+               file->f_pos = tmp;
+               file->f_reada = 0;
+       }
        return file->f_pos;
 }
 
index ef3c09abb2ee19158717a10eb1c1ee4af4c2061b..14cdf84a10d983f03612fc4d0c69c8e96eb1eea6 100644 (file)
@@ -20,6 +20,9 @@
 #include <linux/sysv_fs.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int sysv_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
        return -EISDIR;
@@ -100,7 +103,7 @@ static int sysv_readdir(struct inode * inode, struct file * filp,
                                        put_fs_byte(0,i+dirent->d_name);
                                        put_fs_word(i,&dirent->d_reclen);
                                        brelse(bh);
-                                       return i;
+                                       return ROUND_UP(NAME_OFFSET(dirent)+i+1);
                                }
                        }
                }
index fca3c2b46484ea31663839f9cba3560d9d1bb962..bfadc8aa88d4186c2c72108c9991dfe6f6eed44a 100644 (file)
@@ -19,6 +19,9 @@
 
 #include "xiafs_mac.h"
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int xiafs_dir_read(struct inode *, struct file *, char *, int);
 static int xiafs_readdir(struct inode *, struct file *, struct dirent *, int);
 
@@ -65,7 +68,7 @@ static int xiafs_dir_read(struct inode * inode,
 static int xiafs_readdir(struct inode * inode, 
                       struct file * filp, struct dirent * dirent, int count)
 {
-    u_int offset, i;
+    u_int offset, i,ret;
     struct buffer_head * bh;
     struct xiafs_direct * de;
 
@@ -73,15 +76,24 @@ static int xiafs_readdir(struct inode * inode,
         return -EBADF;
     if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
         return -EBADF;
-    while (filp->f_pos < inode->i_size) {
+    ret = 0;
+    while (!ret && filp->f_pos < inode->i_size) {
         offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
        bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
        if (!bh) {
            filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
            continue;
        }
+       for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) {
+           de = (struct xiafs_direct *) (bh->b_data + i);
+           if (!de->d_rec_len)
+               break;
+           i += de->d_rec_len;
+       }
+       offset = i;
        de = (struct xiafs_direct *) (offset + bh->b_data);
-       while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
+       
+       while (!ret && offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
            if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
                de->d_rec_len < 12 || 
                (char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
@@ -100,12 +112,12 @@ static int xiafs_readdir(struct inode * inode,
                put_fs_byte(0,i+dirent->d_name);
                put_fs_long(de->d_ino,&dirent->d_ino);
                put_fs_word(i,&dirent->d_reclen);
-               brelse(bh);
                if (!IS_RDONLY (inode)) {
                    inode->i_atime=CURRENT_TIME;                    
                    inode->i_dirt=1;
                }
-               return i;
+               ret = ROUND_UP(NAME_OFFSET(dirent)+i+1);
+               break;
            }
            de = (struct xiafs_direct *) (offset + bh->b_data);
        }
index e401ac625ec1f42b8dfbda5fae8a188f9458013e..3a553f58a00f492f8d5827b66f1821550089fd12 100644 (file)
@@ -71,7 +71,6 @@ struct hd_geometry {
 #define HDIO_SETUNMASKINTR     0x303
 #define HDIO_GETMULTCOUNT      0x304
 #define HDIO_SETMULTCOUNT      0x305
-#define HDIO_SETFEATURE        0x306
 #define HDIO_GETIDENTITY       0x307
 #endif
 
index e53cd0eab711541a52bad3e5db914e784b5dc677..c177902b509d771212348b3b8c9747f574c34f0d 100644 (file)
@@ -289,6 +289,7 @@ extern void stop_tty(struct tty_struct * tty);
 extern void start_tty(struct tty_struct * tty);
 extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
 extern int tty_register_driver(struct tty_driver *driver);
+extern int tty_unregister_driver(struct tty_driver *driver);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
                             int buflen);
 
index c223f14674c571e50d2df80989b6691745794263..dde9ab7babb6b88898915fae7d16982d4a31defe 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/termios.h>
 #include <linux/tqueue.h>
+#include <linux/tty.h>
 #include <linux/serial.h>
 #ifdef CONFIG_INET
 #include <linux/netdevice.h>
@@ -91,6 +92,9 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
        X(unregister_chrdev),
        X(register_blkdev),
        X(unregister_blkdev),
+       X(tty_register_driver),
+       X(tty_unregister_driver),
+       X(tty_std_termios),
 
        /* block device driver support */
        X(block_read),
index f018fc39ebbd1c235ae2738a5d889181e6b5ad8c..2a3e80ae48d216e78501d0a2b1c8442151cfbef0 100644 (file)
@@ -83,6 +83,7 @@
  *             Matt Dillon     :       Yet more small nasties remove from the TCP code
  *                                     (Be very nice to this man if tcp finally works 100%) 8)
  *             Alan Cox        :       BSD accept semantics. 
+ *     Peter De Schrijver      :       ENOTCONN check missing in tcp_sendto().
  *
  *
  * To Fix:
@@ -1221,15 +1222,17 @@ static int tcp_sendto(struct sock *sk, unsigned char *from,
 {
        if (flags & ~(MSG_OOB|MSG_DONTROUTE))
                return -EINVAL;
-       if (addr_len < sizeof(*addr)) 
-               return(-EINVAL);
+       if (!tcp_connected(sk->state))
+               return -ENOTCONN;
+       if (addr_len < sizeof(*addr))
+               return -EINVAL;
        if (addr->sin_family && addr->sin_family != AF_INET) 
-               return(-EINVAL);
+               return -EINVAL;
        if (addr->sin_port != sk->dummy_th.dest) 
-               return(-EISCONN);
+               return -EISCONN;
        if (addr->sin_addr.s_addr != sk->daddr) 
-               return(-EISCONN);
-       return(tcp_write(sk, from, len, nonblock, flags));
+               return -EISCONN;
+       return tcp_write(sk, from, len, nonblock, flags);
 }
 
 
@@ -2238,7 +2241,7 @@ static void tcp_close(struct sock *sk, int timeout)
                                /* The +1 is not needed because the FIN takes up seq
                                   is not read!!! */
                                if(skb->len > 0 && after(skb->h.th->seq + skb->len , sk->copied_seq))
-                                       need_reset = 1;
+                                       need_reset = 0;
                                kfree_skb(skb, FREE_READ);
                        }
                        if(sk->debug)