]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.27pre4 2.3.27pre4
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:28:29 +0000 (15:28 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:28:29 +0000 (15:28 -0500)
25 files changed:
arch/i386/kernel/mca.c
drivers/char/Config.in
drivers/isdn/Config.in
drivers/net/ppp_generic.c
fs/bfs/inode.c
fs/ext2/file.c
fs/proc/Makefile
fs/proc/inode-alloc.txt
fs/proc/kcore.c
fs/proc/root.c
fs/proc/sysvipc.c [deleted file]
fs/romfs/inode.c
include/linux/ipc.h
include/linux/msg.h
include/linux/proc_fs.h
include/linux/sem.h
include/linux/sysctl.h
ipc/msg.c
ipc/sem.c
ipc/util.c
ipc/util.h
kernel/module.c
kernel/resource.c
kernel/sysctl.c
net/core/dev.c

index 0a46cd017e4e199bc195c30c86d272692fead274..86fc022e63d494ae0af527ec782e504b0e0b4fd9 100644 (file)
@@ -29,6 +29,9 @@
  *     David Weinehall March 24th, 1999
  *     - Fixed the output of 'Driver Installed' in /proc/mca/pos
  *     - Made the Integrated Video & SCSI show up even if they have id 0000
+ *
+ *     AV November 9th, 1999
+ *     - switched to regular procfs methods.
  */
 
 #include <linux/types.h>
@@ -105,52 +108,7 @@ static struct MCA_info* mca_info = NULL;
 /*--------------------------------------------------------------------*/
 
 #ifdef CONFIG_PROC_FS
-
 static void mca_do_proc_init(void);
-static int mca_default_procfn(char* buf, int slot);
-
-static ssize_t proc_mca_read(struct file*, char*, size_t, loff_t *);
-
-static struct file_operations proc_mca_operations = {
-       NULL,                   /* llseek */
-       proc_mca_read,          /* read */
-       NULL,                   /* write */
-       NULL,                   /* readdir */
-       NULL,                   /* poll */
-       NULL,                   /* ioctl */
-       NULL,                   /* mmap */
-       NULL,                   /* open */
-       NULL,                   /* flush */
-       NULL,                   /* release */
-       NULL,                   /* fsync */
-       NULL,                   /* fascync */
-       NULL,                   /* check_media_change */
-       NULL,                   /* revalidate */
-       NULL                    /* lock */
-};
-
-static struct inode_operations proc_mca_inode_operations = {
-       &proc_mca_operations,   /* default file-ops */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
 #endif
 
 /*--------------------------------------------------------------------*/
@@ -657,7 +615,8 @@ int mca_isenabled(int slot)
 
 #ifdef CONFIG_PROC_FS
 
-int get_mca_info(char *buf) 
+int get_mca_info(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
 {
        int i, j, len = 0;
 
@@ -667,101 +626,45 @@ int get_mca_info(char *buf)
 
                for(i=0; i<MCA_MAX_SLOT_NR; i++) 
                {
-                       len += sprintf(buf+len, "Slot %d: ", i+1);
+                       len += sprintf(page+len, "Slot %d: ", i+1);
                        for(j=0; j<8; j++) 
-                               len += sprintf(buf+len, "%02x ", mca_info->slot[i].pos[j]);
-                       len += sprintf(buf+len, " %s\n", mca_info->slot[i].name);
+                               len += sprintf(page+len, "%02x ", mca_info->slot[i].pos[j]);
+                       len += sprintf(page+len, " %s\n", mca_info->slot[i].name);
                }
 
                /* Format POS registers of integrated video subsystem */
 
-               len += sprintf(buf+len, "Video : ");
+               len += sprintf(page+len, "Video : ");
                for(j=0; j<8; j++) 
-                       len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]);
-               len += sprintf(buf+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name);
+                       len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]);
+               len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name);
 
                /* Format POS registers of integrated SCSI subsystem */
        
-               len += sprintf(buf+len, "SCSI  : ");
+               len += sprintf(page+len, "SCSI  : ");
                for(j=0; j<8; j++)
-                       len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]);
-               len += sprintf(buf+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name);
+                       len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]);
+               len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name);
        } else {
                /* Leave it empty if MCA not detected - this should *never*
                 * happen! 
                 */
        }
 
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
        return len;
 }
 
-
-/*--------------------------------------------------------------------*/
-
-void __init mca_do_proc_init(void)
-{
-       int i;
-       struct proc_dir_entry* node = NULL;
-
-       if(mca_info == NULL) return;    /* Should never happen */
-
-       proc_register(proc_mca, &(struct proc_dir_entry) {
-               PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
-               1, 0, 0, 0, &proc_mca_inode_operations,});
-
-       proc_register(proc_mca, &(struct proc_dir_entry) {
-               PROC_MCA_MACHINE, 7, "machine", S_IFREG|S_IRUGO,
-               1, 0, 0, 0, &proc_mca_inode_operations,});
-
-       /* Initialize /proc/mca entries for existing adapters */
-
-       for(i = 0; i < MCA_NUMADAPTERS; i++) {
-               mca_info->slot[i].procfn = 0;
-               mca_info->slot[i].dev = 0;
-
-               if(!mca_isadapter(i)) continue;
-
-               node = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
-
-               if(node == NULL) {
-                       printk("Failed to allocate memory for MCA proc-entries!");
-                       return;
-               }
-               memset(node, 0, sizeof(struct proc_dir_entry));
-
-               if(i < MCA_MAX_SLOT_NR) {
-                       node->low_ino = PROC_MCA_SLOT + i;
-                       node->namelen = sprintf(mca_info->slot[i].procname,
-                               "slot%d", i+1);
-               } else if(i == MCA_INTEGVIDEO) {
-                       node->low_ino = PROC_MCA_VIDEO;
-                       node->namelen = sprintf(mca_info->slot[i].procname,
-                               "video");
-               } else if(i == MCA_INTEGSCSI) {
-                       node->low_ino = PROC_MCA_SCSI;
-                       node->namelen = sprintf(mca_info->slot[i].procname,
-                               "scsi");
-               }
-               node->name = mca_info->slot[i].procname;
-               node->mode = S_IFREG | S_IRUGO;
-               node->ops = &proc_mca_inode_operations;
-               proc_register(proc_mca, node);
-       }
-
-} /* mca_do_proc_init() */
-
 /*--------------------------------------------------------------------*/
 
-int mca_default_procfn(char* buf, int slot) 
+static int mca_default_procfn(char* buf, struct MCA_adapter *p)
 {
        int len = 0, i;
-
-       /* This really shouldn't happen... */
-
-       if(mca_info == NULL) {
-               *buf = 0;
-               return 0;
-       }
+       int slot = p - mca_info->slot;
 
        /* Print out the basic information */
 
@@ -772,21 +675,21 @@ int mca_default_procfn(char* buf, int slot)
        } else if(slot == MCA_INTEGVIDEO) {
                len += sprintf(buf+len, "Integrated Video Adapter\n");
        }
-       if(mca_info->slot[slot].name[0]) {
+       if(p->name[0]) {
 
                /* Drivers might register a name without /proc handler... */
 
                len += sprintf(buf+len, "Adapter Name: %s\n",
-                       mca_info->slot[slot].name);
+                       p->name);
        } else {
                len += sprintf(buf+len, "Adapter Name: Unknown\n");
        }
        len += sprintf(buf+len, "Id: %02x%02x\n",
-               mca_info->slot[slot].pos[1], mca_info->slot[slot].pos[0]);
+               p->pos[1], p->pos[0]);
        len += sprintf(buf+len, "Enabled: %s\nPOS: ",
                mca_isenabled(slot) ? "Yes" : "No");
        for(i=0; i<8; i++) {
-               len += sprintf(buf+len, "%02x ", mca_info->slot[slot].pos[i]);
+               len += sprintf(buf+len, "%02x ", p->pos[i]);
        }
        len += sprintf(buf+len, "\nDriver Installed: %s",
                mca_is_adapter_used(slot) ? "Yes" : "No");
@@ -796,111 +699,80 @@ int mca_default_procfn(char* buf, int slot)
        return len;
 } /* mca_default_procfn() */
 
-static int get_mca_machine_info(char* buf) 
+static int get_mca_machine_info(char* page, char **start, off_t off,
+                                int count, int *eof, void *data)
 {
        int len = 0;
 
-       len += sprintf(buf+len, "Model Id: 0x%x\n", machine_id);
-       len += sprintf(buf+len, "Submodel Id: 0x%x\n", machine_submodel_id);
-       len += sprintf(buf+len, "BIOS Revision: 0x%x\n", BIOS_revision);
+       len += sprintf(page+len, "Model Id: 0x%x\n", machine_id);
+       len += sprintf(page+len, "Submodel Id: 0x%x\n", machine_submodel_id);
+       len += sprintf(page+len, "BIOS Revision: 0x%x\n", BIOS_revision);
 
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
        return len;
 }
 
-static int mca_fill(char* page, int pid, int type, char** start,
-       loff_t *offset, int length)
+static int mca_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
 {
+       struct MCA_adapter *p = (struct MCA_adapter *)data;
        int len = 0;
-       int slot = 0;
-
-       switch(type) {
-               case PROC_MCA_REGISTERS:
-                       return get_mca_info(page);
-               case PROC_MCA_MACHINE:
-                       return get_mca_machine_info(page);
-               case PROC_MCA_VIDEO:
-                       slot = MCA_INTEGVIDEO;
-                       break;
-               case PROC_MCA_SCSI:
-                       slot = MCA_INTEGSCSI;
-                       break;
-               default:
-                       if(type < PROC_MCA_SLOT || type >= PROC_MCA_LAST) {
-                               return -EBADF;
-                       }
-                       slot = type - PROC_MCA_SLOT;
-                       break;
-       }
-
-       /* If we made it here, we better have a valid slot */
 
        /* Get the standard info */
 
-       len = mca_default_procfn(page, slot);
+       len = mca_default_procfn(page, p);
 
        /* Do any device-specific processing, if there is any */
 
-       if(mca_info->slot[slot].procfn) {
-               len += mca_info->slot[slot].procfn(page+len, slot,
-                       mca_info->slot[slot].dev);
+       if(p->procfn) {
+               len += p->procfn(page+len, p-mca_info->slot, p->dev);
        }
-
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
        return len;
-} /* mca_fill() */
+} /* mca_read_proc() */
 
-/* Blatantly stolen from fs/proc/array.c, and thus is probably overkill */ 
-
-#define PROC_BLOCK_SIZE        (3*1024)
+/*--------------------------------------------------------------------*/
 
-static ssize_t proc_mca_read(struct file* file,
-       char* buf, size_t count, loff_t *ppos)
+void __init mca_do_proc_init(void)
 {
-       unsigned long page;
-       char *start;
-       int length;
-       int end;
-       unsigned int type, pid;
-       struct proc_dir_entry *dp;
-       struct inode *inode = file->f_dentry->d_inode;
-
-       if(count < 0)
-               return -EINVAL;
-       if(count > PROC_BLOCK_SIZE)
-               count = PROC_BLOCK_SIZE;
-       if(!(page = __get_free_page(GFP_KERNEL)))
-               return -ENOMEM;
-       type = inode->i_ino;
-       pid = type >> 16;
-       type &= 0x0000ffff;
-       start = NULL;
-       dp = (struct proc_dir_entry *) inode->u.generic_ip;
-       length = mca_fill((char *) page, pid, type,
-                         &start, ppos, count);
-       if(length < 0) {
-               free_page(page);
-               return length;
-       }
-       if(start != NULL) {
-               /* We have had block-adjusting processing! */
+       int i;
+       struct proc_dir_entry* node = NULL;
+       struct MCA_adapter *p;
 
-               copy_to_user(buf, start, length);
-               *ppos += length;
-               count = length;
-       } else {
-               /* Static 4kB (or whatever) block capacity */
+       if(mca_info == NULL) return;    /* Should never happen */
+
+       create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL);
+       create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL);
+
+       /* Initialize /proc/mca entries for existing adapters */
+
+       for(i = 0; i < MCA_NUMADAPTERS; i++) {
+               p = &mca_info->slot[i];
+               p->procfn = 0;
+
+               if(i < MCA_MAX_SLOT_NR) sprintf(p->procname,"slot%d", i+1);
+               else if(i == MCA_INTEGVIDEO) sprintf(p->procname,"video");
+               else if(i == MCA_INTEGSCSI) sprintf(p->procname,"scsi");
 
-               if(*ppos >= length) {
-                       free_page(page);
-                       return 0;
+               if(!mca_isadapter(i)) continue;
+
+               node = create_proc_read_entry(p->procname, 0, proc_mca,
+                                               mca_read_proc, (void *)p);
+
+               if(node == NULL) {
+                       printk("Failed to allocate memory for MCA proc-entries!");
+                       return;
                }
-               if(count + *ppos > length)
-                       count = length - *ppos;
-               end = count + *ppos;
-               copy_to_user(buf, (char *) page + *ppos, count);
-               *ppos = end;
        }
-       free_page(page);
-       return count;
-} /* proc_mca_read() */
+
+} /* mca_do_proc_init() */
 
 #endif
index 33ac64891f163475e8c502d55a683bfc4a237669..540217fa227a686a0dd59e085598b077f2009116 100644 (file)
@@ -6,7 +6,7 @@ comment 'Character devices'
 
 bool 'Virtual terminal' CONFIG_VT
 if [ "$CONFIG_VT" = "y" ]; then
-  bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
+   bool '  Support for console on virtual terminal' CONFIG_VT_CONSOLE
 fi
 tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
 if [ "$CONFIG_SERIAL" = "y" ]; then
@@ -22,103 +22,101 @@ if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
 fi
 bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
 if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
-   tristate 'Comtrol Rocketport support' CONFIG_ROCKETPORT
-   tristate 'Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
+   tristate '  Comtrol Rocketport support' CONFIG_ROCKETPORT
+   tristate '  Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
    if [ "$CONFIG_DIGIEPCA" = "n" ]; then
-      tristate 'Digiboard PC/Xx Support' CONFIG_DIGI
+      tristate '  Digiboard PC/Xx Support' CONFIG_DIGI
    fi
-   tristate 'Cyclades async mux support' CONFIG_CYCLADES
+   tristate '  Cyclades async mux support' CONFIG_CYCLADES
    if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then
-      bool '  Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
+      bool '    Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
    fi
-   bool 'Stallion multiport serial support' CONFIG_STALDRV
+   bool '  Stallion multiport serial support' CONFIG_STALDRV
    if [ "$CONFIG_STALDRV" = "y" ]; then
-     tristate '  Stallion EasyIO or EC8/32 support' CONFIG_STALLION
-     tristate '  Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
+     tristate '    Stallion EasyIO or EC8/32 support' CONFIG_STALLION
+     tristate '    Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
    fi
-   tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8
-   tristate 'Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
-   tristate 'Specialix IO8+ card support' CONFIG_SPECIALIX
+   tristate '  SDL RISCom/8 card support' CONFIG_RISCOM8
+   tristate '  Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
+   tristate '  Specialix IO8+ card support' CONFIG_SPECIALIX
    if [ "$CONFIG_SPECIALIX" != "n" ]; then
