aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/quota/Makefile1
-rw-r--r--fs/quota/netlink.c95
-rw-r--r--fs/quota/quota.c93
3 files changed, 96 insertions, 93 deletions
diff --git a/fs/quota/Makefile b/fs/quota/Makefile
index 68d4f6dc0578..dcba20445ccb 100644
--- a/fs/quota/Makefile
+++ b/fs/quota/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_QFMT_V1) += quota_v1.o
3obj-$(CONFIG_QFMT_V2) += quota_v2.o 3obj-$(CONFIG_QFMT_V2) += quota_v2.o
4obj-$(CONFIG_QUOTA_TREE) += quota_tree.o 4obj-$(CONFIG_QUOTA_TREE) += quota_tree.o
5obj-$(CONFIG_QUOTACTL) += quota.o 5obj-$(CONFIG_QUOTACTL) += quota.o
6obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
new file mode 100644
index 000000000000..2663ed90fb03
--- /dev/null
+++ b/fs/quota/netlink.c
@@ -0,0 +1,95 @@
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 <net/netlink.h>
9#include <net/genetlink.h>
10
11/* Netlink family structure for quota */
12static struct genl_family quota_genl_family = {
13 .id = GENL_ID_GENERATE,
14 .hdrsize = 0,
15 .name = "VFS_DQUOT",
16 .version = 1,
17 .maxattr = QUOTA_NL_A_MAX,
18};
19
20/**
21 * quota_send_warning - Send warning to userspace about exceeded quota
22 * @type: The quota type: USRQQUOTA, GRPQUOTA,...
23 * @id: The user or group id of the quota that was exceeded
24 * @dev: The device on which the fs is mounted (sb->s_dev)
25 * @warntype: The type of the warning: QUOTA_NL_...
26 *
27 * This can be used by filesystems (including those which don't use
28 * dquot) to send a message to userspace relating to quota limits.
29 *
30 */
31
32void quota_send_warning(short type, unsigned int id, dev_t dev,
33 const char warntype)
34{
35 static atomic_t seq;
36 struct sk_buff *skb;
37 void *msg_head;
38 int ret;
39 int msg_size = 4 * nla_total_size(sizeof(u32)) +
40 2 * nla_total_size(sizeof(u64));
41
42 /* We have to allocate using GFP_NOFS as we are called from a
43 * filesystem performing write and thus further recursion into
44 * the fs to free some data could cause deadlocks. */
45 skb = genlmsg_new(msg_size, GFP_NOFS);
46 if (!skb) {
47 printk(KERN_ERR
48 "VFS: Not enough memory to send quota warning.\n");
49 return;
50 }
51 msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
52 &quota_genl_family, 0, QUOTA_NL_C_WARNING);
53 if (!msg_head) {
54 printk(KERN_ERR
55 "VFS: Cannot store netlink header in quota warning.\n");
56 goto err_out;
57 }
58 ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type);
59 if (ret)
60 goto attr_err_out;
61 ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id);
62 if (ret)
63 goto attr_err_out;
64 ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
65 if (ret)
66 goto attr_err_out;
67 ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
68 if (ret)
69 goto attr_err_out;
70 ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
71 if (ret)
72 goto attr_err_out;
73 ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
74 if (ret)
75 goto attr_err_out;
76 genlmsg_end(skb, msg_head);
77
78 genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
79 return;
80attr_err_out:
81 printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
82err_out:
83 kfree_skb(skb);
84}
85EXPORT_SYMBOL(quota_send_warning);
86
87static int __init quota_init(void)
88{
89 if (genl_register_family(&quota_genl_family) != 0)
90 printk(KERN_ERR
91 "VFS: Failed to create quota netlink interface.\n");
92 return 0;
93};
94
95module_init(quota_init);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index a43bb2c3ceaf..4506c6596347 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -19,8 +19,6 @@
19#include <linux/quotaops.h> 19#include <linux/quotaops.h>
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/writeback.h> 21#include <linux/writeback.h>
22#include <net/netlink.h>
23#include <net/genetlink.h>
24 22
25static int check_quotactl_permission(struct super_block *sb, int type, int cmd, 23static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
26 qid_t id) 24 qid_t id)
@@ -458,94 +456,3 @@ asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
458 return ret; 456 return ret;
459} 457}
460#endif 458#endif
461
462
463#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
464
465/* Netlink family structure for quota */
466static struct genl_family quota_genl_family = {
467 .id = GENL_ID_GENERATE,
468 .hdrsize = 0,
469 .name = "VFS_DQUOT",
470 .version = 1,
471 .maxattr = QUOTA_NL_A_MAX,
472};
473
474/**
475 * quota_send_warning - Send warning to userspace about exceeded quota
476 * @type: The quota type: USRQQUOTA, GRPQUOTA,...
477 * @id: The user or group id of the quota that was exceeded
478 * @dev: The device on which the fs is mounted (sb->s_dev)
479 * @warntype: The type of the warning: QUOTA_NL_...
480 *
481 * This can be used by filesystems (including those which don't use
482 * dquot) to send a message to userspace relating to quota limits.
483 *
484 */
485
486void quota_send_warning(short type, unsigned int id, dev_t dev,
487 const char warntype)
488{
489 static atomic_t seq;
490 struct sk_buff *skb;
491 void *msg_head;
492 int ret;
493 int msg_size = 4 * nla_total_size(sizeof(u32)) +
494 2 * nla_total_size(sizeof(u64));
495
496 /* We have to allocate using GFP_NOFS as we are called from a
497 * filesystem performing write and thus further recursion into
498 * the fs to free some data could cause deadlocks. */
499 skb = genlmsg_new(msg_size, GFP_NOFS);
500 if (!skb) {
501 printk(KERN_ERR
502 "VFS: Not enough memory to send quota warning.\n");
503 return;
504 }
505 msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
506 &quota_genl_family, 0, QUOTA_NL_C_WARNING);
507 if (!msg_head) {
508 printk(KERN_ERR
509 "VFS: Cannot store netlink header in quota warning.\n");
510 goto err_out;
511 }
512 ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type);
513 if (ret)
514 goto attr_err_out;
515 ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id);
516 if (ret)
517 goto attr_err_out;
518 ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
519 if (ret)
520 goto attr_err_out;
521 ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
522 if (ret)
523 goto attr_err_out;
524 ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
525 if (ret)
526 goto attr_err_out;
527 ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
528 if (ret)
529 goto attr_err_out;
530 genlmsg_end(skb, msg_head);
531
532 genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
533 return;
534attr_err_out:
535 printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
536err_out:
537 kfree_skb(skb);
538}
539EXPORT_SYMBOL(quota_send_warning);
540
541static int __init quota_init(void)
542{
543 if (genl_register_family(&quota_genl_family) != 0)
544 printk(KERN_ERR
545 "VFS: Failed to create quota netlink interface.\n");
546 return 0;
547};
548
549module_init(quota_init);
550#endif
551