The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/common/linux_ipc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: linux_ipc.c,v 1.51 2008/05/21 11:15:57 njoly Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Frank van der Linden and Eric Haszlakiewicz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: linux_ipc.c,v 1.51 2008/05/21 11:15:57 njoly Exp $");
   34 
   35 #if defined(_KERNEL_OPT)
   36 #include "opt_sysv.h"
   37 #endif
   38 
   39 #include <sys/param.h>
   40 #include <sys/shm.h>
   41 #include <sys/sem.h>
   42 #include <sys/msg.h>
   43 #include <sys/proc.h>
   44 #include <sys/systm.h>
   45 #include <sys/vnode.h>
   46 
   47 #include <sys/mount.h>
   48 #include <sys/syscallargs.h>
   49 
   50 #include <compat/linux/common/linux_types.h>
   51 #include <compat/linux/common/linux_signal.h>
   52 #include <compat/linux/common/linux_util.h>
   53 #include <compat/linux/common/linux_ipc.h>
   54 #include <compat/linux/common/linux_msg.h>
   55 #include <compat/linux/common/linux_shm.h>
   56 #include <compat/linux/common/linux_sem.h>
   57 
   58 #include <compat/linux/linux_syscallargs.h>
   59 #include <compat/linux/linux_syscall.h>
   60 
   61 #include <compat/linux/common/linux_ipccall.h>
   62 #include <compat/linux/common/linux_machdep.h>
   63 
   64 /*
   65  * Note: Not all linux architechtures have explicit versions
   66  *      of the SYSV* syscalls.  On the ones that don't
   67  *      we pretend that they are defined anyway.  *_args and
   68  *      prototypes are defined in individual headers;
   69  *      syscalls.master lists those syscalls as NOARGS.
   70  *
   71  *      The functions in multiarch are the ones that just need
   72  *      the arguments shuffled around and then use the
   73  *      normal NetBSD syscall.
   74  *
   75  * Function in multiarch:
   76  *      linux_sys_ipc           : linux_ipccall.c
   77  *      liunx_semop             : linux_ipccall.c
   78  *      linux_semget            : linux_ipccall.c
   79  *      linux_msgsnd            : linux_ipccall.c
   80  *      linux_msgrcv            : linux_ipccall.c
   81  *      linux_msgget            : linux_ipccall.c
   82  *      linux_shmdt             : linux_ipccall.c
   83  *      linux_shmget            : linux_ipccall.c
   84  */
   85 
   86 #if defined (SYSVSEM) || defined(SYSVSHM) || defined(SYSVMSG)
   87 /*
   88  * Convert between Linux and NetBSD ipc_perm structures. Only the
   89  * order of the fields is different.
   90  */
   91 void
   92 linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
   93 {
   94 
   95         bpp->_key = lpp->l_key;
   96         bpp->uid = lpp->l_uid;
   97         bpp->gid = lpp->l_gid;
   98         bpp->cuid = lpp->l_cuid;
   99         bpp->cgid = lpp->l_cgid;
  100         bpp->mode = lpp->l_mode;
  101         bpp->_seq = lpp->l_seq;
  102 }
  103 
  104 void
  105 linux_to_bsd_ipc64_perm(struct linux_ipc64_perm *lpp, struct ipc_perm *bpp)
  106 {
  107         bpp->_key = lpp->l_key;
  108         bpp->uid = lpp->l_uid;
  109         bpp->gid = lpp->l_gid;
  110         bpp->cuid = lpp->l_cuid;
  111         bpp->cgid = lpp->l_cgid;
  112         bpp->mode = lpp->l_mode;
  113         bpp->_seq = lpp->l_seq;
  114 }
  115 
  116 void
  117 bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
  118 {
  119 
  120         lpp->l_key = bpp->_key;
  121         lpp->l_uid = bpp->uid;
  122         lpp->l_gid = bpp->gid;
  123         lpp->l_cuid = bpp->cuid;
  124         lpp->l_cgid = bpp->cgid;
  125         lpp->l_mode = bpp->mode;
  126         lpp->l_seq = bpp->_seq;
  127 }
  128 
  129 void
  130 bsd_to_linux_ipc64_perm(struct ipc_perm *bpp, struct linux_ipc64_perm *lpp)
  131 {
  132         lpp->l_key = bpp->_key;
  133         lpp->l_uid = bpp->uid;
  134         lpp->l_gid = bpp->gid;
  135         lpp->l_cuid = bpp->cuid;
  136         lpp->l_cgid = bpp->cgid;
  137         lpp->l_mode = bpp->mode;
  138         lpp->l_seq = bpp->_seq;
  139 }
  140 
  141 #endif
  142 
  143 #ifdef SYSVSEM
  144 /*
  145  * Semaphore operations. Most constants and structures are the same on
  146  * both systems. Only semctl() needs some extra work.
  147  */
  148 
  149 /*
  150  * Convert between Linux and NetBSD semid_ds structures.
  151  */
  152 void
  153 bsd_to_linux_semid_ds(struct semid_ds *bs, struct linux_semid_ds *ls)
  154 {
  155         bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
  156         ls->l_sem_otime = bs->sem_otime;
  157         ls->l_sem_ctime = bs->sem_ctime;
  158         ls->l_sem_nsems = bs->sem_nsems;
  159         ls->l_sem_base = bs->_sem_base;
  160 }
  161 
  162 void
  163 bsd_to_linux_semid64_ds(struct semid_ds *bs, struct linux_semid64_ds *ls)
  164 {
  165         bsd_to_linux_ipc64_perm(&bs->sem_perm, &ls->l_sem_perm);
  166         ls->l_sem_otime = bs->sem_otime;
  167         ls->l_sem_ctime = bs->sem_ctime;
  168         ls->l_sem_nsems = bs->sem_nsems;
  169 }
  170 
  171 void
  172 linux_to_bsd_semid_ds(struct linux_semid_ds *ls, struct semid_ds *bs)
  173 {
  174         linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
  175         bs->sem_otime = ls->l_sem_otime;
  176         bs->sem_ctime = ls->l_sem_ctime;
  177         bs->sem_nsems = ls->l_sem_nsems;
  178         bs->_sem_base = ls->l_sem_base;
  179 }
  180 
  181 void
  182 linux_to_bsd_semid64_ds(struct linux_semid64_ds *ls, struct semid_ds *bs)
  183 {
  184         linux_to_bsd_ipc64_perm(&ls->l_sem_perm, &bs->sem_perm);
  185         bs->sem_otime = ls->l_sem_otime;
  186         bs->sem_ctime = ls->l_sem_ctime;
  187         bs->sem_nsems = ls->l_sem_nsems;
  188 }
  189 
  190 /*
  191  * Most of this can be handled by directly passing the arguments on; we
  192  * just need to frob the `cmd' and convert the semid_ds and semun.
  193  */
  194 int
  195 linux_sys_semctl(struct lwp *l, const struct linux_sys_semctl_args *uap, register_t *retval)
  196 {
  197         /* {
  198                 syscallarg(int) semid;
  199                 syscallarg(int) semnum;
  200                 syscallarg(int) cmd;
  201                 syscallarg(union linux_semun) arg;
  202         } */
  203         struct semid_ds sembuf;
  204         struct linux_semid_ds lsembuf;
  205         struct linux_semid64_ds lsembuf64;
  206         union __semun semun;
  207         int cmd, lcmd, error;
  208         void *pass_arg = NULL;
  209 
  210         lcmd = SCARG(uap, cmd);
  211 #ifdef LINUX_IPC_FORCE64
  212         if (lcmd == LINUX_IPC_STAT || lcmd == LINUX_IPC_SET)
  213                 lcmd |= LINUX_IPC_64;
  214 #endif
  215 
  216         switch (lcmd) {
  217         case LINUX_IPC_SET:
  218                 error = copyin(SCARG(uap, arg).l_buf, &lsembuf,
  219                     sizeof(lsembuf));
  220                 if (error)
  221                         return (error);
  222                 linux_to_bsd_semid_ds(&lsembuf, &sembuf);
  223                 pass_arg = &sembuf;
  224                 cmd = IPC_SET;
  225                 break;
  226 
  227         case LINUX_IPC_SET | LINUX_IPC_64:
  228                 error = copyin(SCARG(uap, arg).l_buf, &lsembuf64,
  229                     sizeof(lsembuf64));
  230                 if (error)
  231                         return (error);
  232                 linux_to_bsd_semid64_ds(&lsembuf64, &sembuf);
  233                 pass_arg = &sembuf;
  234                 cmd = IPC_SET;
  235                 break;
  236 
  237         case LINUX_IPC_STAT:
  238         case LINUX_IPC_STAT | LINUX_IPC_64:
  239                 pass_arg = &sembuf;
  240                 cmd = IPC_STAT;
  241                 break;
  242 
  243         case LINUX_IPC_RMID:
  244                 cmd = IPC_RMID;
  245                 break;
  246 
  247         case LINUX_GETVAL:
  248                 cmd = GETVAL;
  249                 break;
  250 
  251         case LINUX_GETPID:
  252                 cmd = GETPID;
  253                 break;
  254 
  255         case LINUX_GETNCNT:
  256                 cmd = GETNCNT;
  257                 break;
  258 
  259         case LINUX_GETZCNT:
  260                 cmd = GETZCNT;
  261                 break;
  262 
  263         case LINUX_GETALL:
  264                 pass_arg = &semun;
  265                 semun.array = SCARG(uap, arg).l_array;
  266                 cmd = GETALL;
  267                 break;
  268 
  269         case LINUX_SETVAL:
  270                 pass_arg = &semun;
  271                 semun.val = SCARG(uap, arg).l_val;
  272                 cmd = SETVAL;
  273                 break;
  274 
  275         case LINUX_SETALL:
  276                 pass_arg = &semun;
  277                 semun.array = SCARG(uap, arg).l_array;
  278                 cmd = SETALL;
  279                 break;
  280 
  281         default:
  282                 return (EINVAL);
  283         }
  284 
  285         error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
  286             pass_arg, retval);
  287         if (error)
  288                 return error;
  289 
  290         switch (lcmd) {
  291         case LINUX_IPC_STAT:
  292                 bsd_to_linux_semid_ds(&sembuf, &lsembuf);
  293                 error = copyout(&lsembuf, SCARG(uap, arg).l_buf,
  294                     sizeof(lsembuf));
  295                 break;
  296         case LINUX_IPC_STAT | LINUX_IPC_64:
  297                 bsd_to_linux_semid64_ds(&sembuf, &lsembuf64);
  298                 error = copyout(&lsembuf64, SCARG(uap, arg).l_buf,
  299                     sizeof(lsembuf64));
  300                 break;
  301         default:
  302                 break;
  303         }
  304 
  305         return (error);
  306 }
  307 #endif /* SYSVSEM */
  308 
  309 #ifdef SYSVMSG
  310 
  311 void
  312 linux_to_bsd_msqid_ds(struct linux_msqid_ds *lmp, struct msqid_ds *bmp)
  313 {
  314 
  315         linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
  316         bmp->_msg_first = lmp->l_msg_first;
  317         bmp->_msg_last = lmp->l_msg_last;
  318         bmp->_msg_cbytes = lmp->l_msg_cbytes;
  319         bmp->msg_qnum = lmp->l_msg_qnum;
  320         bmp->msg_qbytes = lmp->l_msg_qbytes;
  321         bmp->msg_lspid = lmp->l_msg_lspid;
  322         bmp->msg_lrpid = lmp->l_msg_lrpid;
  323         bmp->msg_stime = lmp->l_msg_stime;
  324         bmp->msg_rtime = lmp->l_msg_rtime;
  325         bmp->msg_ctime = lmp->l_msg_ctime;
  326 }
  327 
  328 void
  329 linux_to_bsd_msqid64_ds(struct linux_msqid64_ds *lmp, struct msqid_ds *bmp)
  330 {
  331         linux_to_bsd_ipc64_perm(&lmp->l_msg_perm, &bmp->msg_perm);
  332         bmp->msg_stime = lmp->l_msg_stime;
  333         bmp->msg_rtime = lmp->l_msg_rtime;
  334         bmp->msg_ctime = lmp->l_msg_ctime;
  335         bmp->_msg_cbytes = lmp->l_msg_cbytes;
  336         bmp->msg_qnum = lmp->l_msg_qnum;
  337         bmp->msg_qbytes = lmp->l_msg_qbytes;
  338         bmp->msg_lspid = lmp->l_msg_lspid;
  339         bmp->msg_lrpid = lmp->l_msg_lrpid;
  340 }
  341 
  342 void
  343 bsd_to_linux_msqid_ds(struct msqid_ds *bmp, struct linux_msqid_ds *lmp)
  344 {
  345 
  346         bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
  347         lmp->l_msg_first = bmp->_msg_first;
  348         lmp->l_msg_last = bmp->_msg_last;
  349         lmp->l_msg_cbytes = bmp->_msg_cbytes;
  350         lmp->l_msg_qnum = bmp->msg_qnum;
  351         lmp->l_msg_qbytes = bmp->msg_qbytes;
  352         lmp->l_msg_lspid = bmp->msg_lspid;
  353         lmp->l_msg_lrpid = bmp->msg_lrpid;
  354         lmp->l_msg_stime = bmp->msg_stime;
  355         lmp->l_msg_rtime = bmp->msg_rtime;
  356         lmp->l_msg_ctime = bmp->msg_ctime;
  357 }
  358 
  359 void
  360 bsd_to_linux_msqid64_ds(struct msqid_ds *bmp, struct linux_msqid64_ds *lmp)
  361 {
  362         bsd_to_linux_ipc64_perm(&bmp->msg_perm, &lmp->l_msg_perm);
  363         lmp->l_msg_stime = bmp->msg_stime;
  364         lmp->l_msg_rtime = bmp->msg_rtime;
  365         lmp->l_msg_ctime = bmp->msg_ctime;
  366         lmp->l_msg_cbytes = bmp->_msg_cbytes;
  367         lmp->l_msg_qnum = bmp->msg_qnum;
  368         lmp->l_msg_qbytes = bmp->msg_qbytes;
  369         lmp->l_msg_lspid = bmp->msg_lspid;
  370         lmp->l_msg_lrpid = bmp->msg_lrpid;
  371 }
  372 
  373 int
  374 linux_sys_msgctl(struct lwp *l, const struct linux_sys_msgctl_args *uap, register_t *retval)
  375 {
  376         /* {
  377                 syscallarg(int) msqid;
  378                 syscallarg(int) cmd;
  379                 syscallarg(struct linux_msqid_ds *) buf;
  380         } */
  381         struct msqid_ds bm, *bmp = NULL;
  382         struct linux_msqid_ds lm;
  383         struct linux_msqid64_ds lm64;
  384         int cmd, lcmd, error;
  385 
  386         lcmd = SCARG(uap, cmd);
  387 #ifdef LINUX_IPC_FORCE64
  388         if (lcmd == LINUX_IPC_STAT || lcmd == LINUX_IPC_SET)
  389                 lcmd |= LINUX_IPC_64;
  390 #endif
  391 
  392         switch (lcmd) {
  393         case LINUX_IPC_STAT:
  394         case LINUX_IPC_STAT|LINUX_IPC_64:
  395                 cmd = IPC_STAT;
  396                 bmp = &bm;
  397                 break;
  398         case LINUX_IPC_SET:
  399                 if ((error = copyin(SCARG(uap, buf), &lm, sizeof lm)))
  400                         return error;
  401                 linux_to_bsd_msqid_ds(&lm, &bm);
  402                 cmd = IPC_SET;
  403                 bmp = &bm;
  404                 break;
  405         case LINUX_IPC_SET|LINUX_IPC_64:
  406                 if ((error = copyin(SCARG(uap, buf), &lm64, sizeof lm64)))
  407                         return error;
  408                 linux_to_bsd_msqid64_ds(&lm64, &bm);
  409                 cmd = IPC_SET;
  410                 bmp = &bm;
  411                 break;
  412         case LINUX_IPC_RMID:
  413                 cmd = IPC_RMID;
  414                 break;
  415         default:
  416                 return EINVAL;
  417         }
  418 
  419         if ((error = msgctl1(l, SCARG(uap, msqid), cmd, bmp)))
  420                 return error;
  421 
  422         switch (lcmd) {
  423         case LINUX_IPC_STAT:
  424                 bsd_to_linux_msqid_ds(&bm, &lm);
  425                 error = copyout(&lm, SCARG(uap, buf), sizeof lm);
  426                 break;
  427         case LINUX_IPC_STAT|LINUX_IPC_64:
  428                 bsd_to_linux_msqid64_ds(&bm, &lm64);
  429                 error = copyout(&lm64, SCARG(uap, buf), sizeof lm64);
  430                 break;
  431         default:
  432                 break;
  433         }
  434 
  435         return error;
  436 }
  437 #endif /* SYSVMSG */
  438 
  439 #ifdef SYSVSHM
  440 /*
  441  * shmget(2). Just make sure the Linux-compatible shmat() semantics
  442  * is enabled for the segment, so that shmat() succeeds even when
  443  * the segment would be removed.
  444  */
  445 int
  446 linux_sys_shmget(struct lwp *l, const struct linux_sys_shmget_args *uap, register_t *retval)
  447 {
  448         /* {
  449                 syscallarg(key_t) key;
  450                 syscallarg(size_t) size;
  451                 syscallarg(int) shmflg;
  452         } */
  453         struct sys_shmget_args bsd_ua;
  454 
  455         SCARG(&bsd_ua, key) = SCARG(uap, key);
  456         SCARG(&bsd_ua, size) = SCARG(uap, size);
  457         SCARG(&bsd_ua, shmflg) = SCARG(uap, shmflg) | _SHM_RMLINGER;
  458 
  459         return sys_shmget(l, &bsd_ua, retval);
  460 }
  461 
  462 /*
  463  * shmat(2). Very straightforward, except that Linux passes a pointer
  464  * in which the return value is to be passed. This is subsequently
  465  * handled by libc, apparently.
  466  */
  467 #ifndef __amd64__
  468 int
  469 linux_sys_shmat(struct lwp *l, const struct linux_sys_shmat_args *uap, register_t *retval)
  470 {
  471         /* {
  472                 syscallarg(int) shmid;
  473                 syscallarg(void *) shmaddr;
  474                 syscallarg(int) shmflg;
  475                 syscallarg(u_long *) raddr;
  476         } */
  477         int error;
  478 
  479         if ((error = sys_shmat(l, (const void *)uap, retval)))
  480                 return error;
  481 
  482         if ((error = copyout(&retval[0], SCARG(uap, raddr), sizeof retval[0])))
  483                 return error;
  484 
  485         retval[0] = 0;
  486         return 0;
  487 }
  488 #endif /* __amd64__ */
  489 
  490 /*
  491  * Convert between Linux and NetBSD shmid_ds structures.
  492  * The order of the fields is once again the difference, and
  493  * we also need a place to store the internal data pointer
  494  * in, which is unfortunately stored in this structure.
  495  *
  496  * We abuse a Linux internal field for that.
  497  */
  498 void
  499 linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
  500 {
  501 
  502         linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
  503         bsp->shm_segsz = lsp->l_shm_segsz;
  504         bsp->shm_lpid = lsp->l_shm_lpid;
  505         bsp->shm_cpid = lsp->l_shm_cpid;
  506         bsp->shm_nattch = lsp->l_shm_nattch;
  507         bsp->shm_atime = lsp->l_shm_atime;
  508         bsp->shm_dtime = lsp->l_shm_dtime;
  509         bsp->shm_ctime = lsp->l_shm_ctime;
  510         bsp->_shm_internal = lsp->l_private2;   /* XXX Oh well. */
  511 }
  512 
  513 void
  514 linux_to_bsd_shmid64_ds(struct linux_shmid64_ds *lsp, struct shmid_ds *bsp)
  515 {
  516 
  517         linux_to_bsd_ipc64_perm(&lsp->l_shm_perm, &bsp->shm_perm);
  518         bsp->shm_segsz = lsp->l_shm_segsz;
  519         bsp->shm_lpid = lsp->l_shm_lpid;
  520         bsp->shm_cpid = lsp->l_shm_cpid;
  521         bsp->shm_nattch = lsp->l_shm_nattch;
  522         bsp->shm_atime = lsp->l_shm_atime;
  523         bsp->shm_dtime = lsp->l_shm_dtime;
  524         bsp->shm_ctime = lsp->l_shm_ctime;
  525         bsp->_shm_internal = (void*)lsp->l___unused5;   /* XXX Oh well. */
  526 }
  527 
  528 void
  529 bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
  530 {
  531 
  532         bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
  533         lsp->l_shm_segsz = bsp->shm_segsz;
  534         lsp->l_shm_lpid = bsp->shm_lpid;
  535         lsp->l_shm_cpid = bsp->shm_cpid;
  536         lsp->l_shm_nattch = bsp->shm_nattch;
  537         lsp->l_shm_atime = bsp->shm_atime;
  538         lsp->l_shm_dtime = bsp->shm_dtime;
  539         lsp->l_shm_ctime = bsp->shm_ctime;
  540         lsp->l_private2 = bsp->_shm_internal;   /* XXX */
  541 }
  542 
  543 void
  544 bsd_to_linux_shmid64_ds(struct shmid_ds *bsp, struct linux_shmid64_ds *lsp)
  545 {
  546         bsd_to_linux_ipc64_perm(&bsp->shm_perm, &lsp->l_shm_perm);
  547         lsp->l_shm_segsz = bsp->shm_segsz;
  548         lsp->l_shm_lpid = bsp->shm_lpid;
  549         lsp->l_shm_cpid = bsp->shm_cpid;
  550         lsp->l_shm_nattch = bsp->shm_nattch;
  551         lsp->l_shm_atime = bsp->shm_atime;
  552         lsp->l_shm_dtime = bsp->shm_dtime;
  553         lsp->l_shm_ctime = bsp->shm_ctime;
  554         lsp->l___unused5 = (u_long)bsp->_shm_internal;  /* XXX */
  555 }
  556 
  557 /*
  558  * shmctl.
  559  *
  560  * The usual structure conversion and massaging is done.
  561  */
  562 int
  563 linux_sys_shmctl(struct lwp *l, const struct linux_sys_shmctl_args *uap, register_t *retval)
  564 {
  565         /* {
  566                 syscallarg(int) shmid;
  567                 syscallarg(int) cmd;
  568                 syscallarg(struct linux_shmid_ds *) buf;
  569         } */
  570         struct shmid_ds bs;
  571         struct linux_shmid_ds ls;
  572         struct linux_shmid64_ds ls64;
  573         struct linux_shminfo64 lsi64;
  574         struct linux_shm_info lsi;
  575         int error, i, cmd, shmid;
  576 
  577         shmid = SCARG(uap, shmid);
  578         cmd = SCARG(uap, cmd);
  579 #ifdef LINUX_IPC_FORCE64
  580         if (cmd == LINUX_IPC_STAT || cmd == LINUX_SHM_STAT ||
  581             cmd == LINUX_IPC_SET)
  582                 cmd |= LINUX_IPC_64;
  583 #endif
  584 
  585         switch (cmd) {
  586         case LINUX_IPC_STAT:
  587         case LINUX_SHM_STAT:
  588                 if (cmd == LINUX_SHM_STAT) {
  589                         shmid = IXSEQ_TO_IPCID(shmid, shmsegs[shmid].shm_perm);
  590                         retval[0] = shmid;
  591                 }
  592                 error = shmctl1(l, shmid, IPC_STAT, &bs);
  593                 if (error != 0)
  594                         return error;
  595                 bsd_to_linux_shmid_ds(&bs, &ls);
  596                 return copyout(&ls, SCARG(uap, buf), sizeof ls);
  597 
  598         case LINUX_IPC_STAT | LINUX_IPC_64:
  599         case LINUX_SHM_STAT | LINUX_IPC_64:
  600                 if (cmd == (LINUX_SHM_STAT | LINUX_IPC_64)) {
  601                         shmid = IXSEQ_TO_IPCID(shmid, shmsegs[shmid].shm_perm);
  602                         retval[0] = shmid;
  603                 }
  604                 error = shmctl1(l, shmid, IPC_STAT, &bs);
  605                 if (error != 0)
  606                         return error;
  607                 bsd_to_linux_shmid64_ds(&bs, &ls64);
  608                 return copyout(&ls64, SCARG(uap, buf), sizeof ls64);
  609 
  610         case LINUX_IPC_SET:
  611                 if ((error = copyin(SCARG(uap, buf), &ls, sizeof ls)))
  612                         return error;
  613                 linux_to_bsd_shmid_ds(&ls, &bs);
  614                 return shmctl1(l, shmid, IPC_SET, &bs);
  615 
  616         case LINUX_IPC_SET | LINUX_IPC_64:
  617                 if ((error = copyin(SCARG(uap, buf), &ls64, sizeof ls64)))
  618                         return error;
  619                 linux_to_bsd_shmid64_ds(&ls64, &bs);
  620                 return shmctl1(l, shmid, IPC_SET, &bs);
  621 
  622         case LINUX_IPC_RMID:
  623                 return shmctl1(l, shmid, IPC_RMID, NULL);
  624 
  625         case LINUX_SHM_LOCK:
  626                 return shmctl1(l, shmid, SHM_LOCK, NULL);
  627 
  628         case LINUX_SHM_UNLOCK:
  629                 return shmctl1(l, shmid, SHM_UNLOCK, NULL);
  630 
  631         case LINUX_IPC_INFO:
  632                 memset(&lsi64, 0, sizeof lsi64);
  633                 lsi64.l_shmmax = shminfo.shmmax;
  634                 lsi64.l_shmmin = shminfo.shmmin;
  635                 lsi64.l_shmmni = shminfo.shmmni;
  636                 lsi64.l_shmseg = shminfo.shmseg;
  637                 lsi64.l_shmall = shminfo.shmall;
  638                 for (i = shminfo.shmmni - 1; i > 0; i--)
  639                         if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
  640                                 break;
  641                 retval[0] = i;
  642                 return copyout(&lsi64, SCARG(uap, buf), sizeof lsi64);
  643 
  644         case LINUX_SHM_INFO:
  645                 (void)memset(&lsi, 0, sizeof lsi);
  646                 lsi.l_used_ids = shm_nused;
  647                 for (i = 0; i < shminfo.shmmni; i++)
  648                         if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
  649                                 lsi.l_shm_tot +=
  650                                     round_page(shmsegs[i].shm_segsz) /
  651                                     uvmexp.pagesize;
  652                 lsi.l_shm_rss = 0;
  653                 lsi.l_shm_swp = 0;
  654                 lsi.l_swap_attempts = 0;
  655                 lsi.l_swap_successes = 0;
  656                 for (i = shminfo.shmmni - 1; i > 0; i--)
  657                         if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
  658                                 break;
  659                 retval[0] = i;
  660                 return copyout(&lsi, SCARG(uap, buf), sizeof lsi);
  661 
  662         default:
  663 #ifdef DEBUG
  664                 printf("linux_sys_shmctl cmd %d\n", SCARG(uap, cmd));
  665 #endif
  666                 return EINVAL;
  667         }
  668 }
  669 #endif /* SYSVSHM */

Cache object: ea45774cf47e6cac46416e75cd18c40a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.