ipcns_notifier.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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. #include <linux/msg.h>
  12. #include <linux/rcupdate.h>
  13. #include <linux/notifier.h>
  14. #include <linux/nsproxy.h>
  15. #include <linux/ipc_namespace.h>
  16. #include "util.h"
  17. static BLOCKING_NOTIFIER_HEAD(ipcns_chain);
  18. static int ipcns_callback(struct notifier_block *self,
  19. unsigned long action, void *arg)
  20. {
  21. struct ipc_namespace *ns;
  22. switch (action) {
  23. case IPCNS_MEMCHANGED: /* amount of lowmem has changed */
  24. /*
  25. * It's time to recompute msgmni
  26. */
  27. ns = container_of(self, struct ipc_namespace, ipcns_nb);
  28. /*
  29. * No need to get a reference on the ns: the 1st job of
  30. * free_ipc_ns() is to unregister the callback routine.
  31. * blocking_notifier_chain_unregister takes the wr lock to do
  32. * it.
  33. * When this callback routine is called the rd lock is held by
  34. * blocking_notifier_call_chain.
  35. * So the ipc ns cannot be freed while we are here.
  36. */
  37. recompute_msgmni(ns);
  38. break;
  39. default:
  40. break;
  41. }
  42. return NOTIFY_OK;
  43. }
  44. int register_ipcns_notifier(struct ipc_namespace *ns)
  45. {
  46. memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
  47. ns->ipcns_nb.notifier_call = ipcns_callback;
  48. ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
  49. return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
  50. }
  51. int unregister_ipcns_notifier(struct ipc_namespace *ns)
  52. {
  53. return blocking_notifier_chain_unregister(&ipcns_chain,
  54. &ns->ipcns_nb);
  55. }
  56. int ipcns_notify(unsigned long val)
  57. {
  58. return blocking_notifier_call_chain(&ipcns_chain, val, NULL);
  59. }