-     bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
+      bool '  Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
    fi 
-   tristate 'Specialix SX (and SI) card support' CONFIG_SX
-   tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL
+   tristate '  Specialix SX (and SI) card support' CONFIG_SX
+   tristate '  Hayes ESP serial port support' CONFIG_ESPSERIAL
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-       dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m
+      dep_tristate '  Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m
    fi
-   dep_tristate 'Microgate SyncLink card support' CONFIG_SYNCLINK m
-   dep_tristate 'HDLC line discipline support' CONFIG_N_HDLC m
+   dep_tristate '  Microgate SyncLink card support' CONFIG_SYNCLINK m
+   dep_tristate '  HDLC line discipline support' CONFIG_N_HDLC m
 fi
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-       int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+   int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
 if [ "$CONFIG_PARPORT" != "n" ]; then
-  dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
-  if [ "$CONFIG_PRINTER" != "n" ]; then
-    bool '  Support for console on line printer' CONFIG_LP_CONSOLE
-  fi
-  dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
+   dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+   if [ "$CONFIG_PRINTER" != "n" ]; then
+      bool '  Support for console on line printer' CONFIG_LP_CONSOLE
+   fi
+   dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
 fi
 
 mainmenu_option next_comment
 comment 'Mice'
 tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
 if [ "$CONFIG_BUSMOUSE" != "n" ]; then
-  dep_tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
-  dep_tristate 'Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
-  dep_tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
-  if [ "$CONFIG_ADB" = "y" ]; then
-    dep_tristate 'Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
-  fi
+   dep_tristate '  ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
+   dep_tristate '  Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
+   dep_tristate '  Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
+   if [ "$CONFIG_ADB" = "y" ]; then
+      dep_tristate '  Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
+   fi
 fi
 
 tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
 if [ "$CONFIG_MOUSE" != "n" ]; then
-       bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
-       tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
-       tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
+   bool '  PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+   tristate '  C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
+   tristate '  PC110 digitizer pad support' CONFIG_PC110_PAD
 fi
 endmenu
 
 tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
 if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
-  bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
-  if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
-    comment '  Edit configuration parameters in ./include/linux/tpqic02.h!'
-  else
-    comment '  Setting runtime QIC-02 configuration is done with qic02conf'
-    comment '  from the tpqic02-support package.  It is available at'
-    comment '  metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
-  fi
-  dep_tristate 'Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV
-  dep_tristate '  Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN
+   bool '  Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
+   if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
+      comment '  Edit configuration parameters in ./include/linux/tpqic02.h!'
+   else
+      comment '  Setting runtime QIC-02 configuration is done with qic02conf'
+      comment '  from the tpqic02-support package.  It is available at'
+      comment '  metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
+   fi
 fi
 
+mainmenu_option next_comment
+comment 'Watchdog Cards'
 bool 'Watchdog Timer Support'  CONFIG_WATCHDOG
 if [ "$CONFIG_WATCHDOG" != "n" ]; then
-  mainmenu_option next_comment
-  comment 'Watchdog Cards'
-  bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
-  tristate '  WDT Watchdog timer' CONFIG_WDT
-  if [ "$CONFIG_WDT" != "n" ]; then
-     bool '    WDT501 features' CONFIG_WDT_501
-     if [ "$CONFIG_WDT_501" = "y" ]; then
+   bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
+   tristate '  WDT Watchdog timer' CONFIG_WDT
+   if [ "$CONFIG_WDT" != "n" ]; then
+      bool '    WDT501 features' CONFIG_WDT_501
+      if [ "$CONFIG_WDT_501" = "y" ]; then
          bool '      Fan Tachometer' CONFIG_WDT_501_FAN
-     fi
-  fi
-  tristate '  Software Watchdog' CONFIG_SOFT_WATCHDOG
-  tristate '  Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
-  tristate '  Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
-  endmenu
+      fi
+   fi
+   tristate '  Software Watchdog' CONFIG_SOFT_WATCHDOG
+   tristate '  Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
+   tristate '  Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
 fi
+endmenu
 
 
 tristate '/dev/nvram support' CONFIG_NVRAM
 bool 'Enhanced Real Time Clock Support' CONFIG_RTC
 if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then
-  bool 'Tadpole ANA H8 Support'  CONFIG_H8
+   bool 'Tadpole ANA H8 Support'  CONFIG_H8
 fi
 
 mainmenu_option next_comment
@@ -126,68 +124,73 @@ comment 'Video For Linux'
 
 tristate 'Video For Linux' CONFIG_VIDEO_DEV
 if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
-  dep_tristate 'ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
-  dep_tristate 'AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then
-    hex '  RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
-  fi
-  dep_tristate 'AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then
-    hex '  RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c
-  fi
-  dep_tristate 'Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
-    hex '  Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
-  fi
-  dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
-    hex '  GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
-  fi
-  dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
-  dep_tristate 'TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then
-    hex '  Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590
-  fi
-  dep_tristate 'Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
-    hex '  Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350
-  fi
-  if [ "$CONFIG_PCI" != "n" ]; then
-    dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
-  fi
-  if [ "$CONFIG_PARPORT" != "n" ]; then
-    dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
-    dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
-  fi
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    if [ "$CONFIG_SGI" = "y" ]; then
-      dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV
-    fi
-  fi
-  dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_PMAC" = "y" ]; then
-    dep_tristate 'PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
-  fi
-  dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
-  dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
-    hex '  SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
-  fi
-  dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_PROC_FS" = "y" ]; then
+   dep_tristate '  I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT
+   comment 'Radio/Video Adapters'
+   dep_tristate '  ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
+   dep_tristate '  AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then
+      hex '  RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
+   fi
+   dep_tristate '  AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then
+      hex '    RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c
+   fi
+   dep_tristate '  Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
+      hex '    Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
+   fi
+   if [ "$CONFIG_PCI" != "n" ]; then
+      dep_tristate '  BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+   fi
+   dep_tristate '  GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
+      hex '    GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
+   fi
+   dep_tristate '  Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
+   dep_tristate '  Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_PMAC" = "y" ]; then
+      dep_tristate '  PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
+   fi
+   if [ "$CONFIG_PARPORT" != "n" ]; then
+      dep_tristate '  Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        dep_tristate '  QuickCam Colour Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
+      fi
+   fi
+   dep_tristate '  SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
+   dep_tristate '  SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
+      hex '    SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
+   fi
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      if [ "$CONFIG_SGI" = "y" ]; then
+        dep_tristate '  SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV
+      fi
+   fi
+   dep_tristate '  TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then
+      hex '    Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590
+   fi
+   dep_tristate '  Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
+      hex '    Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350
+   fi
+   dep_tristate '  Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_PROC_FS" = "y" ]; then
       if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then
-       bool '  Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS
+        bool '    Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS
       fi
-  fi
-  if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then
-    hex '  Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316
-    int '  Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500
-  fi
-  dep_tristate 'Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
-    hex '  ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
-  fi
-  dep_tristate 'IIC on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT
+   fi
+   if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then
+      hex '  Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316
+      int '  Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500
+   fi
+   dep_tristate '  Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
+      hex '    ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
+   fi
+   dep_tristate '  Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV
+   dep_tristate '    Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN
 fi
 
 endmenu
@@ -197,7 +200,7 @@ comment 'Joystick support'
 
 tristate 'Joystick support' CONFIG_JOYSTICK
 if [ "$CONFIG_JOYSTICK" != "n" ]; then
-  source drivers/char/joystick/Config.in
+   source drivers/char/joystick/Config.in
 fi
 endmenu
 
@@ -210,15 +213,15 @@ mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
 tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
 if [ "$CONFIG_FTAPE" != "n" ]; then
-  source drivers/char/ftape/Config.in
+   source drivers/char/ftape/Config.in
 fi
 endmenu
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
-  if [ "$CONFIG_DRM" = "y" ]; then
-    dep_tristate '   3dlabs GMX 2000' CONFIG_DRM_GAMMA m
-  fi
+   bool 'Direct Rendering Manager (XFree86 DRI support) (EXPERIMENTAL)' CONFIG_DRM
+   if [ "$CONFIG_DRM" = "y" ]; then
+      dep_tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA m
+   fi
 fi
 
 endmenu
index e88f5da946f9923bb12a477ce05360671c567952..98b11349a4b8af81cf30811c2148219c8c4348cb 100644 (file)
@@ -2,78 +2,78 @@
 # ISDN device configuration
 #
 if [ "$CONFIG_INET" != "n" ]; then
-  bool 'Support synchronous PPP' CONFIG_ISDN_PPP
-  if [ "$CONFIG_ISDN_PPP" != "n" ]; then
-    bool 'Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
-    bool 'Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
-  fi
+   bool '  Support synchronous PPP' CONFIG_ISDN_PPP
+   if [ "$CONFIG_ISDN_PPP" != "n" ]; then
+      bool '    Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
+      bool '    Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
+   fi
 fi
-bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO
+bool '  Support audio via ISDN' CONFIG_ISDN_AUDIO
 if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then
-  bool 'Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
+   bool '    Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
 fi
-bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
-if [ "$CONFIG_X25" != "n" ]; then
-  bool 'X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25
+bool '  Support isdn diversion services' CONFIG_ISDN_DIVERSION
+if [ "$CONFIG_X25" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   bool '  X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25
 fi
-dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
-dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
-dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
-dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
+dep_tristate '  ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
+dep_tristate '  isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
+dep_tristate '  PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
+dep_tristate '  HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
-    bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
-    if [ "$CONFIG_HISAX_EURO" != "n" ]; then
-           bool 'Support for german chargeinfo' CONFIG_DE_AOC
-           bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
-           bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
-    fi
-    bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
-    bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
-    bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
-    bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
-    bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
-    bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
-    bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
-    bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
-    bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
-    bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
-    bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
-    bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
-    bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
-    bool 'HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
-    bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
-    bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
-    bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
-    bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
-    bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
-    bool 'HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
-    bool 'HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
-    bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
-    bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
-    bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
-    bool 'HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
-    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-        bool 'HiSax Support for Winbond W6692 based cards (EXPERIMENTAL)' CONFIG_HISAX_W6692
-#      bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
-       if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-               bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
-       fi
-    fi
+   bool '    HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
+   if [ "$CONFIG_HISAX_EURO" != "n" ]; then
+      bool '      Support for german chargeinfo' CONFIG_DE_AOC
+      bool '      Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+      bool '      Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
+   fi
+   bool '    HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
+   bool '    HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
+   bool '    HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+   bool '    HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
+   bool '    HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
+   bool '    HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+   bool '    HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+   bool '    HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
+   bool '    HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
+   bool '    HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+   bool '    HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
+   bool '    HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
+   bool '    HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
+   bool '    HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
+   bool '    HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
+   bool '    HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
+   bool '    HiSax Support for MIC card' CONFIG_HISAX_MIC
+   bool '    HiSax Support for NETjet card' CONFIG_HISAX_NETJET
+   bool '    HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
+   bool '    HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
+   bool '    HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+   bool '    HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
+   bool '    HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+   bool '    HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
+   bool '    HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      bool '    HiSax Support for Winbond W6692 based cards (EXPERIMENTAL)' CONFIG_HISAX_W6692
+#      bool '    HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+      if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+        bool '    HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+      fi
+   fi
 fi
-if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-       dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
-       dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   dep_tristate '  Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
+   dep_tristate '  IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
 fi
-dep_tristate 'Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+dep_tristate '  Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
-    bool 'Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+   bool '    Eicon S, SX, SCOM, Quadro, S2M support' CONFIG_ISDN_DRV_EICON_ISA
 fi
-dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
+dep_tristate '  AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
-    bool 'AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
-    bool 'AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
-    bool 'AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
-    bool 'AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
-    bool 'AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
-    bool 'Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
+   bool '    AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
+   bool '    AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
+   bool '    AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
+   bool '    AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+   bool '    AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
+   bool '    Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
 fi
index d560a32ea8a832f2d8050e9d57d2a7fc031f862c..860ecabd6dac9aa43e6c3bca20940368587d4250 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/poll.h>
index 8267eae4b8418fc067d4f0b48c98e799d5cdeabe..c0ee15dc4ec46d83d05d19b4790f9baa3776ae7b 100644 (file)
@@ -263,7 +263,7 @@ static struct super_block * bfs_read_super(struct super_block * s,
        struct buffer_head * bh;
        struct bfs_super_block * bfs_sb;
        struct inode * inode;
-       int i, imap_len;
+       int i, imap_len, bmap_len;
 
        MOD_INC_USE_COUNT;
        lock_super(s);
@@ -295,9 +295,11 @@ static struct super_block * bfs_read_super(struct super_block * s,
        s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
                        + BFS_ROOT_INO - 1;
 
-       s->su_bmap = kmalloc(sizeof(struct bfs_bmap) * s->su_lasti, GFP_KERNEL);
+       bmap_len = sizeof(struct bfs_bmap) * s->su_lasti;
+       s->su_bmap = kmalloc(bmap_len, GFP_KERNEL);
        if (!s->su_bmap)
                goto out;
+       memset(s->su_bmap, 0, bmap_len);
        imap_len = s->su_lasti/8 + 1;
        s->su_imap = kmalloc(imap_len, GFP_KERNEL);
        if (!s->su_imap) {
index 608b04da1db7ec6702250f5050beaf8e4a1c80fc..987b55f94e917601dda24e59d10621e0930eeb42 100644 (file)
@@ -62,6 +62,8 @@ static long long ext2_file_lseek(
                case 1:
                        offset += file->f_pos;
        }
+       if (offset<0)
+               return -EINVAL;
        if (((unsigned long long) offset >> 32) != 0) {
                if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
                        return -EINVAL;
index bb1608b0a9c02b87b3c3d5fbf9f71decac93a68c..8ff6cd5223d4e6c1223321ad24a6c5a148433073 100644 (file)
@@ -9,7 +9,7 @@
 
 O_TARGET := proc.o
 O_OBJS   := inode.o root.o base.o generic.o array.o \
-               kmsg.o proc_tty.o sysvipc.o proc_misc.o kcore.o
+               kmsg.o proc_tty.o proc_misc.o kcore.o
 ifdef CONFIG_OMIRR
 O_OBJS   := $(O_OBJS) omirr.o
 endif
index 440d3baf8e0597c7d8371b7305af1b8001c1b645..748b2d3332edf11349d47333c15cd965c898ff93 100644 (file)
@@ -1,50 +1,19 @@
-Inode allocations in the proc-fs (hex-numbers):
+Current inode allocations in the proc-fs (hex-numbers):
 
   00000000             reserved
-  00000001-00000fff    static entries
+  00000001-00000fff    static entries  (goners)
        001             root-ino
-       002             load-avg
-       003             uptime
-       ...
-       080             net/*
-       ...
        100             scsi/*
        ...
-       xxx             mca/*
-       ...
-       yyy             bus/*
-       ...
        fff             end
 
   00001000-00001fff    dynamic entries
-
   00002000-00002fff    openprom entries
-
   0001xxxx-7fffxxxx    pid-dir entries for pid 1-7fff
-      0000             unused
-      0001             unused
-      0002             pid
-      0003             pid/status
-       ...
-      0008             pid/fd
-       ...
-      00xx-00ff                unused
-      01xx             pid/fd/* for fd 0-ff
-       ...
-      01ff             end
-      0200-ffff                unused
-
   80000000-ffffffff    unused
 
-
-
-New allocation:
-
-  00000000-0000ffff    unchanged
-
-  0001xxxx-7fffxxxx    pid-dir entries for pid 1-7fff
-      0000-00ff                unchanged
-      0100-7fff                unused
-      8000-ffff                pid/fd/* for fd 0-7fff
-
-  80000000-ffffffff    unchanged
+Goals:
+       a) the only static inumber that will stay is root's.
+       b) scsi should go dynamic.
+       c) once we'll split the thing into several virtual filesystems we
+       will get rid of magical ranges (and this file, BTW).
index b50a00b602d2b8ede4e94b31cad62d29dc6c4705..db052fc63004692a52c29941a3603fbb9eaf0604 100644 (file)
@@ -143,7 +143,7 @@ static char *storenote(struct memelfnote *men, char *bufp)
  * store an ELF coredump header in the supplied buffer
  * - assume the memory image is the size specified
  */
-static void elf_kcore_store_hdr(char *bufp, size_t size, off_t dataoff)
+static void elf_kcore_store_hdr(char *bufp)
 {
        struct elf_prstatus prstatus;   /* NT_PRSTATUS */
        struct elf_prpsinfo psinfo;     /* NT_PRPSINFO */
@@ -154,65 +154,86 @@ static void elf_kcore_store_hdr(char *bufp, size_t size, off_t dataoff)
 
        /* acquire an ELF header block from the buffer */
        elf = (struct elfhdr *) bufp;
-       bufp += sizeof(*elf);
-       offset += sizeof(*elf);
+       bufp += sizeof(struct elfhdr);
+       offset += sizeof(struct elfhdr);
 
        /* set up header */
        memcpy(elf->e_ident,ELFMAG,SELFMAG);
        elf->e_ident[EI_CLASS]  = ELF_CLASS;
        elf->e_ident[EI_DATA]   = ELF_DATA;
        elf->e_ident[EI_VERSION]= EV_CURRENT;
-       memset(elf->e_ident+EI_PAD,0,EI_NIDENT-EI_PAD);
+       memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
 
        elf->e_type     = ET_CORE;
        elf->e_machine  = ELF_ARCH;
        elf->e_version  = EV_CURRENT;
        elf->e_entry    = 0;
-       elf->e_phoff    = sizeof(*elf);
+       elf->e_phoff    = sizeof(struct elfhdr);
        elf->e_shoff    = 0;
        elf->e_flags    = 0;
-       elf->e_ehsize   = sizeof(*elf);
+       elf->e_ehsize   = sizeof(struct elfhdr);
        elf->e_phentsize= sizeof(struct elf_phdr);
-       elf->e_phnum    = 2;                    /* no. of segments */
+       elf->e_phnum    = 1;    /* no. of segments  = 1 + Nmodules */
        elf->e_shentsize= 0;
        elf->e_shnum    = 0;
        elf->e_shstrndx = 0;
 
        /* acquire an ELF program header blocks from the buffer for notes */
        nhdr = (struct elf_phdr *) bufp;
-       bufp += sizeof(*nhdr);
-       offset += sizeof(*nhdr);
+       bufp += sizeof(struct elf_phdr);
+       offset += sizeof(struct elf_phdr);
 
        /* store program headers for notes dump */
        nhdr->p_type    = PT_NOTE;
        nhdr->p_offset  = 0;
        nhdr->p_vaddr   = 0;
        nhdr->p_paddr   = 0;
+       nhdr->p_filesz  = 0;
        nhdr->p_memsz   = 0;
        nhdr->p_flags   = 0;
        nhdr->p_align   = 0;
 
        /* acquire an ELF program header blocks from the buffer for data */
        dhdr = (struct elf_phdr *) bufp;
-       bufp += sizeof(*dhdr);
-       offset += sizeof(*dhdr);
+       bufp += sizeof(struct elf_phdr);
+       offset += sizeof(struct elf_phdr);
 
        /* store program headers for data dump */
        dhdr->p_type    = PT_LOAD;
        dhdr->p_flags   = PF_R|PF_W|PF_X;
-       dhdr->p_offset  = dataoff;
+       dhdr->p_offset  = PAGE_SIZE;
        dhdr->p_vaddr   = PAGE_OFFSET;
        dhdr->p_paddr   = __pa(PAGE_OFFSET);
-       dhdr->p_filesz  = size;
-       dhdr->p_memsz   = size;
+       dhdr->p_filesz  = ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE);
+       dhdr->p_memsz   = ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE);
        dhdr->p_align   = PAGE_SIZE;
 
+#ifdef CONFIG_MODULES
+       {
+               struct module *m;
+               for (m=module_list; m; m=m->next) {
+                       dhdr = (struct elf_phdr *) bufp;
+                       bufp += sizeof(struct elf_phdr);
+                       offset += sizeof(struct elf_phdr);
+
+                       dhdr->p_type    = PT_LOAD;
+                       dhdr->p_flags   = PF_R|PF_W|PF_X;
+                       dhdr->p_offset  = (unsigned long)m - PAGE_OFFSET + PAGE_SIZE;
+                       dhdr->p_vaddr   = (unsigned long)m;
+                       dhdr->p_paddr   = __pa(m);
+                       dhdr->p_filesz  = m->size;
+                       dhdr->p_memsz   = m->size;
+                       dhdr->p_align   = 0;
+                       elf->e_phnum++;
+               }
+       }
+#endif
+
        /*
         * Set up the notes in similar form to SVR4 core dumps made
         * with info from their /proc.
         */
        nhdr->p_offset  = offset;
-       nhdr->p_filesz  = 0;
 
        /* set up the process status */
        notes[0].name = "CORE";
@@ -289,7 +310,7 @@ ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
 
                /* create a header */
                memset(page,0,PAGE_SIZE);
-               elf_kcore_store_hdr(page,size-PAGE_SIZE,PAGE_SIZE);
+               elf_kcore_store_hdr(page);
 
                /* copy data to the users buffer */
                copy_to_user(buffer,page,tsz);
index 6fb724922a0614723cb32af2c6e4af6a1caa2168..65feea14221eb4816851c0117c92cbb36188b4d9 100644 (file)
@@ -93,8 +93,7 @@ struct proc_dir_entry proc_root = {
        &proc_root, NULL
 };
 
-struct proc_dir_entry *proc_net, *proc_bus, *proc_sysvipc,
-                     *proc_root_fs, *proc_root_driver;
+struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
 
 #ifdef CONFIG_MCA
 struct proc_dir_entry *proc_mca;
@@ -226,6 +225,73 @@ static int make_inode_number(void)
        return PROC_DYNAMIC_FIRST + i;
 }
 
+int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+       struct inode *inode = dentry->d_inode;
+       struct proc_dir_entry * de;
+       char    *page;
+       int len = 0;
+
+       de = (struct proc_dir_entry *) inode->u.generic_ip;
+       if (!de)
+               return -ENOENT;
+       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
+
+       if (de->readlink_proc)
+               len = de->readlink_proc(de, page);
+
+       if (len > buflen)
+               len = buflen;
+
+       copy_to_user(buffer, page, len);
+       free_page((unsigned long) page);
+       return len;
+}
+
+struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow)
+{
+       struct inode *inode = dentry->d_inode;
+       struct proc_dir_entry * de;
+       char    *page;
+       struct dentry *d;
+       int len = 0;
+
+       de = (struct proc_dir_entry *) inode->u.generic_ip;
+       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+               return NULL;
+
+       if (de->readlink_proc)
+               len = de->readlink_proc(de, page);
+
+       d = lookup_dentry(page, base, follow);
+       free_page((unsigned long) page);
+       return d;
+}
+
+static struct inode_operations proc_link_inode_operations = {
+       NULL,                   /* no file-ops */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       proc_readlink,          /* readlink */
+       proc_follow_link,       /* follow_link */
+       NULL,                   /* get_block */
+       NULL,                   /* readpage */
+       NULL,                   /* writepage */
+       NULL,                   /* flushpage */
+       NULL,                   /* truncate */
+       NULL,                   /* permission */
+       NULL,                   /* smap */
+       NULL                    /* revalidate */
+};
+
 int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
        int     i;
@@ -338,50 +404,6 @@ static struct dentry * proc_self_follow_link(struct dentry *dentry,
        return lookup_dentry(tmp, base, follow);
 }      
 
-int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
-       struct inode *inode = dentry->d_inode;
-       struct proc_dir_entry * de;
-       char    *page;
-       int len = 0;
-
-       de = (struct proc_dir_entry *) inode->u.generic_ip;
-       if (!de)
-               return -ENOENT;
-       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-               return -ENOMEM;
-
-       if (de->readlink_proc)
-               len = de->readlink_proc(de, page);
-
-       if (len > buflen)
-               len = buflen;
-
-       copy_to_user(buffer, page, len);
-       free_page((unsigned long) page);
-       return len;
-}
-
-struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow)
-{
-       struct inode *inode = dentry->d_inode;
-       struct proc_dir_entry * de;
-       char    *page;
-       struct dentry *d;
-       int len = 0;
-
-       de = (struct proc_dir_entry *) inode->u.generic_ip;
-       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-               return NULL;
-
-       if (de->readlink_proc)
-               len = de->readlink_proc(de, page);
-
-       d = lookup_dentry(page, base, follow);
-       free_page((unsigned long) page);
-       return d;
-}
-
 static struct inode_operations proc_self_inode_operations = {
        NULL,                   /* no file-ops */
        NULL,                   /* create */
@@ -405,29 +427,6 @@ static struct inode_operations proc_self_inode_operations = {
        NULL                    /* revalidate */
 };
 
-static struct inode_operations proc_link_inode_operations = {
-       NULL,                   /* no file-ops */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       proc_readlink,          /* readlink */
-       proc_follow_link,       /* follow_link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
-
 static struct proc_dir_entry proc_root_self = {
        0, 4, "self",
        S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
@@ -450,7 +449,7 @@ void __init proc_root_init(void)
        proc_register(&proc_root, &proc_root_self);
        proc_net = create_proc_entry("net", S_IFDIR, 0);
 #ifdef CONFIG_SYSVIPC
-       proc_sysvipc = create_proc_entry("sysvipc", S_IFDIR, 0);
+       create_proc_entry("sysvipc", S_IFDIR, 0);
 #endif
 #ifdef CONFIG_SYSCTL
        proc_sys_root = create_proc_entry("sys", S_IFDIR, 0);
diff --git a/fs/proc/sysvipc.c b/fs/proc/sysvipc.c
deleted file mode 100644 (file)
index 7fff0ed..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  linux/fs/proc/sysvipc.c
- *
- *  Copyright (c) 1999 Dragos Acostachioaie
- *
- *  This code is derived from linux/fs/proc/generic.c,
- *  which is Copyright (C) 1991, 1992 Linus Torvalds.
- *
- *  /proc/sysvipc directory handling functions
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-/* 4K page size but our output routines use some slack for overruns */
-#define PROC_BLOCK_SIZE        (3*1024)
-
-static ssize_t
-proc_sysvipc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
-{
-       struct inode * inode = file->f_dentry->d_inode;
-       char    *page;
-       ssize_t retval=0;
-       int     eof=0;
-       ssize_t n, count;
-       char    *start;
-       struct proc_dir_entry * dp;
-
-       dp = (struct proc_dir_entry *) inode->u.generic_ip;
-       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-               return -ENOMEM;
-
-       while ((nbytes > 0) && !eof)
-       {
-               count = MIN(PROC_BLOCK_SIZE, nbytes);
-
-               start = NULL;
-               if (dp->get_info) {
-                       /*
-                        * Handle backwards compatibility with the old net
-                        * routines.
-                        * 
-                        * XXX What gives with the file->f_flags & O_ACCMODE
-                        * test?  Seems stupid to me....
-                        */
-                       n = dp->get_info(page, &start, *ppos, count,
-                                (file->f_flags & O_ACCMODE) == O_RDWR);
-                       if (n < count)
-                               eof = 1;
-               } else if (dp->read_proc) {
-                       n = dp->read_proc(page, &start, *ppos,
-                                         count, &eof, dp->data);
-               } else
-                       break;
-                       
-               if (!start) {
-                       /*
-                        * For proc files that are less than 4k
-                        */
-                       start = page + *ppos;
-                       n -= *ppos;
-                       if (n <= 0)
-                               break;
-                       if (n > count)
-                               n = count;
-               }
-               if (n == 0)
-                       break;  /* End of file */
-               if (n < 0) {
-                       if (retval == 0)
-                               retval = n;
-                       break;
-               }
-               
-               /* This is a hack to allow mangling of file pos independent
-                * of actual bytes read.  Simply place the data at page,
-                * return the bytes, and set `start' to the desired offset
-                * as an unsigned int. - Paul.Russell@rustcorp.com.au
-                */
-               n -= copy_to_user(buf, start < page ? page : start, n);
-               if (n == 0) {
-                       if (retval == 0)
-                               retval = -EFAULT;
-                       break;
-               }
-
-               *ppos += start < page ? (long)start : n; /* Move down the file */
-               nbytes -= n;
-               buf += n;
-               retval += n;
-       }
-       free_page((unsigned long) page);
-       return retval;
-}
-
-static struct file_operations proc_sysvipc_operations = {
-    NULL,              /* lseek   */
-    proc_sysvipc_read, /* read    */
-    NULL,              /* write   */
-    NULL,              /* readdir */
-    NULL,              /* poll    */
-    NULL,              /* ioctl   */
-    NULL,              /* mmap    */
-    NULL,              /* no special open code    */
-    NULL,              /* no special release code */
-    NULL               /* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_sysvipc_inode_operations = {
-       &proc_sysvipc_operations, /* default net file-ops */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
index 539b60da9003a9d435b865438235c2ba9cad85a5..7cb5617047341e5222d289ed191d40ffd7adabae 100644 (file)
  *                                       exposed a problem in readdir
  *                     2.1.107         code-freeze spellchecker run
  *     Aug 1998                        2.1.118+ VFS changes
+ *     Sep 1998        2.1.122         another VFS change (follow_link)
+ *     Apr 1999        2.2.7           no more EBADF checking in
+ *                                       lookup/readdir, use ERR_PTR
+ *     Jun 1999        2.3.6           d_alloc_root use changed
+ *                     2.3.9           clean up usage of ENOENT/negative
+ *                                       dentries in lookup
+ *                                     clean up page flags setting
+ *                                       (error, uptodate, locking) in
+ *                                       in readpage
+ *                                     use init_special_inode for
+ *                                       fifos/sockets (and streamline) in
+ *                                       read_inode, fix _ops table order
+ *     Aug 1999        2.3.16          __initfunc() => __init change
+ *     Oct 1999        2.3.24          page->owner hack obsoleted
+ *     Nov 1999        2.3.27          2.3.25+ page->offset => index change
  */
 
 /* todo:
@@ -404,7 +419,8 @@ romfs_readpage(struct file * file, struct page * page)
        get_page(page);
        buf = page_address(page);
 
-       offset = page->offset;
+       /* 32 bit warning -- but not for us :) */
+       offset = page->index << PAGE_CACHE_SHIFT;
        if (offset < inode->i_size) {
                avail = inode->i_size-offset;
                readlen = min(avail, PAGE_SIZE);
index 572ed026cc0eab71265db1ce84a83f43fcf8238e..56bcb9780cfece0d96f079a086cc116635d10661 100644 (file)
@@ -42,6 +42,8 @@ struct ipc_perm
 #define IPC_UNUSED     ((void *) -1)
 #define IPC_NOID       ((void *) -2)           /* being allocated/destroyed */
 
+#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_IPC_H */
index 2d42361b1b55e671f67a21841f0e090f80462a9e..b3284bfa1110c8632008d15308381516ed69e830 100644 (file)
@@ -45,9 +45,9 @@ struct msginfo {
        unsigned short  msgseg; 
 };
 
-#define MSGMNI   128   /* <= 32768 */     /* max # of msg queue identifiers */
-#define MSGMAX  4056   /* <= 4056 (?)*/   /* max size of message (bytes) */
-#define MSGMNB 16384   /* <= MAX_INT */   /* default max size of a message queue */
+#define MSGMNI   128   /* <= IPCMNI */     /* max # of msg queue identifiers */
+#define MSGMAX  8192   /* <= INT_MAX */   /* max size of message (bytes) */
+#define MSGMNB 16384   /* <= INT_MAX */   /* default max size of a message queue */
 
 /* unused */
 #define MSGPOOL (MSGMNI*MSGMNB/1024)  /* size in kilobytes of message pool */
index a172f41e7dbf195bf23ad11fe9a596434e96d075..2c6b3874426cbd99d5e2ee9364dd2591056b529c 100644 (file)
@@ -90,15 +90,6 @@ enum scsi_directory_inos {
        PROC_SCSI_LAST = (PROC_SCSI_FILE + 16) /* won't ever see more than */
 };                                             /* 16 HBAs in one machine   */
 
-enum mca_directory_inos {
-       PROC_MCA_MACHINE = (PROC_SCSI_LAST+1),
-       PROC_MCA_REGISTERS,
-       PROC_MCA_VIDEO,
-       PROC_MCA_SCSI,
-       PROC_MCA_SLOT,  /* the 8 adapter slots */
-       PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
-};
-
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
@@ -173,11 +164,8 @@ extern struct proc_dir_entry *proc_net;
 extern struct proc_dir_entry *proc_scsi;
 extern struct proc_dir_entry proc_sys;
 extern struct proc_dir_entry proc_openprom;
-extern struct proc_dir_entry proc_pid;
-extern struct proc_dir_entry proc_pid_fd;
 extern struct proc_dir_entry *proc_mca;
 extern struct proc_dir_entry *proc_bus;
-extern struct proc_dir_entry *proc_sysvipc;
 extern struct proc_dir_entry *proc_root_driver;
 extern struct proc_dir_entry proc_root_kcore;
 
@@ -272,8 +260,6 @@ extern inline int proc_driver_register(const char *module_name)
         return (p == NULL) ? -1 : 0;
 }
 
-
-
 extern struct super_block *proc_super_blocks;
 extern struct dentry_operations proc_dentry_operations;
 extern struct super_block *proc_read_super(struct super_block *,void *,int);
@@ -315,21 +301,16 @@ extern int proc_openprom_unregdev(struct openpromfs_dev *);
   
 extern struct inode_operations proc_dir_inode_operations;
 extern struct inode_operations proc_file_inode_operations;
-extern struct inode_operations proc_netdir_inode_operations;
 extern struct inode_operations proc_openprom_inode_operations;
-extern struct inode_operations proc_mem_inode_operations;
 extern struct inode_operations proc_sys_inode_operations;
 extern struct inode_operations proc_kcore_inode_operations;
 extern struct inode_operations proc_profile_inode_operations;
 extern struct inode_operations proc_kmsg_inode_operations;
-extern struct inode_operations proc_link_inode_operations;
-extern struct inode_operations proc_fd_inode_operations;
 #if CONFIG_AP1000
 extern struct inode_operations proc_ringbuf_inode_operations;
 #endif
 extern struct inode_operations proc_omirr_inode_operations;
 extern struct inode_operations proc_ppc_htab_inode_operations;
-extern struct inode_operations proc_sysvipc_inode_operations;
 
 /*
  * proc_tty.c
@@ -374,16 +355,6 @@ extern inline void proc_net_remove(const char *name)
        remove_proc_entry(name,proc_net);
 }
 
-extern inline int proc_net_register(struct proc_dir_entry * x)
-{
-       return proc_register(proc_net, x);
-}
-
-extern inline int proc_net_unregister(int x)
-{
-       return proc_unregister(proc_net, x);
-}
-
 #else
 
 extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; }
@@ -391,8 +362,6 @@ extern inline int proc_unregister(struct proc_dir_entry *a, int b) { return 0; }
 extern inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, 
        get_info_t *get_info) {return NULL;}
 extern inline void proc_net_remove(const char *name) {}
-extern inline int proc_net_register(struct proc_dir_entry * x) { return 0; }
-extern inline int proc_net_unregister(int x) { return 0; }
 extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; }
 extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; }
 
index 242ac70264c80eb066e3945e43f32c8204ee3026..234d4eebf98893d9b86b169749d38e8aca21195f 100644 (file)
@@ -60,10 +60,10 @@ struct  seminfo {
        int semaem;
 };
 
-#define SEMMNI  128             /* <= 32767  max # of semaphore identifiers */
-#define SEMMSL  250             /* <= 512 max num of semaphores per id */
-#define SEMMNS  (SEMMNI*SEMMSL) /* <= MAX_INT max # of semaphores in system */
-#define SEMOPM  32             /* <= 160 max num of ops per semop call */
+#define SEMMNI  128             /* <= IPCMNI  max # of semaphore identifiers */
+#define SEMMSL  250             /* <= 8 000 max num of semaphores per id */
+#define SEMMNS  (SEMMNI*SEMMSL) /* <= INT_MAX max # of semaphores in system */
+#define SEMOPM  32             /* <= 1 000 max num of ops per semop call */
 #define SEMVMX  32767           /* <= 32767 semaphore maximum value */
 
 /* unused */
index 0e1e65a70aedb4065e4c3ddadd93cd71866d7715..ce76c926d4b2a2879398c620106b98ec220d702d 100644 (file)
@@ -102,9 +102,11 @@ enum
        KERN_MSGMNB=36,         /* int: Maximum message queue size */
        KERN_MSGPOOL=37,        /* int: Maximum system message pool size */
        KERN_SYSRQ=38,          /* int: Sysreq enable */
-       KERN_MAX_THREADS=39,    /* int: Maximum nr of threads in the system */
+       KERN_MAX_THREADS=39,    /* int: Maximum nr of threads in the system */
        KERN_RANDOM=40,         /* Random driver */
-       KERN_SHMALL=41          /* int: Maximum size of shared memory */
+       KERN_SHMALL=41,         /* int: Maximum size of shared memory */
+       KERN_MSGMNI=42,         /* int: msg queue identifiers */
+       KERN_SEM=43             /* int: sysv semaphore limits */
 };
 
 
index 583bc837fba473c0ac6b0357e1b47d688a46325b..2cb9139252e998490a6eb9b4d8f9b25849079da1 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -11,6 +11,7 @@
  * /proc/sysvipc/msg support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
  *
  * mostly rewritten, threaded and wake-one semantics added
+ * MSGMAX limit removed, sysctl's added
  * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/list.h>
-
 #include <asm/uaccess.h>
+#include "util.h"
+
+/* sysctl: */
+int msg_ctlmax = MSGMAX;
+int msg_ctlmnb = MSGMNB;
+int msg_ctlmni = MSGMNI;
 
-#define USHRT_MAX      0xffff
-/* one ms_receiver structure for each sleeping receiver */
+/* one msg_receiver structure for each sleeping receiver */
 struct msg_receiver {
        struct list_head r_list;
        struct task_struct* r_tsk;
@@ -37,14 +42,27 @@ struct msg_receiver {
        struct msg_msg* volatile r_msg;
 };
 
+/* one msg_sender for each sleeping sender */
+struct msg_sender {
+       struct list_head list;
+       struct task_struct* tsk;
+};
+
+struct msg_msgseg {
+       struct msg_msgseg* next;
+       /* the next part of the message follows immediately */
+};
 /* one msg_msg structure for each message */
 struct msg_msg {
        struct list_head m_list; 
        long  m_type;          
        int m_ts;           /* message text size */
+       struct msg_msgseg* next;
        /* the actual message follows immediately */
 };
 
+#define DATALEN_MSG    (PAGE_SIZE-sizeof(struct msg_msg))
+#define DATALEN_SEG    (PAGE_SIZE-sizeof(struct msg_msgseg))
 
 /* one msq_queue structure for each present queue on the system */
 struct msg_queue {
@@ -60,13 +78,7 @@ struct msg_queue {
 
        struct list_head q_messages;
        struct list_head q_receivers;
-       wait_queue_head_t q_rwait;
-};
-
-/* one msq_array structure for each possible queue on the system */
-struct msg_array {
-       spinlock_t lock;
-       struct msg_queue* q;
+       struct list_head q_senders;
 };
 
 #define SEARCH_ANY             1
@@ -74,99 +86,181 @@ struct msg_array {
 #define SEARCH_NOTEQUAL                3
 #define SEARCH_LESSEQUAL       4
 
-static DECLARE_MUTEX(msg_lock);
-static struct msg_array msg_que[MSGMNI];
-
-static unsigned short msg_seq = 0;
-static int msg_used_queues = 0;
-static int msg_max_id = -1;
-
 static atomic_t msg_bytes = ATOMIC_INIT(0);
 static atomic_t msg_hdrs = ATOMIC_INIT(0);
 
+static struct ipc_ids msg_ids;
+
+#define msg_lock(id)   ((struct msg_queue*)ipc_lock(&msg_ids,id))
+#define msg_unlock(id) ipc_unlock(&msg_ids,id)
+#define msg_rmid(id)   ((struct msg_queue*)ipc_rmid(&msg_ids,id))
+#define msg_checkid(msq, msgid)        \
+       ipc_checkid(&msg_ids,&msq->q_perm,msgid)
+#define msg_buildid(id, seq) \
+       ipc_buildid(&msg_ids, id, seq)
+
 static void freeque (int id);
 static int newque (key_t key, int msgflg);
-static int findkey (key_t key);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-/* implemented in ipc/util.c, thread-safe */
-extern int ipcperms (struct ipc_perm *ipcp, short msgflg);
-
 void __init msg_init (void)
 {
-       int id;
+       ipc_init_ids(&msg_ids,msg_ctlmni);
 
-       for (id = 0; id < MSGMNI; id++) {
-               msg_que[id].lock = SPIN_LOCK_UNLOCKED;
-               msg_que[id].q = NULL;
-       }
 #ifdef CONFIG_PROC_FS
        create_proc_read_entry("sysvipc/msg", 0, 0, sysvipc_msg_read_proc, NULL);
 #endif
 }
 
-static int findkey (key_t key)
-{
-       int id;
-       struct msg_queue *msq;
-       
-       for (id = 0; id <= msg_max_id; id++) {
-               msq = msg_que[id].q;
-               if(msq == NULL)
-                       continue;
-               if (key == msq->q_perm.key)
-                       return id;
-       }
-       return -1;
-}
-
 static int newque (key_t key, int msgflg)
 {
        int id;
        struct msg_queue *msq;
-       struct ipc_perm *ipcp;
-
-       for (id = 0; id < MSGMNI; id++) {
-               if (msg_que[id].q == NULL)
-                       break;
-       }
-       if(id == MSGMNI)
-               return -ENOSPC;
 
        msq  = (struct msg_queue *) kmalloc (sizeof (*msq), GFP_KERNEL);
        if (!msq) 
                return -ENOMEM;
-
-       ipcp = &msq->q_perm;
-       ipcp->mode = (msgflg & S_IRWXUGO);
-       ipcp->key = key;
-       ipcp->cuid = ipcp->uid = current->euid;
-       ipcp->gid = ipcp->cgid = current->egid;
-
-       /* ipcp->seq*MSGMNI must be a positive integer.
-        * this limits MSGMNI to 32768
-        */
-       ipcp->seq = msg_seq++;
+       id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
+       if(id == -1) {
+               kfree(msq);
+               return -ENOSPC;
+       }
+       msq->q_perm.mode = (msgflg & S_IRWXUGO);
+       msq->q_perm.key = key;
 
        msq->q_stime = msq->q_rtime = 0;
        msq->q_ctime = CURRENT_TIME;
        msq->q_cbytes = msq->q_qnum = 0;
-       msq->q_qbytes = MSGMNB;
+       msq->q_qbytes = msg_ctlmnb;
        msq->q_lspid = msq->q_lrpid = 0;
        INIT_LIST_HEAD(&msq->q_messages);
        INIT_LIST_HEAD(&msq->q_receivers);
-       init_waitqueue_head(&msq->q_rwait);
+       INIT_LIST_HEAD(&msq->q_senders);
+       msg_unlock(id);
 
-       if (id > msg_max_id)
-               msg_max_id = id;
-       spin_lock(&msg_que[id].lock);
-       msg_que[id].q = msq;
-       spin_unlock(&msg_que[id].lock);
-       msg_used_queues++;
+       return msg_buildid(id,msq->q_perm.seq);
+}
 
-       return (int)msq->q_perm.seq * MSGMNI + id;
+static void free_msg(struct msg_msg* msg)
+{
+       struct msg_msgseg* seg;
+       seg = msg->next;
+       kfree(msg);
+       while(seg != NULL) {
+               struct msg_msgseg* tmp = seg->next;
+               kfree(seg);
+               seg = tmp;
+       }
+}
+
+static struct msg_msg* load_msg(void* src, int len)
+{
+       struct msg_msg* msg;
+       struct msg_msgseg** pseg;
+       int err;
+       int alen;
+
+       alen = len;
+       if(alen > DATALEN_MSG)
+               alen = DATALEN_MSG;
+
+       msg = (struct msg_msg *) kmalloc (sizeof(*msg) + alen, GFP_KERNEL);
+       if(msg==NULL)
+               return ERR_PTR(-ENOMEM);
+
+       msg->next = NULL;
+
+       if (copy_from_user(msg+1, src, alen)) {
+               err = -EFAULT;
+               goto out_err;
+       }
+
+       len -= alen;
+       src = ((char*)src)+alen;
+       pseg = &msg->next;
+       while(len > 0) {
+               struct msg_msgseg* seg;
+               alen = len;
+               if(alen > DATALEN_SEG)
+                       alen = DATALEN_SEG;
+               seg = (struct msg_msgseg *) kmalloc (sizeof(*seg) + alen, GFP_KERNEL);
+               if(seg==NULL) {
+                       err=-ENOMEM;
+                       goto out_err;
+               }
+               *pseg = seg;
+               seg->next = NULL;
+               if(copy_from_user (seg+1, src, alen)) {
+                       err = -EFAULT;
+                       goto out_err;
+               }
+               pseg = &seg->next;
+               len -= alen;
+               src = ((char*)src)+alen;
+       }
+       return msg;
+
+out_err:
+       free_msg(msg);
+       return ERR_PTR(err);
+}
+
+static int store_msg(void* dest, struct msg_msg* msg, int len)
+{
+       int alen;
+       struct msg_msgseg *seg;
+
+       alen = len;
+       if(alen > DATALEN_MSG)
+               alen = DATALEN_MSG;
+       if(copy_to_user (dest, msg+1, alen))
+               return -1;
+
+       len -= alen;
+       dest = ((char*)dest)+alen;
+       seg = msg->next;
+       while(len > 0) {
+               alen = len;
+               if(alen > DATALEN_SEG)
+                       alen = DATALEN_SEG;
+               if(copy_to_user (dest, seg+1, alen))
+                       return -1;
+               len -= alen;
+               dest = ((char*)dest)+alen;
+               seg=seg->next;
+       }
+       return 0;
+}
+
+static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss)
+{
+       mss->tsk=current;
+       current->state=TASK_INTERRUPTIBLE;
+       list_add_tail(&mss->list,&msq->q_senders);
+}
+
+static inline void ss_del(struct msg_sender* mss)
+{
+       if(mss->list.next != NULL)
+               list_del(&mss->list);
+}
+
+static void ss_wakeup(struct list_head* h, int kill)
+{
+       struct list_head *tmp;
+
+       tmp = h->next;
+       while (tmp != h) {
+               struct msg_sender* mss;
+               
+               mss = list_entry(tmp,struct msg_sender,list);
+               tmp = tmp->next;
+               if(kill)
+                       mss->list.next=NULL;
+               wake_up_process(mss->tsk);
+       }
 }
 
 static void expunge_all(struct msg_queue* msq, int res)
@@ -189,48 +283,32 @@ static void freeque (int id)
        struct msg_queue *msq;
        struct list_head *tmp;
 
-       msq=msg_que[id].q;
-       msg_que[id].q = NULL;
-       if (id == msg_max_id) {
-               while ((msg_que[msg_max_id].q == NULL)) {
-                       if(msg_max_id--== 0)
-                               break;
-               }
-       }
-       msg_used_queues--;
+       msq = msg_rmid(id);
 
        expunge_all(msq,-EIDRM);
-
-       while(waitqueue_active(&msq->q_rwait)) {
-               wake_up(&msq->q_rwait);
-               spin_unlock(&msg_que[id].lock);
-               current->policy |= SCHED_YIELD;
-               schedule();
-               spin_lock(&msg_que[id].lock);
-       }
-       spin_unlock(&msg_que[id].lock);
+       ss_wakeup(&msq->q_senders,1);
+       msg_unlock(id);
                
        tmp = msq->q_messages.next;
        while(tmp != &msq->q_messages) {
                struct msg_msg* msg = list_entry(tmp,struct msg_msg,m_list);
                tmp = tmp->next;
                atomic_dec(&msg_hdrs);
-               kfree(msg);
+               free_msg(msg);
        }
        atomic_sub(msq->q_cbytes, &msg_bytes);
        kfree(msq);
 }
 
-
 asmlinkage long sys_msgget (key_t key, int msgflg)
 {
        int id, ret = -EPERM;
        struct msg_queue *msq;
        
-       down(&msg_lock);
+       down(&msg_ids.sem);
        if (key == IPC_PRIVATE) 
                ret = newque(key, msgflg);
-       else if ((id = findkey (key)) == -1) { /* key not used */
+       else if ((id = ipc_findkey(&msg_ids, key)) == -1) { /* key not used */
                if (!(msgflg & IPC_CREAT))
                        ret = -ENOENT;
                else
@@ -238,55 +316,62 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
        } else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) {
                ret = -EEXIST;
        } else {
-               msq = msg_que[id].q;
+               msq = msg_lock(id);
+               if(msq==NULL)
+                       BUG();
                if (ipcperms(&msq->q_perm, msgflg))
                        ret = -EACCES;
                else
-                       ret = (unsigned int) msq->q_perm.seq * MSGMNI + id;
+                       ret = msg_buildid(id, msq->q_perm.seq);
+               msg_unlock(id);
        }
-       up(&msg_lock);
+       up(&msg_ids.sem);
        return ret;
 }
 
 asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 {
-       int id, err;
+       int err;
        struct msg_queue *msq;
        struct msqid_ds tbuf;
        struct ipc_perm *ipcp;
        
        if (msqid < 0 || cmd < 0)
                return -EINVAL;
-       id = msqid % MSGMNI;
+
        switch (cmd) {
        case IPC_INFO: 
        case MSG_INFO: 
        { 
                struct msginfo msginfo;
+               int max_id;
                if (!buf)
                        return -EFAULT;
                /* We must not return kernel stack data.
-                * due to variable alignment, it's not enough
+                * due to padding, it's not enough
                 * to set all member fields.
                 */
                memset(&msginfo,0,sizeof(msginfo));     
-               msginfo.msgmni = MSGMNI;
-               msginfo.msgmax = MSGMAX;
-               msginfo.msgmnb = MSGMNB;
-               msginfo.msgmap = MSGMAP;
-               msginfo.msgpool = MSGPOOL;
-               msginfo.msgtql = MSGTQL;
+               msginfo.msgmni = msg_ctlmni;
+               msginfo.msgmax = msg_ctlmax;
+               msginfo.msgmnb = msg_ctlmnb;
                msginfo.msgssz = MSGSSZ;
                msginfo.msgseg = MSGSEG;
+               down(&msg_ids.sem);
                if (cmd == MSG_INFO) {
-                       msginfo.msgpool = msg_used_queues;
+                       msginfo.msgpool = msg_ids.in_use;
                        msginfo.msgmap = atomic_read(&msg_hdrs);
                        msginfo.msgtql = atomic_read(&msg_bytes);
+               } else {
+                       msginfo.msgmap = MSGMAP;
+                       msginfo.msgpool = MSGPOOL;
+                       msginfo.msgtql = MSGTQL;
                }
-
+               max_id = msg_ids.max_id;
+               up(&msg_ids.sem);
                if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
                        return -EFAULT;
-               return (msg_max_id < 0) ? 0: msg_max_id;
+               return (max_id < 0) ? 0: max_id;
        }
        case MSG_STAT:
        case IPC_STAT:
@@ -294,19 +379,18 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                int success_return;
                if (!buf)
                        return -EFAULT;
-               if(cmd == MSG_STAT && msqid > MSGMNI)
+               if(cmd == MSG_STAT && msqid > msg_ids.size)
                        return -EINVAL;
 
-               spin_lock(&msg_que[id].lock);
-               msq = msg_que[id].q;
-               err = -EINVAL;
+               msq = msg_lock(msqid);
                if (msq == NULL)
-                       goto out_unlock;
+                       return -EINVAL;
+
                if(cmd == MSG_STAT) {
-                       success_return = (unsigned int) msq->q_perm.seq * MSGMNI + msqid;
+                       success_return = msg_buildid(msqid, msq->q_perm.seq);
                } else {
                        err = -EIDRM;
-                       if (msq->q_perm.seq != (unsigned int) msqid / MSGMNI)
+                       if (msg_checkid(msq,msqid))
                                goto out_unlock;
                        success_return = 0;
                }
@@ -339,7 +423,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 
                tbuf.msg_lspid  = msq->q_lspid;
                tbuf.msg_lrpid  = msq->q_lrpid;
-               spin_unlock(&msg_que[id].lock);
+               msg_unlock(msqid);
                if (copy_to_user (buf, &tbuf, sizeof(*buf)))
                        return -EFAULT;
                return success_return;
@@ -356,32 +440,31 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                return  -EINVAL;
        }
 
-       down(&msg_lock);
-       spin_lock(&msg_que[id].lock);
-       msq = msg_que[id].q;
-       err = -EINVAL;
+       down(&msg_ids.sem);
+       msq = msg_lock(msqid);
+       err=-EINVAL;
        if (msq == NULL)
-               goto out_unlock_up;
+               goto out_up;
+
        err = -EIDRM;
-       if (msq->q_perm.seq != (unsigned int) msqid / MSGMNI)
+       if (msg_checkid(msq,msqid))
                goto out_unlock_up;
        ipcp = &msq->q_perm;
+       err = -EPERM;
+       if (current->euid != ipcp->cuid && 
+           current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
+           /* We _could_ check for CAP_CHOWN above, but we don't */
+               goto out_unlock_up;
 
        switch (cmd) {
        case IPC_SET:
        {
                int newqbytes;
-               err = -EPERM;
-               if (current->euid != ipcp->cuid && 
-                   current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
-                   /* We _could_ check for CAP_CHOWN above, but we don't */
-                       goto out_unlock_up;
-
                if(tbuf.msg_qbytes == 0)
                        newqbytes = tbuf.msg_lqbytes;
                 else
                        newqbytes = tbuf.msg_qbytes;
-               if (newqbytes > MSGMNB && !capable(CAP_SYS_RESOURCE))
+               if (newqbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
                        goto out_unlock_up;
                msq->q_qbytes = newqbytes;
 
@@ -397,27 +480,23 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                /* sleeping senders might be able to send
                 * due to a larger queue size.
                 */
-               wake_up(&msq->q_rwait);
-               spin_unlock(&msg_que[id].lock);
+               ss_wakeup(&msq->q_senders,0);
+               msg_unlock(msqid);
                break;
        }
        case IPC_RMID:
-               err = -EPERM;
-               if (current->euid != ipcp->cuid && 
-                   current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
-                       goto out_unlock;
-               freeque (id); 
+               freeque (msqid); 
                break;
        }
        err = 0;
 out_up:
-       up(&msg_lock);
+       up(&msg_ids.sem);
        return err;
 out_unlock_up:
-       spin_unlock(&msg_que[id].lock);
+       msg_unlock(msqid);
        goto out_up;
 out_unlock:
-       spin_unlock(&msg_que[id].lock);
+       msg_unlock(msqid);
        return err;
 }
 
@@ -471,67 +550,61 @@ int inline pipelined_send(struct msg_queue* msq, struct msg_msg* msg)
 
 asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
 {
-       int id;
        struct msg_queue *msq;
        struct msg_msg *msg;
        long mtype;
        int err;
        
-       if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
+       if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0)
                return -EINVAL;
        if (get_user(mtype, &msgp->mtype))
                return -EFAULT; 
        if (mtype < 1)
                return -EINVAL;
 
-       msg = (struct msg_msg *) kmalloc (sizeof(*msg) + msgsz, GFP_KERNEL);
-       if(msg==NULL)
-               return -ENOMEM;
+       msg = load_msg(msgp->mtext, msgsz);
+       if(IS_ERR(msg))
+               return PTR_ERR(msg);
 
-       if (copy_from_user(msg+1, msgp->mtext, msgsz)) {
-               kfree(msg);
-               return -EFAULT;
-       }       
        msg->m_type = mtype;
        msg->m_ts = msgsz;
 
-       id = (unsigned int) msqid % MSGMNI;
-       spin_lock(&msg_que[id].lock);
-       err= -EINVAL;
-retry:
-       msq = msg_que[id].q;
-       if (msq == NULL)
+       msq = msg_lock(msqid);
+       err=-EINVAL;
+       if(msq==NULL)
                goto out_free;
-
+retry:
        err= -EIDRM;
-       if (msq->q_perm.seq != (unsigned int) msqid / MSGMNI) 
-               goto out_free;
+       if (msg_checkid(msq,msqid))
+               goto out_unlock_free;
 
        err=-EACCES;
        if (ipcperms(&msq->q_perm, S_IWUGO)) 
-               goto out_free;
+               goto out_unlock_free;
 
-       if(msgsz + msq->q_cbytes > msq->q_qbytes) {
-               DECLARE_WAITQUEUE(wait,current);
+       if(msgsz + msq->q_cbytes > msq->q_qbytes ||
+               1 + msq->q_qnum > msq->q_qbytes) {
+               struct msg_sender s;
 
                if(msgflg&IPC_NOWAIT) {
                        err=-EAGAIN;
-                       goto out_free;
+                       goto out_unlock_free;
                }
-               current->state = TASK_INTERRUPTIBLE;
-               add_wait_queue(&msq->q_rwait,&wait);
-               spin_unlock(&msg_que[id].lock);
+               ss_add(msq, &s);
+               msg_unlock(msqid);
                schedule();
                current->state= TASK_RUNNING;
+
+               msq = msg_lock(msqid);
+               err = -EIDRM;
+               if(msq==NULL)
+                       goto out_free;
+               ss_del(&s);
                
-               remove_wait_queue(&msq->q_rwait,&wait);
                if (signal_pending(current)) {
-                       kfree(msg);
-                       return -EINTR;
+                       err=-EINTR;
+                       goto out_unlock_free;
                }
-
-               spin_lock(&msg_que[id].lock);
-               err = -EIDRM;
                goto retry;
        }
 
@@ -549,10 +622,11 @@ retry:
        msq->q_lspid = current->pid;
        msq->q_stime = CURRENT_TIME;
 
+out_unlock_free:
+       msg_unlock(msqid);
 out_free:
        if(msg!=NULL)
-               kfree(msg);
-       spin_unlock(&msg_que[id].lock);
+               free_msg(msg);
        return err;
 }
 
@@ -582,7 +656,6 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,
        struct msg_receiver msr_d;
        struct list_head* tmp;
        struct msg_msg* msg, *found_msg;
-       int id;
        int err;
        int mode;
 
@@ -590,13 +663,10 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,
                return -EINVAL;
        mode = convert_mode(&msgtyp,msgflg);
 
-       id = (unsigned int) msqid % MSGMNI;
-       spin_lock(&msg_que[id].lock);
+       msq = msg_lock(msqid);
+       if(msq==NULL)
+               return -EINVAL;
 retry:
-       msq = msg_que[id].q;
-       err=-EINVAL;
-       if (msq == NULL)
-               goto out_unlock;
        err=-EACCES;
        if (ipcperms (&msq->q_perm, S_IRUGO))
                goto out_unlock;
@@ -630,21 +700,19 @@ retry:
                msq->q_cbytes -= msg->m_ts;
                atomic_sub(msg->m_ts,&msg_bytes);
                atomic_dec(&msg_hdrs);
-               if(waitqueue_active(&msq->q_rwait))
-                       wake_up(&msq->q_rwait);
-out_success_unlock:
-               spin_unlock(&msg_que[id].lock);
+               ss_wakeup(&msq->q_senders,0);
+               msg_unlock(msqid);
 out_success:
                msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
                if (put_user (msg->m_type, &msgp->mtype) ||
-                           copy_to_user (msgp->mtext, msg+1, msgsz))
-               {
+                   store_msg(msgp->mtext, msg, msgsz)) {
                            msgsz = -EFAULT;
                }
-               kfree(msg);
+               free_msg(msg);
                return msgsz;
        } else
        {
+               struct msg_queue *t;
                /* no message waiting. Prepare for pipelined
                 * receive.
                 */
@@ -657,12 +725,13 @@ out_success:
                msr_d.r_msgtype = msgtyp;
                msr_d.r_mode = mode;
                if(msgflg & MSG_NOERROR)
-                       msr_d.r_maxsize = MSGMAX;
+                       msr_d.r_maxsize = INT_MAX;
                 else
                        msr_d.r_maxsize = msgsz;
                msr_d.r_msg = ERR_PTR(-EAGAIN);
                current->state = TASK_INTERRUPTIBLE;
-               spin_unlock(&msg_que[id].lock);
+               msg_unlock(msqid);
+
                schedule();
                current->state = TASK_RUNNING;
 
@@ -670,16 +739,22 @@ out_success:
                if(!IS_ERR(msg)) 
                        goto out_success;
 
-               spin_lock(&msg_que[id].lock);
+               t = msg_lock(msqid);
+               if(t==NULL)
+                       msqid=-1;
                msg = (struct msg_msg*)msr_d.r_msg;
                if(!IS_ERR(msg)) {
                        /* our message arived while we waited for
                         * the spinlock. Process it.
                         */
-                       goto out_success_unlock;
+                       if(msqid!=-1)
+                               msg_unlock(msqid);
+                       goto out_success;
                }
                err = PTR_ERR(msg);
                if(err == -EAGAIN) {
+                       if(msqid==-1)
+                               BUG();
                        list_del(&msr_d.r_list);
                        if (signal_pending(current))
                                err=-EINTR;
@@ -688,7 +763,8 @@ out_success:
                }
        }
 out_unlock:
-       spin_unlock(&msg_que[id].lock);
+       if(msqid!=-1)
+               msg_unlock(msqid);
        return err;
 }
 
@@ -699,28 +775,29 @@ static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int l
        off_t begin = 0;
        int i, len = 0;
 
-       down(&msg_lock);
+       down(&msg_ids.sem);
        len += sprintf(buffer, "       key      msqid perms cbytes  qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n");
 
-       for(i = 0; i <= msg_max_id; i++) {
-               spin_lock(&msg_que[i].lock);
-               if(msg_que[i].q != NULL) {
+       for(i = 0; i <= msg_ids.max_id; i++) {
+               struct msg_queue * msq;
+               msq = msg_lock(i);
+               if(msq != NULL) {
                        len += sprintf(buffer + len, "%10d %10d  %4o  %5u %5u %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
-                               msg_que[i].q->q_perm.key,
-                               msg_que[i].q->q_perm.seq * MSGMNI + i,
-                               msg_que[i].q->q_perm.mode,
-                               msg_que[i].q->q_cbytes,
-                               msg_que[i].q->q_qnum,
-                               msg_que[i].q->q_lspid,
-                               msg_que[i].q->q_lrpid,
-                               msg_que[i].q->q_perm.uid,
-                               msg_que[i].q->q_perm.gid,
-                               msg_que[i].q->q_perm.cuid,
-                               msg_que[i].q->q_perm.cgid,
-                               msg_que[i].q->q_stime,
-                               msg_que[i].q->q_rtime,
-                               msg_que[i].q->q_ctime);
-                       spin_unlock(&msg_que[i].lock);
+                               msq->q_perm.key,
+                               msg_buildid(i,msq->q_perm.seq),
+                               msq->q_perm.mode,
+                               msq->q_cbytes,
+                               msq->q_qnum,
+                               msq->q_lspid,
+                               msq->q_lrpid,
+                               msq->q_perm.uid,
+                               msq->q_perm.gid,
+                               msq->q_perm.cuid,
+                               msq->q_perm.cgid,
+                               msq->q_stime,
+                               msq->q_rtime,
+                               msq->q_ctime);
+                       msg_unlock(i);
 
                        pos += len;
                        if(pos < offset) {
@@ -729,13 +806,12 @@ static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int l
                        }
                        if(pos > offset + length)
                                goto done;
-               } else {
-                       spin_unlock(&msg_que[i].lock);
                }
+
        }
        *eof = 1;
 done:
-       up(&msg_lock);
+       up(&msg_ids.sem);
        *start = buffer + (offset - begin);
        len -= (offset - begin);
        if(len > length)
@@ -745,4 +821,3 @@ done:
        return len;
 }
 #endif
-
index f91b11c36e69148525702deba4c2769a296e059e..a5f2310b30d603580b3d6ea0125523c4058effaa 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -51,7 +51,8 @@
  *
  * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
  *
- * SMP-threaded (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * SMP-threaded, sysctl's added
+ * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
-
 #include <asm/uaccess.h>
+#include "util.h"
+
+
+#define sem_lock(id)   ((struct semid_ds*)ipc_lock(&sem_ids,id))
+#define sem_unlock(id) ipc_unlock(&sem_ids,id)
+#define sem_rmid(id)   ((struct semid_ds*)ipc_rmid(&sem_ids,id))
+#define sem_checkid(sma, semid)        \
+       ipc_checkid(&sem_ids,&sma->sem_perm,semid)
+#define sem_buildid(id, seq) \
+       ipc_buildid(&sem_ids, id, seq)
+static struct ipc_ids sem_ids;
 
-extern int ipcperms (struct ipc_perm *ipcp, short semflg);
 static int newary (key_t, int, int);
-static int findkey (key_t key);
 static void freeary (int id);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-struct semid_ary
-{
-       spinlock_t lock;
-       struct semid_ds* s;
-};
-
-static struct semid_ary semary[SEMMNI];
-
-static DECLARE_MUTEX(sem_lock);
-static int max_semid = 0;
-static int used_sems = 0;
-static int used_semids = 0;
+#define SEMMSL_FAST    256 /* 512 bytes on stack */
+#define SEMOPM_FAST    64  /* ~ 372 bytes on stack */
 
-static unsigned short sem_seq = 0;
-
-/* anti-deadlock ordering:
- *     sem_lock < semary[].lock
+/*
  * linked list protection:
  *     sem_undo.id_next,
  *     semid_ds.sem_pending{,last},
- *     semid_ds.sem_undo: semary[].lock for read/write
+ *     semid_ds.sem_undo: sem_lock() for read/write
  *     sem_undo.proc_next: only "current" is allowed to read/write that field.
  *     
  */
 
+int sem_ctls[4] = {SEMMSL, SEMMNS, SEMOPM, SEMMNI};
+#define sc_semmsl      (sem_ctls[0])
+#define sc_semmns      (sem_ctls[1])
+#define sc_semopm      (sem_ctls[2])
+#define sc_semmni      (sem_ctls[3])
+
+static int used_sems = 0;
+
 void __init sem_init (void)
 {
-       int i;
+       used_sems = 0;
+       ipc_init_ids(&sem_ids,sc_semmni);
 
-       used_sems = used_semids = max_semid = sem_seq = 0;
-       for (i = 0; i < SEMMNI; i++) {
-               semary[i].lock = SPIN_LOCK_UNLOCKED;
-               semary[i].s = NULL;
-       }
 #ifdef CONFIG_PROC_FS
        create_proc_read_entry("sysvipc/sem", 0, 0, sysvipc_sem_read_proc, NULL);
 #endif
-       return;
-}
-
-static int findkey (key_t key)
-{
-       int id;
-       struct semid_ds *sma;
-
-       for (id = 0; id <= max_semid; id++) {
-               sma = semary[id].s;
-               if(sma==NULL)
-                       continue;
-
-               if (key == sma->sem_perm.key)
-                       return id;
-       }
-       return -1;
 }
 
 static int newary (key_t key, int nsems, int semflg)
 {
        int id;
        struct semid_ds *sma;
-       struct ipc_perm *ipcp;
        int size;
 
        if (!nsems)
                return -EINVAL;
-       if (used_sems + nsems > SEMMNS)
+       if (used_sems + nsems > sc_semmns)
                return -ENOSPC;
-       for (id = 0; id < SEMMNI; id++) {
-               if(semary[id].s == NULL)
-                       goto found;
-       }
-       return -ENOSPC;
-found:
+
        size = sizeof (*sma) + nsems * sizeof (struct sem);
-       used_sems += nsems;
-       sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);
+       sma = (struct semid_ds *) ipc_alloc(size);
        if (!sma) {
-               used_sems -= nsems;
                return -ENOMEM;
        }
        memset (sma, 0, size);
+       id = ipc_addid(&sem_ids, &sma->sem_perm, sc_semmni);
+       if(id == -1) {
+               ipc_free(sma, size);
+               return -ENOSPC;
+       }
+       used_sems += nsems;
+
+       sma->sem_perm.mode = (semflg & S_IRWXUGO);
+       sma->sem_perm.key = key;
+
        sma->sem_base = (struct sem *) &sma[1];
-       ipcp = &sma->sem_perm;
-       ipcp->mode = (semflg & S_IRWXUGO);
-       ipcp->key = key;
-       ipcp->cuid = ipcp->uid = current->euid;
-       ipcp->gid = ipcp->cgid = current->egid;
-       /* sma->sem_perm.seq*MSGMNI must be a positive integer.
-        * this limits MSGMNI to 32768
-        */
-       sma->sem_perm.seq = sem_seq++;
        /* sma->sem_pending = NULL; */
        sma->sem_pending_last = &sma->sem_pending;
        /* sma->undo = NULL; */
        sma->sem_nsems = nsems;
        sma->sem_ctime = CURRENT_TIME;
-       if (id > max_semid)
-               max_semid = id;
-       used_semids++;
-       spin_lock(&semary[id].lock);
-       semary[id].s = sma;
-       spin_unlock(&semary[id].lock);
-       return (unsigned int) sma->sem_perm.seq * SEMMNI + id;
+       sem_unlock(id);
+
+       return sem_buildid(id, sma->sem_perm.seq);
 }
 
 asmlinkage long sys_semget (key_t key, int nsems, int semflg)
@@ -180,13 +152,13 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
        int id, err = -EINVAL;
        struct semid_ds *sma;
 
-       if (nsems < 0 || nsems > SEMMSL)
+       if (nsems < 0 || nsems > sc_semmsl)
                return -EINVAL;
-       down(&sem_lock);
+       down(&sem_ids.sem);
        
        if (key == IPC_PRIVATE) {
                err = newary(key, nsems, semflg);
-       } else if ((id = findkey (key)) == -1) {  /* key not used */
+       } else if ((id = ipc_findkey(&sem_ids, key)) == -1) {  /* key not used */
                if (!(semflg & IPC_CREAT))
                        err = -ENOENT;
                else
@@ -194,19 +166,46 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
        } else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {
                err = -EEXIST;
        } else {
-               sma = semary[id].s;
+               sma = sem_lock(id);
+               if(sma==NULL)
+                       BUG();
                if (nsems > sma->sem_nsems)
                        err = -EINVAL;
                else if (ipcperms(&sma->sem_perm, semflg))
                        err = -EACCES;
                else
-                       err = (int) sma->sem_perm.seq * SEMMNI + id;
+                       err = sem_buildid(id, sma->sem_perm.seq);
+               sem_unlock(id);
        }
 
-       up(&sem_lock);
+       up(&sem_ids.sem);
        return err;
 }
 
+/* doesn't acquire the sem_lock on error! */
+static int sem_revalidate(int semid, struct semid_ds* sma, int nsems, short flg)
+{
+       struct semid_ds* smanew;
+
+       smanew = sem_lock(semid);
+       if(smanew==NULL)
+               return -EIDRM;
+       if(smanew != sma)
+               goto out_EIDRM;
+       if(sem_checkid(sma,semid))
+               goto out_EIDRM;
+       if(sma->sem_nsems != nsems) {
+out_EIDRM:
+               sem_unlock(semid);
+               return -EIDRM;
+       }
+
+       if (ipcperms(&sma->sem_perm, flg)) {
+               sem_unlock(semid);
+               return -EACCES;
+       }
+       return 0;
+}
 /* Manage the doubly linked list sma->sem_pending as a FIFO:
  * insert new queue elements at the tail sma->sem_pending_last.
  */
@@ -387,15 +386,9 @@ static void freeary (int id)
        struct semid_ds *sma;
        struct sem_undo *un;
        struct sem_queue *q;
+       int size;
 
-       /* we own both locks, noone can get in */
-       sma = semary[id].s;
-       semary[id].s = NULL;
-
-       used_sems -= sma->sem_nsems;
-       if (id == max_semid)
-               while (max_semid && (semary[--max_semid].s == NULL));
-       used_semids--;
+       sma = sem_rmid(id);
 
        /* Invalidate the existing undo structures for this semaphore set.
         * (They will be freed without any further action in sem_exit()
@@ -410,40 +403,46 @@ static void freeary (int id)
                q->prev = NULL;
                wake_up_process(q->sleeper); /* doesn't sleep */
        }
+       sem_unlock(id);
 
-       kfree(sma);
+       used_sems -= sma->sem_nsems;
+       size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
+       ipc_free(sma, size);
 }
 
 int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
 {
        int err = -EINVAL;
-       int lid = semid % SEMMNI;
 
        switch(cmd) {
        case IPC_INFO:
        case SEM_INFO:
        {
                struct seminfo seminfo;
+               int max_id;
 
-               seminfo.semmni = SEMMNI;
-               seminfo.semmns = SEMMNS;
-               seminfo.semmsl = SEMMSL;
-               seminfo.semopm = SEMOPM;
+               memset(&seminfo,0,sizeof(seminfo));
+               seminfo.semmni = sc_semmni;
+               seminfo.semmns = sc_semmns;
+               seminfo.semmsl = sc_semmsl;
+               seminfo.semopm = sc_semopm;
                seminfo.semvmx = SEMVMX;
                seminfo.semmnu = SEMMNU;
                seminfo.semmap = SEMMAP;
                seminfo.semume = SEMUME;
-               seminfo.semusz = SEMUSZ;
-               seminfo.semaem = SEMAEM;
+               down(&sem_ids.sem);
                if (cmd == SEM_INFO) {
-                       down(&sem_lock);
-                       seminfo.semusz = used_semids;
+                       seminfo.semusz = sem_ids.in_use;
                        seminfo.semaem = used_sems;
-                       up(&sem_lock);
+               } else {
+                       seminfo.semusz = SEMUSZ;
+                       seminfo.semaem = SEMAEM;
                }
+               max_id = sem_ids.max_id;
+               up(&sem_ids.sem);
                if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 
                        return -EFAULT;
-               return max_semid;
+               return (max_id < 0) ? 0: max_id;
        }
        case SEM_STAT:
        {
@@ -451,24 +450,24 @@ int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
                struct semid_ds tbuf;
                int id;
 
-               if (semid > max_semid)
+               if(semid > sem_ids.size)
+                       return -EINVAL;
+
+               sma = sem_lock(semid);
+               if(sma == NULL)
                        return -EINVAL;
 
-               spin_lock(&semary[lid].lock);
-               err = -EINVAL;
-               sma = semary[semid].s;
-               if (sma ==  NULL)
-                       goto out_unlock;
                err = -EACCES;
                if (ipcperms (&sma->sem_perm, S_IRUGO))
                        goto out_unlock;
-               id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;
+               id = sem_buildid(semid, sma->sem_perm.seq);
+
                memset(&tbuf,0,sizeof(tbuf));
                tbuf.sem_perm   = sma->sem_perm;
                tbuf.sem_otime  = sma->sem_otime;
                tbuf.sem_ctime  = sma->sem_ctime;
                tbuf.sem_nsems  = sma->sem_nsems;
-               spin_unlock(&semary[lid].lock);
+               sem_unlock(semid);
                if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
                        return -EFAULT;
                return id;
@@ -478,99 +477,136 @@ int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
        }
        return err;
 out_unlock:
-       spin_unlock(&semary[lid].lock);
+       sem_unlock(semid);
        return err;
 }
 
-int semctl_locked_unlock(int semid, int semnum, int cmd, union semun arg)
+int semctl_main(int semid, int semnum, int cmd, union semun arg)
 {
        struct semid_ds *sma;
-       struct semid_ds tbuf;
+       struct sem* curr;
        int err;
-       int lid = semid % SEMMNI;
+       ushort fast_sem_io[SEMMSL_FAST];
+       ushort* sem_io = fast_sem_io;
+       int nsems;
+
+       sma = sem_lock(semid);
+       if(sma==NULL)
+               return -EINVAL;
 
-       sma = semary[lid].s;
-       err=-EINVAL;
-       if (sma == NULL)
-               goto out_unlock;
        err=-EIDRM;
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+       if (sem_checkid(sma,semid))
                goto out_unlock;
 
        err = -EACCES;
-       if (ipcperms(&sma->sem_perm, S_IRUGO))
-                       goto out_unlock;        
-       
+       if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
+               goto out_unlock;
+
+       nsems = sma->sem_nsems;
        switch (cmd) {
        case GETALL:
        {
                ushort *array = arg.array;
-               ushort sem_io[SEMMSL];
                int i;
-               int nsems = sma->sem_nsems;
+
+               if(nsems > SEMMSL_FAST) {
+                       sem_unlock(semid);                      
+                       sem_io = ipc_alloc(sizeof(ushort)*nsems);
+                       if(sem_io == NULL)
+                               return -ENOMEM;
+                       err = sem_revalidate(semid, sma, nsems, S_IRUGO);
+                       if(err)
+                               goto out_free;
+               }
 
                for (i = 0; i < sma->sem_nsems; i++)
                        sem_io[i] = sma->sem_base[i].semval;
-               spin_unlock(&semary[lid].lock);
-               if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
-                       return -EFAULT;
-               return 0;
+               sem_unlock(semid);
+               err = 0;
+               if(copy_to_user(array, sem_io, nsems*sizeof(ushort)))
+                       err = -EFAULT;
+               goto out_free;
+       }
+       case SETALL:
+       {
+               int i;
+               struct sem_undo *un;
+
+               sem_unlock(semid);
+
+               if(nsems > SEMMSL_FAST) {
+                       sem_io = ipc_alloc(sizeof(ushort)*nsems);
+                       if(sem_io == NULL)
+                               return -ENOMEM;
+               }
+
+               if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
+                       err = -EFAULT;
+                       goto out_free;
+               }
+
+               for (i = 0; i < nsems; i++) {
+                       if (sem_io[i] > SEMVMX) {
+                               err = -ERANGE;
+                               goto out_free;
+                       }
+               }
+               err = sem_revalidate(semid, sma, nsems, S_IWUGO);
+               if(err)
+                       goto out_free;
+
+               for (i = 0; i < nsems; i++)
+                       sma->sem_base[i].semval = sem_io[i];
+               for (un = sma->undo; un; un = un->id_next)
+                       for (i = 0; i < nsems; i++)
+                               un->semadj[i] = 0;
+               sma->sem_ctime = CURRENT_TIME;
+               /* maybe some queued-up processes were waiting for this */
+               update_queue(sma);
+               err = 0;
+               goto out_unlock;
        }
        case IPC_STAT:
+       {
+               struct semid_ds tbuf;
                memset(&tbuf,0,sizeof(tbuf));
                tbuf.sem_perm   = sma->sem_perm;
                tbuf.sem_otime  = sma->sem_otime;
                tbuf.sem_ctime  = sma->sem_ctime;
                tbuf.sem_nsems  = sma->sem_nsems;
-               spin_unlock(&semary[lid].lock);
+               sem_unlock(semid);
                if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
                        return -EFAULT;
                return 0;
-default:
-               err = -EINVAL;
        }
-out_unlock:
-       spin_unlock(&semary[lid].lock);
-       return err;
-
-}
-
-int semctl_locked(int semid, int semnum, int cmd, union semun arg)
-{
-       struct semid_ds *sma;
-       int lid = semid % SEMMNI;
-       struct sem *curr;
-
-       sma = semary[lid].s;
-       if (sma == NULL)
-               return -EINVAL;
-
-       if (ipcperms (&sma->sem_perm, (cmd==SETVAL)?S_IWUGO:S_IRUGO))
-               return -EACCES;
-
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-               return -EIDRM;
-
-       if (semnum >= sma->sem_nsems)
-               return -EINVAL;
+       /* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */
+       }
+       err = -EINVAL;
+       if(semnum < 0 || semnum >= nsems)
+               goto out_unlock;
 
        curr = &sma->sem_base[semnum];
 
        switch (cmd) {
        case GETVAL:
-               return curr->semval;
+               err = curr->semval;
+               goto out_unlock;
        case GETPID:
-               return curr->sempid & 0xffff;
+               err = curr->sempid & 0xffff;
+               goto out_unlock;
        case GETNCNT:
-               return count_semncnt(sma,semnum);
+               err = count_semncnt(sma,semnum);
+               goto out_unlock;
        case GETZCNT:
-               return count_semzcnt(sma,semnum);
+               err = count_semzcnt(sma,semnum);
+               goto out_unlock;
        case SETVAL:
        {
                int val = arg.val;
                struct sem_undo *un;
+               err = -ERANGE;
                if (val > SEMVMX || val < 0)
-                       return -ERANGE;
+                       goto out_unlock;
 
                for (un = sma->undo; un; un = un->id_next)
                        un->semadj[semnum] = 0;
@@ -578,17 +614,22 @@ int semctl_locked(int semid, int semnum, int cmd, union semun arg)
                sma->sem_ctime = CURRENT_TIME;
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
-               return 0;
+               err = 0;
+               goto out_unlock;
        }
        }
-       return -EINVAL;
+out_unlock:
+       sem_unlock(semid);
+out_free:
+       if(sem_io != fast_sem_io)
+               ipc_free(sem_io, sizeof(ushort)*nsems);
+       return err;
 }
 
 int semctl_down(int semid, int semnum, int cmd, union semun arg)
 {
        struct semid_ds *sma;
        int err;
-       int lid = semid % SEMMNI;
        struct semid_ds tbuf;
        struct ipc_perm *ipcp;
 
@@ -596,66 +637,25 @@ int semctl_down(int semid, int semnum, int cmd, union semun arg)
                if(copy_from_user (&tbuf, arg.buf, sizeof (tbuf)))
                        return -EFAULT;
        }
-       spin_lock(&semary[lid].lock);
-       sma = semary[lid].s;
-       err=-EINVAL;
-       if (sma == NULL)
+       sma = sem_lock(semid);
+       if(sma==NULL)
+               return -EINVAL;
+
+       if (sem_checkid(sma,semid)) {
+               err=-EIDRM;
                goto out_unlock;
+       }       
        ipcp = &sma->sem_perm;
        
-       if(cmd == SETALL) {
-               int i;
-               struct sem_undo *un;
-               unsigned int nsems;
-               ushort sem_io[SEMMSL];
-               /* SETALL doesn't belong into this
-                * group, but I need the semaphore
-                * for atomically reading nsems
-                * and changing the semaphore values
-                */
-               err=-EACCES;
-               if (ipcperms (ipcp, S_IWUGO))
-                       goto out_unlock;
-               nsems=sma->sem_nsems;
-               spin_unlock(&semary[lid].lock);
-
-               if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort)))
-                       return -EFAULT;
-               for (i = 0; i < nsems; i++) {
-                       if (sem_io[i] > SEMVMX) {
-                               return -ERANGE;
-                       }
-               }
-               /* we still own sem_lock, ie neither ownership
-                * nor permissions of the sem array could
-                * have changed. Just continue.
-                */
-               spin_lock(&semary[lid].lock);
-               for (i = 0; i < nsems; i++)
-                       sma->sem_base[i].semval = sem_io[i];
-               for (un = sma->undo; un; un = un->id_next)
-                       for (i = 0; i < nsems; i++)
-                               un->semadj[i] = 0;
-               sma->sem_ctime = CURRENT_TIME;
-               /* maybe some queued-up processes were waiting for this */
-               update_queue(sma);
-               err = 0;
-               goto out_unlock;
-       }
-
        if (current->euid != ipcp->cuid && 
            current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
                err=-EPERM;
                goto out_unlock;
        }
