netlink.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include <linux/cred.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <linux/quotaops.h>
  6. #include <linux/sched.h>
  7. #include <linux/slab.h>
  8. #include <net/netlink.h>
  9. #include <net/genetlink.h>
  10. /* Netlink family structure for quota */
  11. static struct genl_family quota_genl_family = {
  12. .id = GENL_ID_GENERATE,
  13. .hdrsize = 0,
  14. .name = "VFS_DQUOT",
  15. .version = 1,
  16. .maxattr = QUOTA_NL_A_MAX,
  17. };
  18. /**
  19. * quota_send_warning - Send warning to userspace about exceeded quota
  20. * @type: The quota type: USRQQUOTA, GRPQUOTA,...
  21. * @id: The user or group id of the quota that was exceeded
  22. * @dev: The device on which the fs is mounted (sb->s_dev)
  23. * @warntype: The type of the warning: QUOTA_NL_...
  24. *
  25. * This can be used by filesystems (including those which don't use
  26. * dquot) to send a message to userspace relating to quota limits.
  27. *
  28. */
  29. void quota_send_warning(struct kqid qid, dev_t dev,
  30. const char warntype)
  31. {
  32. static atomic_t seq;
  33. struct sk_buff *skb;
  34. void *msg_head;
  35. int ret;
  36. int msg_size = 4 * nla_total_size(sizeof(u32)) +
  37. 2 * nla_total_size(sizeof(u64));
  38. /* We have to allocate using GFP_NOFS as we are called from a
  39. * filesystem performing write and thus further recursion into
  40. * the fs to free some data could cause deadlocks. */
  41. skb = genlmsg_new(msg_size, GFP_NOFS);
  42. if (!skb) {
  43. printk(KERN_ERR
  44. "VFS: Not enough memory to send quota warning.\n");
  45. return;
  46. }
  47. msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
  48. &quota_genl_family, 0, QUOTA_NL_C_WARNING);
  49. if (!msg_head) {
  50. printk(KERN_ERR
  51. "VFS: Cannot store netlink header in quota warning.\n");
  52. goto err_out;
  53. }
  54. ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, qid.type);
  55. if (ret)
  56. goto attr_err_out;
  57. ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID,
  58. from_kqid_munged(&init_user_ns, qid));
  59. if (ret)
  60. goto attr_err_out;
  61. ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
  62. if (ret)
  63. goto attr_err_out;
  64. ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
  65. if (ret)
  66. goto attr_err_out;
  67. ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
  68. if (ret)
  69. goto attr_err_out;
  70. ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID,
  71. from_kuid_munged(&init_user_ns, current_uid()));
  72. if (ret)
  73. goto attr_err_out;
  74. genlmsg_end(skb, msg_head);
  75. genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
  76. return;
  77. attr_err_out:
  78. printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
  79. err_out:
  80. kfree_skb(skb);
  81. }
  82. EXPORT_SYMBOL(quota_send_warning);
  83. static int __init quota_init(void)
  84. {
  85. if (genl_register_family(&quota_genl_family) != 0)
  86. printk(KERN_ERR
  87. "VFS: Failed to create quota netlink interface.\n");
  88. return 0;
  89. };
  90. module_init(quota_init);