at v2.6.32 2.3 kB view raw
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}