-               
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI) {
-               err=-EIDRM;
-               goto out_unlock;
-       }       
+
        switch(cmd){
        case IPC_RMID:
-               freeary(lid);
+               freeary(semid);
                err = 0;
                break;
        case IPC_SET:
@@ -664,27 +664,28 @@ int semctl_down(int semid, int semnum, int cmd, union semun arg)
                ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
                                | (tbuf.sem_perm.mode & S_IRWXUGO);
                sma->sem_ctime = CURRENT_TIME;
+               sem_unlock(semid);
                err = 0;
                break;
        default:
+               sem_unlock(semid);
                err = -EINVAL;
+               break;
        }
+       return err;
 
 out_unlock:
-       spin_unlock(&semary[lid].lock);
+       sem_unlock(semid);
        return err;
 }
 
 asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
 {
-       int lid; /* lock id */
        int err = -EINVAL;
 
-       if (semid < 0 || semnum < 0 || cmd < 0)
+       if (semid < 0)
                return -EINVAL;
 
-       lid = semid % SEMMNI;
-
        switch(cmd) {
        case IPC_INFO:
        case SEM_INFO:
@@ -692,25 +693,20 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
                err = semctl_nolock(semid,semnum,cmd,arg);
                return err;
        case GETALL:
-       case IPC_STAT:
-               spin_lock(&semary[lid].lock);
-               err = semctl_locked_unlock(semid,semnum,cmd,arg);
-               return err;
        case GETVAL:
        case GETPID:
        case GETNCNT:
        case GETZCNT:
+       case IPC_STAT:
        case SETVAL:
-               spin_lock(&semary[lid].lock);
-               err= semctl_locked(semid,semnum,cmd,arg);
-               spin_unlock(&semary[lid].lock);
-               return err;
        case SETALL:
+               err = semctl_main(semid,semnum,cmd,arg);
+               return err;
        case IPC_RMID:
        case IPC_SET:
-               down(&sem_lock);
-               err= semctl_down(semid,semnum,cmd,arg);
-               up(&sem_lock);
+               down(&sem_ids.sem);
+               err = semctl_down(semid,semnum,cmd,arg);
+               up(&sem_ids.sem);
                return err;
        default:
                return -EINVAL;
@@ -734,33 +730,27 @@ static struct sem_undo* freeundos(struct semid_ds *sma, struct sem_undo* un)
        return un->proc_next;
 }
 
+/* returns without sem_lock on error! */
 static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, int alter)
 {
-       int size;
+       int size, nsems, error;
        struct sem_undo *un;
-       int error,id;
-       id = (unsigned int) semid % SEMMNI;
-       size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
-       spin_unlock(&semary[id].lock);
+
+       nsems = sma->sem_nsems;
+       size = sizeof(struct sem_undo) + sizeof(short)*nsems;
+       sem_unlock(semid);
 
        un = (struct sem_undo *) kmalloc(size, GFP_KERNEL);
-       spin_lock(&semary[id].lock);
-       if (!un) {
+       if (!un)
                return -ENOMEM;
-       }
-       sma = semary[id].s;
-       error = -EIDRM;
-       if (sma == NULL)
-               goto out;
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-               goto out;
-       if (size != sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems)
-               goto out;
 
-       error = -EACCES;
-       if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-               goto out;
        memset(un, 0, size);
+       error = sem_revalidate(semid, sma, nsems, alter ? S_IWUGO : S_IRUGO);
+       if(error) {
+               kfree(un);
+               return error;
+       }
+
        un->semadj = (short *) &un[1];
        un->semid = semid;
        un->proc_next = current->semundo;
@@ -769,42 +759,42 @@ static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, in
        sma->undo = un;
        *unp = un;
        return 0;
-out:
-       kfree(un);
-       return error;
 }
 
 asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
