mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-05-20 11:44:14 +00:00
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>
This commit is contained in:
committed by
Linus Torvalds
parent
f4566f0485
commit
3e148c7993
28
ipc/util.h
28
ipc/util.h
@@ -32,7 +32,7 @@ struct ipc_ids {
|
||||
int in_use;
|
||||
unsigned short seq;
|
||||
unsigned short seq_max;
|
||||
struct mutex mutex;
|
||||
struct rw_semaphore rw_mutex;
|
||||
struct idr ipcs_idr;
|
||||
};
|
||||
|
||||
@@ -81,8 +81,10 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
|
||||
|
||||
#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
|
||||
|
||||
/* must be called with ids->mutex acquired.*/
|
||||
/* must be called with ids->rw_mutex acquired for writing */
|
||||
int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
|
||||
|
||||
/* must be called with ids->rw_mutex acquired for reading */
|
||||
int ipc_get_maxid(struct ipc_ids *);
|
||||
|
||||
/* must be called with both locks acquired. */
|
||||
@@ -107,6 +109,11 @@ void* ipc_rcu_alloc(int size);
|
||||
void ipc_rcu_getref(void *ptr);
|
||||
void ipc_rcu_putref(void *ptr);
|
||||
|
||||
/*
|
||||
* ipc_lock_down: called with rw_mutex held
|
||||
* ipc_lock: called without that lock held
|
||||
*/
|
||||
struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *, int);
|
||||
struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
|
||||
|
||||
void 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)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids,
|
||||
int id)
|
||||
{
|
||||
struct kern_ipc_perm *out;
|
||||
|
||||
out = ipc_lock_down(ids, id);
|
||||
if (IS_ERR(out))
|
||||
return out;
|
||||
|
||||
if (ipc_checkid(ids, out, id)) {
|
||||
ipc_unlock(out);
|
||||
return ERR_PTR(-EIDRM);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids,
|
||||
int id)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user