linux/ipc/ipcns_notifier.c
<<
>>
Prefs
   1/*
   2 * linux/ipc/ipcns_notifier.c
   3 * Copyright (C) 2007 BULL SA. Nadia Derbey
   4 *
   5 * Notification mechanism for ipc namespaces:
   6 * The callback routine registered in the memory chain invokes the ipcns
   7 * notifier chain with the IPCNS_MEMCHANGED event.
   8 * Each callback routine registered in the ipcns namespace recomputes msgmni
   9 * for the owning namespace.
  10 */
  11
  12#include <linux/msg.h>
  13#include <linux/rcupdate.h>
  14#include <linux/notifier.h>
  15#include <linux/nsproxy.h>
  16#include <linux/ipc_namespace.h>
  17
  18#include "util.h"
  19
  20
  21
  22static BLOCKING_NOTIFIER_HEAD(ipcns_chain);
  23
  24
  25static int ipcns_callback(struct notifier_block *self,
  26                                unsigned long action, void *arg)
  27{
  28        struct ipc_namespace *ns;
  29
  30        switch (action) {
  31        case IPCNS_MEMCHANGED:   /* amount of lowmem has changed */
  32        case IPCNS_CREATED:
  33        case IPCNS_REMOVED:
  34                /*
  35                 * It's time to recompute msgmni
  36                 */
  37                ns = container_of(self, struct ipc_namespace, ipcns_nb);
  38                /*
  39                 * No need to get a reference on the ns: the 1st job of
  40                 * free_ipc_ns() is to unregister the callback routine.
  41                 * blocking_notifier_chain_unregister takes the wr lock to do
  42                 * it.
  43                 * When this callback routine is called the rd lock is held by
  44                 * blocking_notifier_call_chain.
  45                 * So the ipc ns cannot be freed while we are here.
  46                 */
  47                recompute_msgmni(ns);
  48                break;
  49        default:
  50                break;
  51        }
  52
  53        return NOTIFY_OK;
  54}
  55
  56int register_ipcns_notifier(struct ipc_namespace *ns)
  57{
  58        int rc;
  59
  60        memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
  61        ns->ipcns_nb.notifier_call = ipcns_callback;
  62        ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
  63        rc = blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
  64        if (!rc)
  65                ns->auto_msgmni = 1;
  66        return rc;
  67}
  68
  69int cond_register_ipcns_notifier(struct ipc_namespace *ns)
  70{
  71        int rc;
  72
  73        memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
  74        ns->ipcns_nb.notifier_call = ipcns_callback;
  75        ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
  76        rc = blocking_notifier_chain_cond_register(&ipcns_chain,
  77                                                        &ns->ipcns_nb);
  78        if (!rc)
  79                ns->auto_msgmni = 1;
  80        return rc;
  81}
  82
  83void unregister_ipcns_notifier(struct ipc_namespace *ns)
  84{
  85        blocking_notifier_chain_unregister(&ipcns_chain, &ns->ipcns_nb);
  86        ns->auto_msgmni = 0;
  87}
  88
  89int ipcns_notify(unsigned long val)
  90{
  91        return blocking_notifier_call_chain(&ipcns_chain, val, NULL);
  92}
  93