-       int id, error = -EINVAL;
+       int error = -EINVAL;
        struct semid_ds *sma;
-       struct sembuf sops[SEMOPM], *sop;
+       struct sembuf fast_sops[SEMOPM_FAST];
+       struct sembuf* sops = fast_sops, *sop;
        struct sem_undo *un;
        int undos = 0, decrease = 0, alter = 0;
        struct sem_queue queue;
 
        if (nsops < 1 || semid < 0)
                return -EINVAL;
-
-       if (nsops > SEMOPM)
+       if (nsops > sc_semopm)
                return -E2BIG;
-       if (copy_from_user (sops, tsops, nsops * sizeof(*tsops)))
-               return -EFAULT;
-
-       id = (unsigned int) semid % SEMMNI;
-       spin_lock(&semary[id].lock);
-       sma = semary[id].s;
-       error = -EINVAL;
-       if (sma == NULL)
-               goto out;
+       if(nsops > SEMOPM_FAST) {
+               sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
+               if(sops==NULL)
+                       return -ENOMEM;
+       }
+       if (copy_from_user (sops, tsops, nsops * sizeof(*tsops))) {
+               error=-EFAULT;
+               goto out_free;
+       }
+       sma = sem_lock(semid);
+       error=-EINVAL;
+       if(sma==NULL)
+               goto out_free;
        error = -EIDRM;
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-               goto out;
-
+       if (sem_checkid(sma,semid))
+               goto out_unlock_free;
        error = -EFBIG;
        for (sop = sops; sop < sops + nsops; sop++) {
                if (sop->sem_num >= sma->sem_nsems)
-                       goto out;
+                       goto out_unlock_free;
                if (sop->sem_flg & SEM_UNDO)
                        undos++;
                if (sop->sem_op < 0)
@@ -816,7 +806,7 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 
        error = -EACCES;
        if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-               goto out;
+               goto out_unlock_free;
        if (undos) {
                /* Make sure we have an undo structure
                 * for this process and this semaphore set.
@@ -832,8 +822,8 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
                }
                if (!un) {
                        error = alloc_undo(sma,&un,semid,alter);
-                       if(error<0)
-                               goto out;
+                       if(error)
+                               goto out_free;
                }
        } else
                un = NULL;
@@ -852,25 +842,30 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
        queue.undo = un;
        queue.pid = current->pid;
        queue.alter = decrease;
-       queue.id = id;
-       current->semsleeping = &queue;
+       queue.id = semid;
        if (alter)
                append_to_queue(sma ,&queue);
        else
                prepend_to_queue(sma ,&queue);
+       current->semsleeping = &queue;
 
        for (;;) {
+               struct semid_ds* tmp;
                queue.status = -EINTR;
                queue.sleeper = current;
                current->state = TASK_INTERRUPTIBLE;
-               spin_unlock(&semary[id].lock);
+               sem_unlock(semid);
 
                schedule();
 
-               /* we can lock the semary even if it was
-                * deleted.
-                */
-               spin_lock(&semary[id].lock);
+               tmp = sem_lock(semid);
+               if(tmp==NULL) {
+                       if(queue.status != -EIDRM)
+                               BUG();
+                       current->semsleeping = NULL;
+                       error = -EIDRM;
+                       goto out_free;
+               }
                /*
                 * If queue.status == 1 we where woken up and
                 * have to retry else we simply return.
@@ -890,7 +885,7 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
                                break;
                        /* Everything done by update_queue */
                        current->semsleeping = NULL;
-                       goto out;
+                       goto out_unlock_free;
                }
        }
        current->semsleeping = NULL;
