netlink.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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(short type, unsigned int id, 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, type);
  55. if (ret)
  56. goto attr_err_out;
  57. ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id);
  58. if (ret)
  59. goto attr_err_out;
  60. ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
  61. if (ret)
  62. goto attr_err_out;
  63. ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
  64. if (ret)
  65. goto attr_err_out;
  66. ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
  67. if (ret)
  68. goto attr_err_out;
  69. ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
  70. if (ret)
  71. goto attr_err_out;
  72. genlmsg_end(skb, msg_head);
  73. genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
  74. return;
  75. attr_err_out:
  76. printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
  77. err_out:
  78. kfree_skb(skb);
  79. }
  80. EXPORT_SYMBOL(quota_send_warning);
  81. static int __init quota_init(void)
  82. {
  83. if (genl_register_family(&quota_genl_family) != 0)
  84. printk(KERN_ERR
  85. "VFS: Failed to create quota netlink interface.\n");
  86. return 0;
  87. };
  88. module_init(quota_init);