aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/util.h
diff options
context:
space:
mode:
authorNadia Derbey <Nadia.Derbey@bull.net>2007-10-19 02:40:54 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:48 -0400
commit3e148c79938aa39035669c1cfa3ff60722134535 (patch)
tree0effb3edfece56ea38a9727ec8f4721d9a4c3ea8 /ipc/util.h
parentf4566f04854d78acfc74b9acb029744acde9d033 (diff)
fix idr_find() locking
This is a patch that fixes the way idr_find() used to be called in ipc_lock(): in all the paths that don't imply an update of the ipcs idr, it was called without the idr tree being locked. The changes are: . in ipc_ids, the mutex has been changed into a reader/writer semaphore. . ipc_lock() now takes the mutex as a reader during the idr_find(). . a new routine ipc_lock_down() has been defined: it doesn't take the mutex, assuming that it is being held by the caller. This is the routine that is now called in all the update paths. Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net> Acked-by: Jarek Poplawski <jarkao2@o2.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/util.h')
-rw-r--r--ipc/util.h28
1 files changed, 26 insertions, 2 deletions
diff --git a/ipc/util.h b/ipc/util.h
index 99414a36a250..bd47687077e0 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -32,7 +32,7 @@ struct ipc_ids {
32 int in_use; 32 int in_use;
33 unsigned short seq; 33 unsigned short seq;
34 unsigned short seq_max; 34 unsigned short seq_max;
35 struct mutex mutex; 35 struct rw_semaphore rw_mutex;
36 struct idr ipcs_idr; 36 struct idr ipcs_idr;
37}; 37};
38 38
@@ -81,8 +81,10 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
81 81
82#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) 82#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
83 83
84/* must be called with ids->mutex acquired.*/ 84/* must be called with ids->rw_mutex acquired for writing */
85int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); 85int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
86
87/* must be called with ids->rw_mutex acquired for reading */
86int ipc_get_maxid(struct ipc_ids *); 88int ipc_get_maxid(struct ipc_ids *);
87 89
88/* must be called with both locks acquired. */ 90/* must be called with both locks acquired. */
@@ -107,6 +109,11 @@ void* ipc_rcu_alloc(int size);
107void ipc_rcu_getref(void *ptr); 109void ipc_rcu_getref(void *ptr);
108void ipc_rcu_putref(void *ptr); 110void ipc_rcu_putref(void *ptr);
109 111
112/*
113 * ipc_lock_down: called with rw_mutex held
114 * ipc_lock: called without that lock held
115 */
116struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *, int);
110struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int); 117struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
111 118
112void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out); 119void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
@@ -155,6 +162,23 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm)
155 rcu_read_unlock(); 162 rcu_read_unlock();
156} 163}
157 164
165static inline struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids,
166 int id)
167{
168 struct kern_ipc_perm *out;
169
170 out = ipc_lock_down(ids, id);
171 if (IS_ERR(out))
172 return out;
173
174 if (ipc_checkid(ids, out, id)) {
175 ipc_unlock(out);
176 return ERR_PTR(-EIDRM);
177 }
178
179 return out;
180}
181
158static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, 182static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids,
159 int id) 183 int id)
160{ 184{