@@ -898,8 +893,11 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 update:
        if (alter)
                update_queue (sma);
-out:
-       spin_unlock(&semary[id].lock);
+out_unlock_free:
+       sem_unlock(semid);
+out_free:
+       if(sops != fast_sops)
+               kfree(sops);
        return error;
 }
 
@@ -925,34 +923,32 @@ void sem_exit (void)
        /* If the current process was sleeping for a semaphore,
         * remove it from the queue.
         */
-       /* semsleeping is part of "current", and it
-        * is never modified by another thread.
-        * No synchronization required.
-        */
        if ((q = current->semsleeping)) {
-               spin_lock(&semary[current->semsleeping->id].lock);
+               int semid = q->id;
+               sma = sem_lock(semid);
+               current->semsleeping = NULL;
 
-               if (q->prev)
+               if (q->prev) {
+                       if(sma==NULL)
+                               BUG();
                        remove_from_queue(q->sma,q);
-               current->semsleeping = NULL;
-               spin_unlock(&semary[current->semsleeping->id].lock);
+               }
+               if(sma!=NULL)
+                       sem_unlock(semid);
        }
 
        for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
                int semid = u->semid;
-               int lid;
                if(semid == -1)
                        continue;
-               lid = semid % SEMMNI;
-               spin_lock(&semary[lid].lock);
+               sma = sem_lock(semid);
+               if (sma == NULL)
+                       continue;
 
                if (u->semid == -1)
                        goto next_entry;
 
