From: Pierre Peiffer Date: Tue, 29 Apr 2008 08:00:49 +0000 (-0700) Subject: IPC/semaphores: move the rwmutex handling inside semctl_down X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=522bb2a2b420a0c1d0fcd037aa4e1bb9e2bca447;p=openwrt%2Fstaging%2Fblogic.git IPC/semaphores: move the rwmutex handling inside semctl_down semctl_down is called with the rwmutex (the one which protects the list of ipcs) taken in write mode. This patch moves this rwmutex taken in write-mode inside semctl_down. This has the advantages of reducing a little bit the window during which this rwmutex is taken, clarifying sys_semctl, and finally of having a coherent behaviour with [shm|msg]ctl_down Signed-off-by: Pierre Peiffer Acked-by: Serge Hallyn Cc: Nadia Derbey Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/ipc/sem.c b/ipc/sem.c index 1b5ae352cde4..77162eddcbfc 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -875,6 +875,11 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __ } } +/* + * This function handles some semctl commands which require the rw_mutex + * to be held in write mode. + * NOTE: no locks must be held, the rw_mutex is taken inside this function. + */ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, int cmd, int version, union semun arg) { @@ -887,9 +892,12 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, if(copy_semid_from_user (&setbuf, arg.buf, version)) return -EFAULT; } + down_write(&sem_ids(ns).rw_mutex); sma = sem_lock_check_down(ns, semid); - if (IS_ERR(sma)) - return PTR_ERR(sma); + if (IS_ERR(sma)) { + err = PTR_ERR(sma); + goto out_up; + } ipcp = &sma->sem_perm; @@ -915,26 +923,22 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, switch(cmd){ case IPC_RMID: freeary(ns, ipcp); - err = 0; - break; + goto out_up; case IPC_SET: ipcp->uid = setbuf.uid; ipcp->gid = setbuf.gid; ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | (setbuf.mode & S_IRWXUGO); sma->sem_ctime = get_seconds(); - sem_unlock(sma); - err = 0; break; default: - sem_unlock(sma); err = -EINVAL; - break; } - return err; out_unlock: sem_unlock(sma); +out_up: + up_write(&sem_ids(ns).rw_mutex); return err; } @@ -968,9 +972,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) return err; case IPC_RMID: case IPC_SET: - down_write(&sem_ids(ns).rw_mutex); err = semctl_down(ns,semid,semnum,cmd,version,arg); - up_write(&sem_ids(ns).rw_mutex); return err; default: return -EINVAL;