X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=ipc%2Futil.h;h=9ffea40457cedb17eca4cc9df13ed1b3a5f1a3f7;hb=73cf60232ef16e1f8a64defa97214a1722db1e6c;hp=99414a36a2504e42d4745b184247537e1777d539;hpb=f4566f04854d78acfc74b9acb029744acde9d033;p=linux-2.6-omap-h63xx.git diff --git a/ipc/util.h b/ipc/util.h index 99414a36a25..9ffea40457c 100644 --- a/ipc/util.h +++ b/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); @@ -127,7 +134,7 @@ extern int ipcget_new(struct ipc_namespace *, struct ipc_ids *, extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *, struct ipc_ops *, struct ipc_params *); -static inline int ipc_buildid(struct ipc_ids *ids, int id, int seq) +static inline int ipc_buildid(int id, int seq) { return SEQ_MULTIPLIER * seq + id; } @@ -135,8 +142,7 @@ static inline int ipc_buildid(struct ipc_ids *ids, int id, int seq) /* * Must be called with ipcp locked */ -static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp, - int uid) +static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int uid) { if (uid / SEQ_MULTIPLIER != ipcp->seq) return 1; @@ -155,6 +161,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(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) { @@ -164,7 +187,7 @@ static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, if (IS_ERR(out)) return out; - if (ipc_checkid(ids, out, id)) { + if (ipc_checkid(out, id)) { ipc_unlock(out); return ERR_PTR(-EIDRM); }