2005-04-17 02:20:36 +04:00
/*
* linux / ipc / util . h
* Copyright ( C ) 1999 Christoph Rohland
*
2006-01-15 04:43:54 +03:00
* ipc helper functions ( c ) 1999 Manfred Spraul < manfred @ colorfullife . com >
2006-10-02 13:18:20 +04:00
* namespaces support . 2006 OpenVZ , SWsoft Inc .
* Pavel Emelianov < xemul @ openvz . org >
2005-04-17 02:20:36 +04:00
*/
# ifndef _IPC_UTIL_H
# define _IPC_UTIL_H
2007-10-19 10:40:48 +04:00
# include <linux/idr.h>
2007-10-19 10:40:51 +04:00
# include <linux/err.h>
2007-10-19 10:40:48 +04:00
2005-04-17 02:20:36 +04:00
# define USHRT_MAX 0xffff
# define SEQ_MULTIPLIER (IPCMNI)
void sem_init ( void ) ;
void msg_init ( void ) ;
void shm_init ( void ) ;
2006-10-02 13:18:20 +04:00
int sem_init_ns ( struct ipc_namespace * ns ) ;
int msg_init_ns ( struct ipc_namespace * ns ) ;
int shm_init_ns ( struct ipc_namespace * ns ) ;
void sem_exit_ns ( struct ipc_namespace * ns ) ;
void msg_exit_ns ( struct ipc_namespace * ns ) ;
void shm_exit_ns ( struct ipc_namespace * ns ) ;
2005-04-17 02:20:36 +04:00
struct ipc_ids {
int in_use ;
unsigned short seq ;
unsigned short seq_max ;
2006-03-26 13:37:17 +04:00
struct mutex mutex ;
2007-10-19 10:40:48 +04:00
struct idr ipcs_idr ;
2005-04-17 02:20:36 +04:00
} ;
2007-10-19 10:40:49 +04:00
/*
* Structure that holds the parameters needed by the ipc operations
* ( see after )
*/
struct ipc_params {
key_t key ;
int flg ;
union {
size_t size ; /* for shared memories */
int nsems ; /* for semaphores */
} u ; /* holds the getnew() specific param */
} ;
/*
* Structure that holds some ipc operations . This structure is used to unify
* the calls to sys_msgget ( ) , sys_semget ( ) , sys_shmget ( )
* . routine to call to create a new ipc object . Can be one of newque ,
* newary , newseg
* . routine to call to call to check permissions for a new ipc object .
* Can be one of security_msg_associate , security_sem_associate ,
* security_shm_associate
* . routine to call for an extra check if needed
*/
struct ipc_ops {
int ( * getnew ) ( struct ipc_namespace * , struct ipc_params * ) ;
int ( * associate ) ( void * , int ) ;
int ( * more_checks ) ( void * , struct ipc_params * ) ;
} ;
2005-09-07 02:17:09 +04:00
struct seq_file ;
2007-07-16 10:40:58 +04:00
2007-10-19 10:40:48 +04:00
void ipc_init_ids ( struct ipc_ids * ) ;
2005-09-07 02:17:09 +04:00
# ifdef CONFIG_PROC_FS
void __init ipc_init_proc_interface ( const char * path , const char * header ,
2006-10-02 13:18:20 +04:00
int ids , int ( * show ) ( struct seq_file * , void * ) ) ;
2005-09-07 02:17:09 +04:00
# else
# define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
# endif
2005-04-17 02:20:36 +04:00
2006-10-02 13:18:20 +04:00
# define IPC_SEM_IDS 0
# define IPC_MSG_IDS 1
# define IPC_SHM_IDS 2
2006-03-26 13:37:17 +04:00
/* must be called with ids->mutex acquired.*/
2007-10-19 10:40:48 +04:00
int ipc_addid ( struct ipc_ids * , struct kern_ipc_perm * , int ) ;
int ipc_get_maxid ( struct ipc_ids * ) ;
2005-04-17 02:20:36 +04:00
/* must be called with both locks acquired. */
2007-10-19 10:40:48 +04:00
void ipc_rmid ( struct ipc_ids * , struct kern_ipc_perm * ) ;
2005-04-17 02:20:36 +04:00
int ipcperms ( struct kern_ipc_perm * ipcp , short flg ) ;
/* for rare, potentially huge allocations.
* both function can sleep
*/
void * ipc_alloc ( int size ) ;
void ipc_free ( void * ptr , int size ) ;
/*
* For allocation that need to be freed by RCU .
* Objects are reference counted , they start with reference count 1.
* getref increases the refcount , the putref call that reduces the recount
* to 0 schedules the rcu destruction . Caller must guarantee locking .
*/
void * ipc_rcu_alloc ( int size ) ;
void ipc_rcu_getref ( void * ptr ) ;
void ipc_rcu_putref ( void * ptr ) ;
2007-10-19 10:40:51 +04:00
struct kern_ipc_perm * ipc_lock ( struct ipc_ids * , int ) ;
2005-04-17 02:20:36 +04:00
int ipc_buildid ( struct ipc_ids * ids , int id , int seq ) ;
void kernel_to_ipc64_perm ( struct kern_ipc_perm * in , struct ipc64_perm * out ) ;
void ipc64_perm_to_ipc_perm ( struct ipc64_perm * in , struct ipc_perm * out ) ;
2005-07-13 00:58:25 +04:00
# if defined(__ia64__) || defined(__x86_64__) || defined(__hppa__) || defined(__XTENSA__)
2005-04-17 02:20:36 +04:00
/* On IA-64, we always use the "64-bit version" of the IPC structures. */
# define ipc_parse_version(cmd) IPC_64
# else
int ipc_parse_version ( int * cmd ) ;
# endif
extern void free_msg ( struct msg_msg * msg ) ;
extern struct msg_msg * load_msg ( const void __user * src , int len ) ;
extern int store_msg ( void __user * dest , struct msg_msg * msg , int len ) ;
2007-10-19 10:40:49 +04:00
extern int ipcget_new ( struct ipc_namespace * , struct ipc_ids * ,
struct ipc_ops * , struct ipc_params * ) ;
extern int ipcget_public ( struct ipc_namespace * , struct ipc_ids * ,
struct ipc_ops * , struct ipc_params * ) ;
2007-10-19 10:40:51 +04:00
static inline int ipc_checkid ( struct ipc_ids * ids , struct kern_ipc_perm * ipcp ,
int uid )
{
if ( uid / SEQ_MULTIPLIER ! = ipcp - > seq )
return 1 ;
return 0 ;
}
static inline void ipc_lock_by_ptr ( struct kern_ipc_perm * perm )
{
rcu_read_lock ( ) ;
spin_lock ( & perm - > lock ) ;
}
static inline void ipc_unlock ( struct kern_ipc_perm * perm )
{
spin_unlock ( & perm - > lock ) ;
rcu_read_unlock ( ) ;
}
static inline struct kern_ipc_perm * ipc_lock_check ( struct ipc_ids * ids ,
int id )
{
struct kern_ipc_perm * out ;
out = ipc_lock ( ids , id ) ;
if ( IS_ERR ( out ) )
return out ;
if ( ipc_checkid ( ids , out , id ) ) {
ipc_unlock ( out ) ;
return ERR_PTR ( - EIDRM ) ;
}
return out ;
}
2007-10-19 10:40:49 +04:00
static inline int ipcget ( struct ipc_namespace * ns , struct ipc_ids * ids ,
struct ipc_ops * ops , struct ipc_params * params )
{
if ( params - > key = = IPC_PRIVATE )
return ipcget_new ( ns , ids , ops , params ) ;
else
return ipcget_public ( ns , ids , ops , params ) ;
}
2005-04-17 02:20:36 +04:00
# endif