ipcns_notifier.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. case IPCNS_CREATED:
  25. case IPCNS_REMOVED:
  26. /*
  27. * It's time to recompute msgmni
  28. */
  29. ns = container_of(self, struct ipc_namespace, ipcns_nb);
  30. /*
  31. * No need to get a reference on the ns: the 1st job of
  32. * free_ipc_ns() is to unregister the callback routine.
  33. * blocking_notifier_chain_unregister takes the wr lock to do
  34. * it.
  35. * When this callback routine is called the rd lock is held by
  36. * blocking_notifier_call_chain.
  37. * So the ipc ns cannot be freed while we are here.
  38. */
  39. recompute_msgmni(ns);
  40. break;
  41. default:
  42. break;
  43. }
  44. return NOTIFY_OK;
  45. }
  46. int register_ipcns_notifier(struct ipc_namespace *ns)
  47. {
  48. int rc;
  49. memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
  50. ns->ipcns_nb.notifier_call = ipcns_callback;
  51. ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
  52. rc = blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
  53. if (!rc)
  54. ns->auto_msgmni = 1;
  55. return rc;
  56. }
  57. int cond_register_ipcns_notifier(struct ipc_namespace *ns)
  58. {
  59. int rc;
  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_cond_register(&ipcns_chain,
  64. &ns->ipcns_nb);
  65. if (!rc)
  66. ns->auto_msgmni = 1;
  67. return rc;
  68. }
  69. void unregister_ipcns_notifier(struct ipc_namespace *ns)
  70. {
  71. blocking_notifier_chain_unregister(&ipcns_chain, &ns->ipcns_nb);
  72. ns->auto_msgmni = 0;
  73. }
  74. int ipcns_notify(unsigned long val)
  75. {
  76. return blocking_notifier_call_chain(&ipcns_chain, val, NULL);
  77. }