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