-               sma = semary[lid].s;
-               if (sma == NULL)
-                       goto next_entry;
-               if (sma->sem_perm.seq != (unsigned int) u->semid / SEMMNI)
+               if (sem_checkid(sma,u->semid))
                        goto next_entry;
 
                /* remove u from the sma->undo list */
@@ -977,7 +973,7 @@ found:
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
 next_entry:
-               spin_unlock(&semary[lid].lock);
+               sem_unlock(semid);
        }
        current->semundo = NULL;
 }
@@ -990,35 +986,37 @@ static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int l
        int i, len = 0;
 
        len += sprintf(buffer, "       key      semid perms nsems   uid   gid  cuid  cgid      otime      ctime\n");
-       down(&sem_lock);
+       down(&sem_ids.sem);
 
-       for(i = 0; i < SEMMNI; i++)
-               if(semary[i].s != NULL) {
-                       spin_lock(&semary[i].lock);
+       for(i = 0; i <= sem_ids.max_id; i++) {
+               struct semid_ds *sma;
+               sma = sem_lock(i);
+               if(sma) {
                        len += sprintf(buffer + len, "%10d %10d  %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
-                               semary[i].s->sem_perm.key,
-                               semary[i].s->sem_perm.seq * SEMMNI + i,
-                               semary[i].s->sem_perm.mode,
-                               semary[i].s->sem_nsems,
-                               semary[i].s->sem_perm.uid,
-                               semary[i].s->sem_perm.gid,
-                               semary[i].s->sem_perm.cuid,
-                               semary[i].s->sem_perm.cgid,
-                               semary[i].s->sem_otime,
-                               semary[i].s->sem_ctime);
-                       spin_unlock(&semary[i].lock);
+                               sma->sem_perm.key,
+                               sem_buildid(i,sma->sem_perm.seq),
+                               sma->sem_perm.mode,
+                               sma->sem_nsems,
+                               sma->sem_perm.uid,
+                               sma->sem_perm.gid,
+                               sma->sem_perm.cuid,
+                               sma->sem_perm.cgid,
+                               sma->sem_otime,
+                               sma->sem_ctime);
+                       sem_unlock(i);
 
                        pos += len;
                        if(pos < offset) {
                                len = 0;
-                       begin = pos;
+                               begin = pos;
                        }
                        if(pos > offset + length)
                                goto done;
                }
+       }
        *eof = 1;
 done:
