*** shm.c Thu Mar 7 17:30:21 2002 --- shm.c.new Thu Mar 7 17:00:05 2002 *************** *** 15,20 **** --- 15,28 ---- * */ + /* + * uClinux revisions for NO_MM + * + * A simplistic attempt to get shared memory under a mmu-less system. Uses + * the shm_file pointer as a pointer to a chunk of shared memory instead of + * a "struct file". + */ + #include #include #include *************** *** 27,33 **** #include "util.h" struct shmid_kernel /* private to the kernel */ ! { struct kern_ipc_perm shm_perm; struct file * shm_file; int id; --- 35,41 ---- #include "util.h" struct shmid_kernel /* private to the kernel */ ! { struct kern_ipc_perm shm_perm; struct file * shm_file; int id; *************** *** 42,49 **** --- 50,59 ---- #define shm_flags shm_perm.mode + #ifndef NO_MM static struct file_operations shm_file_operations; static struct vm_operations_struct shm_vm_ops; + #endif /* NO_MM */ static struct ipc_ids shm_ids; *************** *** 56,63 **** --- 66,75 ---- ipc_buildid(&shm_ids, id, seq) static int newseg (key_t key, int shmflg, size_t size); + #ifndef NO_MM static void shm_open (struct vm_area_struct *shmd); static void shm_close (struct vm_area_struct *shmd); + #endif /* NO_MM */ #ifdef CONFIG_PROC_FS static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); #endif *************** *** 106,116 **** --- 118,130 ---- shm_unlock(id); } + #ifndef NO_MM /* This is called by fork, once for every shm attach. */ static void shm_open (struct vm_area_struct *shmd) { shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino); } + #endif /* NO_MM */ /* * shm_destroy - free the struct shmid_kernel *************** *** 123,133 **** --- 137,152 ---- { shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; shm_rmid (shp->id); + #ifndef NO_MM shmem_lock(shp->shm_file, 0); fput (shp->shm_file); + #else + kfree (shp->shm_file); + #endif /* NO_MM */ kfree (shp); } + #ifndef NO_MM /* * remove the attach descriptor shmd. * free memory for segment if it is marked destroyed. *************** *** 172,177 **** --- 191,204 ---- close: shm_close, /* callback for when the vm-area is released */ nopage: shmem_nopage, }; + #else + struct file *shmem_file_setup(char * name, loff_t size) + { + void * f = kmalloc(size, GFP_KERNEL); + + return (struct file *)(PTR_ERR(f) ? f : (void *)-ENOMEM); + } + #endif /* NO_MM */ static int newseg (key_t key, int shmflg, size_t size) { *************** *** 199,205 **** error = -ENOSPC; id = shm_addid(shp); ! if(id == -1) goto no_id; shp->shm_perm.key = key; shp->shm_flags = (shmflg & S_IRWXUGO); --- 226,232 ---- error = -ENOSPC; id = shm_addid(shp); ! if(id == -1) goto no_id; shp->shm_perm.key = key; shp->shm_flags = (shmflg & S_IRWXUGO); *************** *** 211,224 **** --- 238,258 ---- shp->shm_nattch = 0; shp->id = shm_buildid(id,shp->shm_perm.seq); shp->shm_file = file; + #ifndef NO_MM file->f_dentry->d_inode->i_ino = shp->id; file->f_op = &shm_file_operations; + #endif /* NO_MM */ shm_tot += numpages; shm_unlock (id); return shp->id; no_id: + #ifndef NO_MM fput(file); + #else + kfree(file); + #endif + no_file: kfree(shp); return error; *************** *** 284,290 **** uid_t uid; gid_t gid; mode_t mode; ! }; static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void *buf, int version) { --- 318,324 ---- uid_t uid; gid_t gid; mode_t mode; ! }; static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void *buf, int version) { *************** *** 337,343 **** out.shmmin = in->shmmin; out.shmmni = in->shmmni; out.shmseg = in->shmseg; ! out.shmall = in->shmall; return copy_to_user(buf, &out, sizeof(out)); } --- 371,377 ---- out.shmmin = in->shmmin; out.shmmni = in->shmmni; out.shmseg = in->shmseg; ! out.shmall = in->shmall; return copy_to_user(buf, &out, sizeof(out)); } *************** *** 346,354 **** } } ! static void shm_get_stat (unsigned long *rss, unsigned long *swp) { struct shmem_inode_info *info; int i; *rss = 0; --- 380,390 ---- } } ! static void shm_get_stat (unsigned long *rss, unsigned long *swp) { + #ifndef NO_MM struct shmem_inode_info *info; + #endif int i; *rss = 0; *************** *** 356,372 **** --- 392,414 ---- for(i = 0; i <= shm_ids.max_id; i++) { struct shmid_kernel* shp; + #ifndef NO_MM struct inode * inode; + #endif shp = shm_get(i); if(shp == NULL) continue; + #ifndef NO_MM inode = shp->shm_file->f_dentry->d_inode; info = SHMEM_I(inode); spin_lock (&info->lock); *rss += inode->i_mapping->nrpages; *swp += info->swapped; spin_unlock (&info->lock); + #else + *rss += (shp->shm_segsz + PAGE_SIZE -1) >> PAGE_SHIFT; + #endif } } *************** *** 472,481 **** --- 514,527 ---- if(err) goto out_unlock; if(cmd==SHM_LOCK) { + #ifndef NO_MM shmem_lock(shp->shm_file, 1); + #endif /* NO_MM */ shp->shm_flags |= SHM_LOCKED; } else { + #ifndef NO_MM shmem_lock(shp->shm_file, 0); + #endif /* NO_MM */ shp->shm_flags &= ~SHM_LOCKED; } shm_unlock(shmid); *************** *** 487,493 **** * We cannot simply remove the file. The SVID states * that the block remains until the last person * detaches from it, then is deleted. A shmat() on ! * an RMID segment is legal in older Linux and if * we change it apps break... * * Instead we set a destroyed flag, and then blow --- 533,539 ---- * We cannot simply remove the file. The SVID states * that the block remains until the last person * detaches from it, then is deleted. A shmat() on ! * an RMID segment is legal in older Linux and if * we change it apps break... * * Instead we set a destroyed flag, and then blow *************** *** 496,508 **** down(&shm_ids.sem); shp = shm_lock(shmid); err = -EINVAL; ! if (shp == NULL) goto out_up; err = shm_checkid(shp, shmid); if(err) goto out_unlock_up; if (current->euid != shp->shm_perm.uid && ! current->euid != shp->shm_perm.cuid && !capable(CAP_SYS_ADMIN)) { err=-EPERM; goto out_unlock_up; --- 542,554 ---- down(&shm_ids.sem); shp = shm_lock(shmid); err = -EINVAL; ! if (shp == NULL) goto out_up; err = shm_checkid(shp, shmid); if(err) goto out_unlock_up; if (current->euid != shp->shm_perm.uid && ! current->euid != shp->shm_perm.cuid && !capable(CAP_SYS_ADMIN)) { err=-EPERM; goto out_unlock_up; *************** *** 534,540 **** goto out_unlock_up; err=-EPERM; if (current->euid != shp->shm_perm.uid && ! current->euid != shp->shm_perm.cuid && !capable(CAP_SYS_ADMIN)) { goto out_unlock_up; } --- 580,586 ---- goto out_unlock_up; err=-EPERM; if (current->euid != shp->shm_perm.uid && ! current->euid != shp->shm_perm.cuid && !capable(CAP_SYS_ADMIN)) { goto out_unlock_up; } *************** *** 569,576 **** --- 615,624 ---- { struct shmid_kernel *shp; unsigned long addr; + #ifndef NO_MM unsigned long size; struct file * file; + #endif /* NO_MM */ int err; unsigned long flags; unsigned long prot; *************** *** 622,633 **** --- 670,684 ---- shm_unlock(shmid); return -EACCES; } + #ifndef NO_MM file = shp->shm_file; size = file->f_dentry->d_inode->i_size; + #endif /* NO_MM */ shp->shm_nattch++; shm_unlock(shmid); down_write(¤t->mm->mmap_sem); + #ifndef NO_MM if (addr && !(shmflg & SHM_REMAP)) { user_addr = ERR_PTR(-EINVAL); if (find_vma_intersection(current->mm, addr, addr + size)) *************** *** 640,647 **** addr > current->mm->start_stack - size - PAGE_SIZE * 5) goto invalid; } ! user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0); invalid: up_write(¤t->mm->mmap_sem); --- 691,708 ---- addr > current->mm->start_stack - size - PAGE_SIZE * 5) goto invalid; } ! user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0); + #else + if (addr) { + user_addr = ERR_PTR(-EINVAL); + goto invalid; + } + + user_addr = (void*)shp->shm_file; + if (user_addr) + shm_inc(shmid); + #endif /* NO_MM */ invalid: up_write(¤t->mm->mmap_sem); *************** *** 670,675 **** --- 731,737 ---- */ asmlinkage long sys_shmdt (char *shmaddr) { + #ifndef NO_MM struct mm_struct *mm = current->mm; struct vm_area_struct *shmd, *shmdnext; *************** *** 681,686 **** --- 743,771 ---- do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start); } up_write(&mm->mmap_sem); + #else + int i; + + down (&shm_ids.sem); + for(i= 0; i <= shm_ids.max_id; i++) { + struct shmid_kernel* shp; + + shp = shm_lock(i); + if(shp!=NULL) { + if (shp->shm_file == (struct file *)shmaddr) { + shp->shm_lprid = current->pid; + shp->shm_dtim = CURRENT_TIME; + shp->shm_nattch--; + if(shp->shm_nattch == 0 && + shp->shm_flags & SHM_DEST) + shm_destroy (shp); + i = shm_ids.max_id+1; /* Make this the last iteration */ + } + shm_unlock(i); + } + } + up (&shm_ids.sem); + #endif /* NO_MM */ return 0; }