diff -uNr linux-2.3.3.orig/CREDITS linux-2.3.3/CREDITS --- linux-2.3.3.orig/CREDITS Tue May 18 18:33:45 1999 +++ linux-2.3.3/CREDITS Mon May 17 16:32:06 1999 @@ -16,6 +16,14 @@ S: (ask for current address) S: Finland +N: Dragos Acostachioaie +E: dragos@iname.com +W: http://www.arbornet.org/~dragos +D: /proc/sysvipc +S: C. Negri 6, bl. D3 +S: Iasi 6600 +S: Romania + N: Dave Airlie E: airlied@linux.ie W: http://www.csn.ul.ie/~airlied diff -uNr linux-2.3.3.orig/fs/proc/Makefile linux-2.3.3/fs/proc/Makefile --- linux-2.3.3.orig/fs/proc/Makefile Thu Jun 25 00:30:10 1998 +++ linux-2.3.3/fs/proc/Makefile Mon May 17 16:32:07 1999 @@ -9,7 +9,7 @@ O_TARGET := proc.o O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \ - kmsg.o scsi.o proc_tty.o + kmsg.o scsi.o proc_tty.o sysvipc.o ifdef CONFIG_OMIRR O_OBJS := $(O_OBJS) omirr.o endif diff -uNr linux-2.3.3.orig/fs/proc/root.c linux-2.3.3/fs/proc/root.c --- linux-2.3.3.orig/fs/proc/root.c Wed Apr 28 18:47:39 1999 +++ linux-2.3.3/fs/proc/root.c Mon May 17 16:32:07 1999 @@ -155,7 +155,7 @@ &proc_root, NULL }; -struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus; +struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc; #ifdef CONFIG_MCA struct proc_dir_entry proc_mca = { @@ -681,6 +681,9 @@ proc_register(&proc_root, &proc_root_self); proc_net = create_proc_entry("net", S_IFDIR, 0); proc_scsi = create_proc_entry("scsi", S_IFDIR, 0); +#ifdef CONFIG_SYSVIPC + proc_sysvipc = create_proc_entry("sysvipc", S_IFDIR, 0); +#endif #ifdef CONFIG_SYSCTL proc_register(&proc_root, &proc_sys_root); #endif diff -uNr linux-2.3.3.orig/fs/proc/sysvipc.c linux-2.3.3/fs/proc/sysvipc.c --- linux-2.3.3.orig/fs/proc/sysvipc.c Thu Jan 1 02:00:00 1970 +++ linux-2.3.3/fs/proc/sysvipc.c Mon May 17 16:32:07 1999 @@ -0,0 +1,138 @@ +/* + * 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 +#include +#include +#include +#include + +#include + +#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, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; diff -uNr linux-2.3.3.orig/include/linux/proc_fs.h linux-2.3.3/include/linux/proc_fs.h --- linux-2.3.3.orig/include/linux/proc_fs.h Tue May 18 18:33:31 1999 +++ linux-2.3.3/include/linux/proc_fs.h Mon May 17 16:50:45 1999 @@ -52,7 +52,8 @@ PROC_STRAM, PROC_SOUND, PROC_MTRR, /* whether enabled or not */ - PROC_FS + PROC_FS, + PROC_SYSVIPC }; enum pid_directory_inos { @@ -243,6 +244,12 @@ PROC_CODA_FS_LAST }; +enum sysvipc_directory_inos { + PROC_SYSVIPC_SHM = PROC_CODA_FS_LAST, + PROC_SYSVIPC_SEM, + PROC_SYSVIPC_MSG +}; + /* Finally, the dynamically allocatable proc entries are reserved: */ #define PROC_DYNAMIC_FIRST 4096 @@ -313,6 +320,7 @@ 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 inode_operations proc_scsi_inode_operations; @@ -422,6 +430,7 @@ #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; /* * generic.c diff -uNr linux-2.3.3.orig/ipc/msg.c linux-2.3.3/ipc/msg.c --- linux-2.3.3.orig/ipc/msg.c Tue May 18 18:33:15 1999 +++ linux-2.3.3/ipc/msg.c Mon May 17 16:37:19 1999 @@ -8,6 +8,7 @@ * Fixed up the unchecked user space derefs * Copyright (C) 1998 Alan Cox & Andi Kleen * + * /proc/sysvipc/msg support (c) 1999 Dragos Acostachioaie */ #include @@ -15,6 +16,7 @@ #include #include #include +#include #include @@ -23,6 +25,9 @@ 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 static struct msqid_ds *msgque[MSGMNI]; static int msgbytes = 0; @@ -35,11 +40,18 @@ void __init msg_init (void) { int id; - +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif + for (id = 0; id < MSGMNI; id++) msgque[id] = (struct msqid_ds *) IPC_UNUSED; msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0; init_waitqueue_head(&msg_lock); +#ifdef CONFIG_PROC_FS + ent = create_proc_entry("sysvipc/msg", 0, 0); + ent->read_proc = sysvipc_msg_read_proc; +#endif return; } @@ -492,3 +504,49 @@ return err; } +#ifdef CONFIG_PROC_FS +static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +{ + off_t pos = 0; + off_t begin = 0; + int i, len = 0; + + len += sprintf(buffer, " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n"); + + for(i = 0; i < MSGMNI; i++) + if(msgque[i] != IPC_UNUSED) { + len += sprintf(buffer + len, "%10d %10d %4o %5u %5u %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", + msgque[i]->msg_perm.key, + msgque[i]->msg_perm.seq * MSGMNI + i, + msgque[i]->msg_perm.mode, + msgque[i]->msg_cbytes, + msgque[i]->msg_qnum, + msgque[i]->msg_lspid, + msgque[i]->msg_lrpid, + msgque[i]->msg_perm.uid, + msgque[i]->msg_perm.gid, + msgque[i]->msg_perm.cuid, + msgque[i]->msg_perm.cgid, + msgque[i]->msg_stime, + msgque[i]->msg_rtime, + msgque[i]->msg_ctime); + + pos += len; + if(pos < offset) { + len = 0; + begin = pos; + } + if(pos > offset + length) + goto done; + } + *eof = 1; +done: + *start = buffer + (offset - begin); + len -= (offset - begin); + if(len > length) + len = length; + if(len < 0) + len = 0; + return len; +} +#endif diff -uNr linux-2.3.3.orig/ipc/sem.c linux-2.3.3/ipc/sem.c --- linux-2.3.3.orig/ipc/sem.c Tue May 18 18:33:15 1999 +++ linux-2.3.3/ipc/sem.c Mon May 17 16:41:39 1999 @@ -48,11 +48,14 @@ * better but only get the semops right which only wait for zero or * increase. If there are decrement operations in the operations * array we do the same as before. + * + * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie */ #include #include #include +#include #include @@ -60,6 +63,9 @@ 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 static struct semid_ds *semary[SEMMNI]; static int used_sems = 0, used_semids = 0; @@ -71,11 +77,18 @@ void __init sem_init (void) { int i; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif init_waitqueue_head(&sem_lock); used_sems = used_semids = max_semid = sem_seq = 0; for (i = 0; i < SEMMNI; i++) semary[i] = (struct semid_ds *) IPC_UNUSED; +#ifdef CONFIG_PROC_FS + ent = create_proc_entry("sysvipc/sem", 0, 0); + ent->read_proc = sysvipc_sem_read_proc; +#endif return; } @@ -785,3 +798,46 @@ } current->semundo = NULL; } + +#ifdef CONFIG_PROC_FS +static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +{ + off_t pos = 0; + off_t begin = 0; + int i, len = 0; + + len += sprintf(buffer, " key semid perms nsems uid gid cuid cgid otime ctime\n"); + + for(i = 0; i < SEMMNI; i++) + if(semary[i] != IPC_UNUSED) { + len += sprintf(buffer + len, "%10d %10d %4o %5u %5u %5u %5u %5u %10lu %10lu\n", + semary[i]->sem_perm.key, + semary[i]->sem_perm.seq * SEMMNI + i, + semary[i]->sem_perm.mode, + semary[i]->sem_nsems, + semary[i]->sem_perm.uid, + semary[i]->sem_perm.gid, + semary[i]->sem_perm.cuid, + semary[i]->sem_perm.cgid, + semary[i]->sem_otime, + semary[i]->sem_ctime); + + pos += len; + if(pos < offset) { + len = 0; + begin = pos; + } + if(pos > offset + length) + goto done; + } + *eof = 1; +done: + *start = buffer + (offset - begin); + len -= (offset - begin); + if(len > length) + len = length; + if(len < 0) + len = 0; + return len; +} +#endif diff -uNr linux-2.3.3.orig/ipc/shm.c linux-2.3.3/ipc/shm.c --- linux-2.3.3.orig/ipc/shm.c Tue May 18 18:33:15 1999 +++ linux-2.3.3/ipc/shm.c Mon May 17 16:42:48 1999 @@ -4,6 +4,8 @@ * Many improvements/fixes by Bruno Haible. * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994. * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli. + * + * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie */ #include @@ -12,6 +14,7 @@ #include #include #include +#include #include #include @@ -26,6 +29,9 @@ static void shm_close (struct vm_area_struct *shmd); static unsigned long shm_nopage(struct vm_area_struct *, unsigned long, int); static int shm_swapout(struct vm_area_struct *, struct page *); +#ifdef CONFIG_PROC_FS +static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); +#endif static int shm_tot = 0; /* total number of shared memory pages */ static int shm_rss = 0; /* number of shared memory pages that are in memory */ @@ -44,11 +50,18 @@ void __init shm_init (void) { int id; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif for (id = 0; id < SHMMNI; id++) shm_segs[id] = (struct shmid_kernel *) IPC_UNUSED; shm_tot = shm_rss = shm_seq = max_shmid = used_segs = 0; init_waitqueue_head(&shm_lock); +#ifdef CONFIG_PROC_FS + ent = create_proc_entry("sysvipc/shm", 0, 0); + ent->read_proc = sysvipc_shm_read_proc; +#endif return; } @@ -762,3 +775,50 @@ return; } } + +#ifdef CONFIG_PROC_FS +static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +{ + off_t pos = 0; + off_t begin = 0; + int i, len = 0; + + len += sprintf(buffer, " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n"); + + for(i = 0; i < SHMMNI; i++) + if(shm_segs[i] != IPC_UNUSED) { + len += sprintf(buffer + len, "%10d %10d %4o %10d %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n", + shm_segs[i]->u.shm_perm.key, + shm_segs[i]->u.shm_perm.seq * SHMMNI + i, + shm_segs[i]->u.shm_perm.mode, + shm_segs[i]->u.shm_segsz, + shm_segs[i]->u.shm_cpid, + shm_segs[i]->u.shm_lpid, + shm_segs[i]->u.shm_nattch, + shm_segs[i]->u.shm_perm.uid, + shm_segs[i]->u.shm_perm.gid, + shm_segs[i]->u.shm_perm.cuid, + shm_segs[i]->u.shm_perm.cgid, + shm_segs[i]->u.shm_atime, + shm_segs[i]->u.shm_dtime, + shm_segs[i]->u.shm_ctime); + + pos += len; + if(pos < offset) { + len = 0; + begin = pos; + } + if(pos > offset + length) + goto done; + } + *eof = 1; +done: + *start = buffer + (offset - begin); + len -= (offset - begin); + if(len > length) + len = length; + if(len < 0) + len = 0; + return len; +} +#endif