-       up(&sem_lock);
+       up(&sem_ids.sem);
        *start = buffer + (offset - begin);
        len -= (offset - begin);
        if(len > length)
index b391c44899a46f16bd9a6435404d52b927b7f817..2ba2ab047ebf2f30b2f5042f96189de25c580b18 100644 (file)
@@ -6,6 +6,8 @@
  *            get BSD style process accounting right.
  *            Occurs in several places in the IPC code.
  *            Chris Evans, <chris@ferret.lmh.ox.ac.uk>
+ * Nov 1999 - ipc helper functions, unified SMP locking
+ *           Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/config.h>
 #include <linux/shm.h>
 #include <linux/init.h>
 #include <linux/msg.h>
-
-#include "util.h"
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
+#include <linux/malloc.h>
 
 #if defined(CONFIG_SYSVIPC)
 
-extern void sem_init (void), msg_init (void), shm_init (void);
+#include "util.h"
 
 void __init ipc_init (void)
 {
@@ -28,6 +31,157 @@ void __init ipc_init (void)
        return;
 }
 
+void __init ipc_init_ids(struct ipc_ids* ids, int size)
+{
+       int i;
+       sema_init(&ids->sem,1);
+       ids->size = size;
+       if(size == 0)
+               return;
+       if(size > IPCMNI)
+               size = IPCMNI;
+
+       ids->in_use = 0;
+       ids->max_id = -1;
+       ids->seq = 0;
+       {
+               int seq_limit = INT_MAX/SEQ_MULTIPLIER;
+               if(seq_limit > USHRT_MAX)
+                       ids->seq_max = USHRT_MAX;
+                else
+                       ids->seq_max = seq_limit;
+       }
+
+       ids->entries = ipc_alloc(sizeof(struct ipc_id)*size);
+
+       if(ids->entries == NULL) {
+               printk(KERN_ERR "ipc_init_ids() failed, ipc service disabled.\n");
+               ids->size = 0;
+       }
+       ids->ary = SPIN_LOCK_UNLOCKED;
+       for(i=0;i<size;i++) {
+               ids->entries[i].p = NULL;
+       }
+}
+
+int ipc_findkey(struct ipc_ids* ids, key_t key)
+{
+       int id;
+       struct ipc_perm* p;
+
+       for (id = 0; id <= ids->max_id; id++) {
+               p = ids->entries[id].p;
+               if(p==NULL)
+                       continue;
+               if (key == p->key)
+                       return id;
+       }
+       return -1;
+}
+
+static int grow_ary(struct ipc_ids* ids, int newsize)
+{
+       struct ipc_id* new;
+       struct ipc_id* old;
+       int i;
+
+       if(newsize > IPCMNI)
+               newsize = IPCMNI;
+       if(newsize <= ids->size)
+               return newsize;
+
+       new = ipc_alloc(sizeof(struct ipc_id)*newsize);
+       if(new == NULL)
+               return ids->size;
+       memcpy(new, ids->entries, sizeof(struct ipc_id)*ids->size);
+       for(i=ids->size;i<newsize;i++) {
+               new[i].p = NULL;
+       }
+       spin_lock(&ids->ary);
+
+       old = ids->entries;
+       ids->entries = new;
+       i = ids->size;
+       ids->size = newsize;
+       spin_unlock(&ids->ary);
+       ipc_free(old, sizeof(struct ipc_id)*i);
+       return ids->size;
+}
+
+int ipc_addid(struct ipc_ids* ids, struct ipc_perm* new, int size)
+{
+       int id;
+
+       size = grow_ary(ids,size);
+       for (id = 0; id < size; id++) {
+               if(ids->entries[id].p == NULL)
+                       goto found;
+       }
+       return -1;
+found:
+       ids->in_use++;
+       if (id > ids->max_id)
+               ids->max_id = id;
+
+       new->cuid = new->uid = current->euid;
+       new->gid = new->cgid = current->egid;
+
+       new->seq = ids->seq++;
+       if(ids->seq > ids->seq_max)
+               ids->seq = 0;
+
+       ipc_lock(ids,id);
+       ids->entries[id].p = new;
+       return id;
+}
+
+struct ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
+{
+       struct ipc_perm* p;
+       int lid = id % SEQ_MULTIPLIER;
+       if(lid > ids->size)
+               BUG();
+       p = ids->entries[lid].p;
+       ids->entries[lid].p = NULL;
+       if(p==NULL)
+               BUG();
+       ids->in_use--;
+
+       if (lid == ids->max_id) {
+               do {
+                       lid--;
+                       if(lid == -1)
+                               break;
+               } while (ids->entries[lid].p == NULL);
+               ids->max_id = lid;
+       }
+       return p;
+}
+
+void* ipc_alloc(int size)
+{
+       void* out;
+       if(size > PAGE_SIZE) {
+               lock_kernel();
+               out = vmalloc(size);
+               unlock_kernel();
+       } else {
+               out = kmalloc(size, GFP_KERNEL);
+       }
+       return out;
+}
+
+void ipc_free(void* ptr, int size)
+{
+       if(size > PAGE_SIZE) {
+               lock_kernel();
+               vfree(ptr);
+               unlock_kernel();
+       } else {
+               kfree(ptr);
+       }
+}
+
 /* 
  * Check user, group, other permissions for access
  * to ipc resources. return 0 if allowed
index 15bc68a286ecf978e5f40f6c49772ee36ad468a4..a58eadebc26bc5eb05b0b777ad2abad3b5c25653 100644 (file)
@@ -1,12 +1,78 @@
 /*
  * linux/ipc/util.h
  * Copyright (C) 1999 Christoph Rohland
+ *
+ * ipc helper functions (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
-/*
- * IPCMNI is the absolute maximum for ipc identifier. This is used to
- * detect stale identifiers
+#define USHRT_MAX 0xffff
+#define SEQ_MULTIPLIER (IPCMNI)
+
+void sem_init (void);
+void msg_init (void);
+void shm_init (void);
+
+struct ipc_ids {
+       int size;
+       int in_use;
+       int max_id;
+       unsigned short seq;
+       unsigned short seq_max;
+       struct semaphore sem;   
+       spinlock_t ary;
+       struct ipc_id* entries;
+};
+
+struct ipc_id {
+       struct ipc_perm* p;
+};
+
+
+void __init ipc_init_ids(struct ipc_ids* ids, int size);
+
+/* must be called with ids->sem acquired.*/
+int ipc_findkey(struct ipc_ids* ids, key_t key);
+int ipc_addid(struct ipc_ids* ids, struct ipc_perm* new, int size);
+
+/* must be called with both locks acquired. */
+struct ipc_perm* ipc_rmid(struct ipc_ids* ids, int id);
+
+int ipcperms (struct ipc_perm *ipcp, short flg);
+
+/* for rare, potentially huge allocations.
+ * both function can sleep
  */
-#define IPCMNI (1<<15)          
+void* ipc_alloc(int size);
+void ipc_free(void* ptr, int size);
+
+extern inline struct ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+{
+       struct ipc_perm* out;
+       int lid = id % SEQ_MULTIPLIER;
+       if(lid > ids->size)
+               return NULL;
+
+       spin_lock(&ids->ary);
+       out = ids->entries[lid].p;
+       if(out==NULL)
+               spin_unlock(&ids->ary);
+       return out;
+}
+
+extern inline void ipc_unlock(struct ipc_ids* ids, int id)
+{
+       spin_unlock(&ids->ary);
+}
+
+extern inline int ipc_buildid(struct ipc_ids* ids, int id, int seq)
+{
+       return SEQ_MULTIPLIER*seq + id;
+}
+
+extern inline int ipc_checkid(struct ipc_ids* ids, struct ipc_perm* ipcp, int uid)
+{
+       if(uid/SEQ_MULTIPLIER != ipcp->seq)
+               return 1;
+       return 0;
+}
 
-extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
index fd80b8c42b415a6afc96b203ebb029bfe8698506..9b82e4e555b035537aa3b34fd1c728f66bfff6d9 100644 (file)
@@ -60,7 +60,7 @@ unsigned long get_kcore_size(void)
        struct module * m;
 
        if (module_list == &kernel_module)
-               return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
+               return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE);
 
        /* shouldn't we have a rw spinlock for module_list? */
        lock_kernel();
@@ -992,7 +992,7 @@ get_module_symbol(char *modname, char *symname)
 /* no MODULES so high_memory is good enough for /proc/kcore (TA) */
 unsigned long get_kcore_size(void)
 {
-       return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
+       return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE);
 }
 
 
index 26ee5e29d692c7635a42f0b8cd20ec9d6c24458a..e3dd3a16dd649e429329f40ce2391430f7edd85a 100644 (file)
@@ -20,7 +20,7 @@ struct resource iomem_resource = { "PCI mem", 0x00000000, 0xFFFFFFFF, IORESOURCE
 static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
 
 /*
- * This generates reports for /proc/ioports and /proc/memory
+ * This generates reports for /proc/ioports and /proc/iomem
  */
 static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end)
 {
index 7d22b8217afdc9b9ec1eaf221d18cf22e423328e..f18ad13c15f38453f54b3ad5bf8b4387a52fa01d 100644 (file)
@@ -50,6 +50,10 @@ extern int sg_big_buff;
 #endif
 #ifdef CONFIG_SYSVIPC
 extern size_t shm_prm[];
+extern int msg_ctlmax;
+extern int msg_ctlmnb;
+extern int msg_ctlmni;
+extern int sem_ctls[];
 #endif
 
 #ifdef __sparc__
@@ -215,6 +219,14 @@ static ctl_table kern_table[] = {
 #ifdef CONFIG_SYSVIPC
        {KERN_SHMMAX, "shmmax", &shm_prm, 3*sizeof (size_t),
         0644, NULL, &proc_doulongvec_minmax},
+       {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int),
+        0644, NULL, &proc_dointvec},
+       {KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
+        0644, NULL, &proc_dointvec},
+       {KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int),
+        0644, NULL, &proc_dointvec},
+       {KERN_SEM, "sem", &sem_ctls, 4*sizeof (int),
+        0644, NULL, &proc_dointvec},
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
        {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
index 96e5d8508f70166446fab8d1e91135c495aca6ca..612a14d5c2ec33554b2d39f39e16a5e00c112cbf 100644 (file)
@@ -1999,6 +1999,7 @@ int unregister_netdevice(struct net_device *dev)
  *
  */
 
+extern void net_device_init(void);
 extern void ip_auto_config(void);
 
 int __init net_dev_init(void)