--- 2.4.19pre8aa3/ipc/shm.c.~1~ Wed May 15 22:37:20 2002 +++ 2.4.19pre8aa3/ipc/shm.c Mon May 20 06:18:11 2002 @@ -117,12 +117,15 @@ static void shm_open (struct vm_area_str * * @shp: struct to free * - * It has to be called with shp and shm_ids.sem locked + * It has to be called with the id locked and the shm_ids.sem + * held. Before returning it unlocks the id internally. fput() + * is a blocking operation. */ -static void shm_destroy (struct shmid_kernel *shp) +static void shm_destroy (struct shmid_kernel *shp, int id) { - shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; shm_rmid (shp->id); + shm_unlock(id); + shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; shmem_lock(shp->shm_file, 0); fput (shp->shm_file); kfree (shp); @@ -149,9 +152,9 @@ static void shm_close (struct vm_area_st shp->shm_nattch--; if(shp->shm_nattch == 0 && shp->shm_flags & SHM_DEST) - shm_destroy (shp); - - shm_unlock(id); + shm_destroy (shp, id); + else + shm_unlock(id); up (&shm_ids.sem); } @@ -512,11 +515,11 @@ asmlinkage long sys_shmctl (int shmid, i shp->shm_flags |= SHM_DEST; /* Do not find it any more */ shp->shm_perm.key = IPC_PRIVATE; + shm_unlock(shmid); } else - shm_destroy (shp); + shm_destroy (shp, shmid); /* Unlock */ - shm_unlock(shmid); up(&shm_ids.sem); return err; } @@ -653,8 +656,9 @@ invalid: shp->shm_nattch--; if(shp->shm_nattch == 0 && shp->shm_flags & SHM_DEST) - shm_destroy (shp); - shm_unlock(shmid); + shm_destroy (shp, shmid); + else + shm_unlock(shmid); up (&shm_ids.sem); *raddr = (unsigned long) user_addr;