diff -uNr 4-1-ac7/Documentation/Changes c1/Documentation/Changes --- 4-1-ac7/Documentation/Changes Wed May 31 20:29:23 2000 +++ c1/Documentation/Changes Fri Jun 2 13:22:23 2000 @@ -72,6 +72,18 @@ General Information =================== + System V shared memory is now implemented via a filesystem. You do +not have to mount it to use it as long as you can live with the +default maxima for shared memory and segments. If you wish to change +these variables, you have to mount it with the options nr_blocks +and/or nr_inodes. If you want to use POSIX shm, then it needs to be +mounted somewhere. The recommended place is /dev/shm and this can be +done by adding the following line to /etc/fstab: + +none /dev/shm shm defaults 0 0 + +Remember to create the directory that you intend to mount shm on. + now performs a cold reboot instead of a warm reboot for increased hardware compatibility. If you want a warm reboot and know it works on your hardware, add a "reboot=warm" command line option diff -uNr 4-1-ac7/Documentation/Configure.help c1/Documentation/Configure.help --- 4-1-ac7/Documentation/Configure.help Wed May 31 20:29:23 2000 +++ c1/Documentation/Configure.help Fri Jun 2 13:22:34 2000 @@ -2581,11 +2581,10 @@ http://www.linuxdoc.org/docs.html#guide . Shared memory is now implemented using a new (minimal) virtual file - system, which you need to mount before programs can use shared - memory. To do this automatically at system startup just add the + system. To mount it automatically at system startup just add the following line to your /etc/fstab: - none /var/shm shm defaults 0 0 + none /dev/shm shm defaults 0 0 Saying Y here enlarges your kernel by about 18 KB. Just say Y. diff -uNr 4-1-ac7/include/asm-s390/pgtable.h c1/include/asm-s390/pgtable.h --- 4-1-ac7/include/asm-s390/pgtable.h Mon May 22 15:02:03 2000 +++ c1/include/asm-s390/pgtable.h Wed May 31 20:38:47 2000 @@ -270,6 +270,7 @@ extern inline int pte_none(pte_t pte) { return ((pte_val(pte) & (_PAGE_INVALID | _PAGE_RO)) == _PAGE_INVALID); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = _PAGE_INVALID; } +#define PTE_INIT(x) pte_clear(x) extern inline int pte_pagenr(pte_t pte) { return ((unsigned long)((pte_val(pte) >> PAGE_SHIFT))); } extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } diff -uNr 4-1-ac7/ipc/shm.c c1/ipc/shm.c --- 4-1-ac7/ipc/shm.c Wed May 24 09:10:57 2000 +++ c1/ipc/shm.c Fri Jun 2 12:58:57 2000 @@ -16,11 +16,9 @@ * * The filesystem has the following restrictions/bugs: * 1) It only can handle one directory. - * 2) Because the directory is represented by the SYSV shm array it - * can only be mounted one time. - * 3) Private writeable mappings are not supported - * 4) Read and write are not implemented (should they?) - * 5) No special nodes are supported + * 2) Private writeable mappings are not supported + * 3) Read and write are not implemented (should they?) + * 4) No special nodes are supported * * There are the following mount options: * - nr_blocks (^= shmall) is the number of blocks of size PAGE_SIZE @@ -335,7 +333,7 @@ return (struct shmid_kernel *)ipc_rmid(&shm_ids,id); } -static __inline__ int shm_addid(struct shmid_kernel *shp) +static inline int shm_addid(struct shmid_kernel *shp) { return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1); } @@ -544,13 +542,37 @@ return 0; } -#define SHM_ENTRY(shp, index) (shp)->shm_dir[(index)/PTRS_PER_PTE][(index)%PTRS_PER_PTE] +/* + * We cannot use kmalloc for shm_alloc since this restricts the + * maximum size of the segments. + * + * We also cannot use vmalloc, since this uses too much of the vmalloc + * space and we run out of this on highend machines. + * + * So we have to use this complicated indirect scheme to alloc the shm + * page tables. + * + */ + +#ifdef PTE_INIT +static inline void init_ptes (pte_t *pte, int number) { + while (number--) + PTE_INIT (pte++); +} +#else +static inline void init_ptes (pte_t *pte, int number) { + memset (pte, 0, number*sizeof(*pte)); +} +#endif + +#define PTES_PER_PAGE (PAGE_SIZE/sizeof(pte_t)) +#define SHM_ENTRY(shp, index) (shp)->shm_dir[(index)/PTES_PER_PAGE][(index)%PTES_PER_PAGE] static pte_t **shm_alloc(unsigned long pages, int doacc) { - unsigned short dir = pages / PTRS_PER_PTE; - unsigned short last = pages % PTRS_PER_PTE; - pte_t **ret, **ptr, *pte; + unsigned short dir = pages / PTES_PER_PAGE; + unsigned short last = pages % PTES_PER_PAGE; + pte_t **ret, **ptr; if (pages == 0) return NULL; @@ -564,8 +586,7 @@ *ptr = (pte_t *)__get_free_page (GFP_KERNEL); if (!*ptr) goto free; - for (pte = *ptr; pte < *ptr + PTRS_PER_PTE; pte++) - pte_clear (pte); + init_ptes (*ptr, PTES_PER_PAGE); } /* The last one is probably not of PAGE_SIZE: we use kmalloc */ @@ -573,8 +594,7 @@ *ptr = kmalloc (last*sizeof(pte_t), GFP_KERNEL); if (!*ptr) goto free; - for (pte = *ptr; pte < *ptr + last; pte++) - pte_clear (pte); + init_ptes (*ptr, last); } if (doacc) { shm_lockall(); @@ -597,14 +617,14 @@ static void shm_free(pte_t** dir, unsigned long pages, int doacc) { int i, rss, swp; - pte_t **ptr = dir+pages/PTRS_PER_PTE; + pte_t **ptr = dir+pages/PTES_PER_PAGE; if (!dir) return; for (i = 0, rss = 0, swp = 0; i < pages ; i++) { pte_t pte; - pte = dir[i/PTRS_PER_PTE][i%PTRS_PER_PTE]; + pte = dir[i/PTES_PER_PAGE][i%PTES_PER_PAGE]; if (pte_none(pte)) continue; if (pte_present(pte)) { @@ -617,7 +637,7 @@ } /* first the last page */ - if (pages%PTRS_PER_PTE) + if (pages%PTES_PER_PAGE) kfree (*ptr); /* now the whole pages */ while (--ptr >= dir) @@ -663,10 +683,10 @@ BUG(); error = -ENOSPC; if (shm_tot - shp->shm_npages >= shm_ctlall) - goto out; + goto size_out; error = 0; if (shp->shm_segsz == attr->ia_size) - goto out; + goto size_out; /* Now we set them to the real values */ old_dir = shp->shm_dir; old_pages = shp->shm_npages; @@ -674,8 +694,8 @@ pte_t *swap; int i,j; i = old_pages < new_pages ? old_pages : new_pages; - j = i % PTRS_PER_PTE; - i /= PTRS_PER_PTE; + j = i % PTES_PER_PAGE; + i /= PTES_PER_PAGE; if (j) memcpy (new_dir[i], old_dir[i], j * sizeof (pte_t)); while (i--) { @@ -687,10 +707,21 @@ shp->shm_dir = new_dir; shp->shm_npages = new_pages; shp->shm_segsz = attr->ia_size; -out: +size_out: shm_unlock(inode->i_ino); shm_free (old_dir, old_pages, 1); + set_attr: + if (!(shp = shm_lock(inode->i_ino))) + BUG(); + if (attr->ia_valid & ATTR_MODE) + shp->shm_perm.mode = attr->ia_mode; + if (attr->ia_valid & ATTR_UID) + shp->shm_perm.uid = attr->ia_uid; + if (attr->ia_valid & ATTR_GID) + shp->shm_perm.gid = attr->ia_gid; + shm_unlock (inode->i_ino); + inode_setattr(inode, attr); return error; } @@ -1073,6 +1104,9 @@ case IPC_SET: { + struct dentry * dentry; + char name[SHM_FMT_LEN+1]; + if ((shmid % SEQ_MULTIPLIER)== zero_id) return -EINVAL; @@ -1098,7 +1132,29 @@ shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO) | (setbuf.mode & S_IRWXUGO); shp->shm_ctim = CURRENT_TIME; - break; + shm_unlock(shmid); + up(&shm_ids.sem); + + sprintf (name, SHM_FMT, shmid); + lock_kernel(); + dentry = lookup_one(name, lock_parent(shm_sb->s_root)); + unlock_dir(shm_sb->s_root); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto bad_dentry; + err = -ENOENT; + if (dentry->d_inode) { + struct inode *ino = dentry->d_inode; + ino->i_uid = setbuf.uid; + ino->i_gid = setbuf.gid; + ino->i_mode = (setbuf.mode & S_IRWXUGO) | (ino->i_mode & ~S_IALLUGO);; + ino->i_atime = ino->i_mtime = ino->i_ctime = CURRENT_TIME; + err = 0; + } + dput (dentry); + bad_dentry: + unlock_kernel(); + return err; } default: @@ -1492,7 +1548,7 @@ shm_lockall(); check_id: shp = shm_get(swap_id); - if(shp==NULL || shp->shm_flags & SHM_LOCKED) { + if(shp==NULL || shp->shm_flags & PRV_LOCKED) { next_id: swap_idx = 0; if (++swap_id > shm_ids.max_id) { diff -uNr 4-1-ac7/ipc/util.c c1/ipc/util.c --- 4-1-ac7/ipc/util.c Wed May 24 09:10:57 2000 +++ c1/ipc/util.c Wed May 31 20:30:48 2000 @@ -310,7 +310,7 @@ int map_zero_setup(struct vm_area_struct *vma) { - return -EINVAL; + return -ENOSYS; } #endif /* CONFIG_SYSVIPC */