xref: /openbmc/linux/fs/quota/quota.c (revision 6ae09575b3c951ad77c07d068b8dbbc09031b2d1)
1884d179dSJan Kara /*
2884d179dSJan Kara  * Quota code necessary even when VFS quota support is not compiled
3884d179dSJan Kara  * into the kernel.  The interesting stuff is over in dquot.c, here
4884d179dSJan Kara  * we have symbols for initial quotactl(2) handling, the sysctl(2)
5884d179dSJan Kara  * variables, etc - things needed even when quota support disabled.
6884d179dSJan Kara  */
7884d179dSJan Kara 
8884d179dSJan Kara #include <linux/fs.h>
9884d179dSJan Kara #include <linux/namei.h>
10884d179dSJan Kara #include <linux/slab.h>
11884d179dSJan Kara #include <asm/current.h>
12884d179dSJan Kara #include <asm/uaccess.h>
13884d179dSJan Kara #include <linux/compat.h>
14884d179dSJan Kara #include <linux/kernel.h>
15884d179dSJan Kara #include <linux/security.h>
16884d179dSJan Kara #include <linux/syscalls.h>
17884d179dSJan Kara #include <linux/buffer_head.h>
18884d179dSJan Kara #include <linux/capability.h>
19884d179dSJan Kara #include <linux/quotaops.h>
20884d179dSJan Kara #include <linux/types.h>
2186e931a3SSteven Whitehouse #include <net/netlink.h>
2286e931a3SSteven Whitehouse #include <net/genetlink.h>
23884d179dSJan Kara 
24884d179dSJan Kara /* Check validity of generic quotactl commands */
25268157baSJan Kara static int generic_quotactl_valid(struct super_block *sb, int type, int cmd,
26268157baSJan Kara 				  qid_t id)
27884d179dSJan Kara {
28884d179dSJan Kara 	if (type >= MAXQUOTAS)
29884d179dSJan Kara 		return -EINVAL;
30884d179dSJan Kara 	if (!sb && cmd != Q_SYNC)
31884d179dSJan Kara 		return -ENODEV;
32884d179dSJan Kara 	/* Is operation supported? */
33884d179dSJan Kara 	if (sb && !sb->s_qcop)
34884d179dSJan Kara 		return -ENOSYS;
35884d179dSJan Kara 
36884d179dSJan Kara 	/* Check privileges */
37884d179dSJan Kara 	if (cmd == Q_GETQUOTA) {
38884d179dSJan Kara 		if (((type == USRQUOTA && current_euid() != id) ||
39884d179dSJan Kara 		     (type == GRPQUOTA && !in_egroup_p(id))) &&
40884d179dSJan Kara 		    !capable(CAP_SYS_ADMIN))
41884d179dSJan Kara 			return -EPERM;
42884d179dSJan Kara 	}
43884d179dSJan Kara 	else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
44884d179dSJan Kara 		if (!capable(CAP_SYS_ADMIN))
45884d179dSJan Kara 			return -EPERM;
46884d179dSJan Kara 
47884d179dSJan Kara 	return 0;
48884d179dSJan Kara }
49884d179dSJan Kara 
50884d179dSJan Kara /* Check validity of XFS Quota Manager commands */
51268157baSJan Kara static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd,
52268157baSJan Kara 			      qid_t id)
53884d179dSJan Kara {
54884d179dSJan Kara 	if (type >= XQM_MAXQUOTAS)
55884d179dSJan Kara 		return -EINVAL;
56884d179dSJan Kara 	if (!sb)
57884d179dSJan Kara 		return -ENODEV;
58884d179dSJan Kara 	if (!sb->s_qcop)
59884d179dSJan Kara 		return -ENOSYS;
60884d179dSJan Kara 
61884d179dSJan Kara 	/* Check privileges */
62884d179dSJan Kara 	if (cmd == Q_XGETQUOTA) {
63884d179dSJan Kara 		if (((type == XQM_USRQUOTA && current_euid() != id) ||
64884d179dSJan Kara 		     (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
65884d179dSJan Kara 		     !capable(CAP_SYS_ADMIN))
66884d179dSJan Kara 			return -EPERM;
67884d179dSJan Kara 	} else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) {
68884d179dSJan Kara 		if (!capable(CAP_SYS_ADMIN))
69884d179dSJan Kara 			return -EPERM;
70884d179dSJan Kara 	}
71884d179dSJan Kara 
72884d179dSJan Kara 	return 0;
73884d179dSJan Kara }
74884d179dSJan Kara 
75268157baSJan Kara static int check_quotactl_valid(struct super_block *sb, int type, int cmd,
76268157baSJan Kara 				qid_t id)
77884d179dSJan Kara {
78884d179dSJan Kara 	int error;
79884d179dSJan Kara 
80884d179dSJan Kara 	if (XQM_COMMAND(cmd))
81884d179dSJan Kara 		error = xqm_quotactl_valid(sb, type, cmd, id);
82884d179dSJan Kara 	else
83884d179dSJan Kara 		error = generic_quotactl_valid(sb, type, cmd, id);
84884d179dSJan Kara 	if (!error)
85884d179dSJan Kara 		error = security_quotactl(cmd, type, id, sb);
86884d179dSJan Kara 	return error;
87884d179dSJan Kara }
88884d179dSJan Kara 
89850b201bSChristoph Hellwig #ifdef CONFIG_QUOTA
90850b201bSChristoph Hellwig void sync_quota_sb(struct super_block *sb, int type)
91884d179dSJan Kara {
92884d179dSJan Kara 	int cnt;
93884d179dSJan Kara 
94850b201bSChristoph Hellwig 	if (!sb->s_qcop->quota_sync)
95850b201bSChristoph Hellwig 		return;
96850b201bSChristoph Hellwig 
97884d179dSJan Kara 	sb->s_qcop->quota_sync(sb, type);
98884d179dSJan Kara 
99884d179dSJan Kara 	if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
100884d179dSJan Kara 		return;
101884d179dSJan Kara 	/* This is not very clever (and fast) but currently I don't know about
102884d179dSJan Kara 	 * any other simple way of getting quota data to disk and we must get
103884d179dSJan Kara 	 * them there for userspace to be visible... */
104884d179dSJan Kara 	if (sb->s_op->sync_fs)
105884d179dSJan Kara 		sb->s_op->sync_fs(sb, 1);
106884d179dSJan Kara 	sync_blockdev(sb->s_bdev);
107884d179dSJan Kara 
108884d179dSJan Kara 	/*
109884d179dSJan Kara 	 * Now when everything is written we can discard the pagecache so
110884d179dSJan Kara 	 * that userspace sees the changes.
111884d179dSJan Kara 	 */
112884d179dSJan Kara 	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
113884d179dSJan Kara 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
114884d179dSJan Kara 		if (type != -1 && cnt != type)
115884d179dSJan Kara 			continue;
116884d179dSJan Kara 		if (!sb_has_quota_active(sb, cnt))
117884d179dSJan Kara 			continue;
118268157baSJan Kara 		mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
119268157baSJan Kara 				  I_MUTEX_QUOTA);
120884d179dSJan Kara 		truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
121884d179dSJan Kara 		mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
122884d179dSJan Kara 	}
123884d179dSJan Kara 	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
124884d179dSJan Kara }
125850b201bSChristoph Hellwig #endif
126884d179dSJan Kara 
127*6ae09575SChristoph Hellwig static int quota_sync_all(int type)
128884d179dSJan Kara {
129850b201bSChristoph Hellwig 	struct super_block *sb;
130884d179dSJan Kara 	int cnt;
131*6ae09575SChristoph Hellwig 	int ret;
132*6ae09575SChristoph Hellwig 
133*6ae09575SChristoph Hellwig 	if (type >= MAXQUOTAS)
134*6ae09575SChristoph Hellwig 		return -EINVAL;
135*6ae09575SChristoph Hellwig 	ret = security_quotactl(Q_SYNC, type, 0, NULL);
136*6ae09575SChristoph Hellwig 	if (ret)
137*6ae09575SChristoph Hellwig 		return ret;
138884d179dSJan Kara 
139884d179dSJan Kara 	spin_lock(&sb_lock);
140884d179dSJan Kara restart:
141884d179dSJan Kara 	list_for_each_entry(sb, &super_blocks, s_list) {
142268157baSJan Kara 		/* This test just improves performance so it needn't be
143268157baSJan Kara 		 * reliable... */
144884d179dSJan Kara 		for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
145884d179dSJan Kara 			if (type != -1 && type != cnt)
146884d179dSJan Kara 				continue;
147884d179dSJan Kara 			if (!sb_has_quota_active(sb, cnt))
148884d179dSJan Kara 				continue;
149884d179dSJan Kara 			if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
150884d179dSJan Kara 			   list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
151884d179dSJan Kara 				continue;
152884d179dSJan Kara 			break;
153884d179dSJan Kara 		}
154884d179dSJan Kara 		if (cnt == MAXQUOTAS)
155884d179dSJan Kara 			continue;
156884d179dSJan Kara 		sb->s_count++;
157884d179dSJan Kara 		spin_unlock(&sb_lock);
158884d179dSJan Kara 		down_read(&sb->s_umount);
159850b201bSChristoph Hellwig 		if (sb->s_root)
160850b201bSChristoph Hellwig 			sync_quota_sb(sb, type);
161884d179dSJan Kara 		up_read(&sb->s_umount);
162884d179dSJan Kara 		spin_lock(&sb_lock);
163884d179dSJan Kara 		if (__put_super_and_need_restart(sb))
164884d179dSJan Kara 			goto restart;
165884d179dSJan Kara 	}
166884d179dSJan Kara 	spin_unlock(&sb_lock);
167*6ae09575SChristoph Hellwig 
168*6ae09575SChristoph Hellwig 	return 0;
169884d179dSJan Kara }
170884d179dSJan Kara 
171c411e5f6SChristoph Hellwig static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
172268157baSJan Kara 		         void __user *addr)
173884d179dSJan Kara {
174884d179dSJan Kara 	char *pathname;
175f450d4feSChristoph Hellwig 	int ret = -ENOSYS;
176884d179dSJan Kara 
177268157baSJan Kara 	pathname = getname(addr);
178268157baSJan Kara 	if (IS_ERR(pathname))
179884d179dSJan Kara 		return PTR_ERR(pathname);
180f450d4feSChristoph Hellwig 	if (sb->s_qcop->quota_on)
181884d179dSJan Kara 		ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0);
182884d179dSJan Kara 	putname(pathname);
183884d179dSJan Kara 	return ret;
184884d179dSJan Kara }
185884d179dSJan Kara 
186c411e5f6SChristoph Hellwig static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
187c411e5f6SChristoph Hellwig {
188884d179dSJan Kara 	__u32 fmt;
189884d179dSJan Kara 
190884d179dSJan Kara 	down_read(&sb_dqopt(sb)->dqptr_sem);
191884d179dSJan Kara 	if (!sb_has_quota_active(sb, type)) {
192884d179dSJan Kara 		up_read(&sb_dqopt(sb)->dqptr_sem);
193884d179dSJan Kara 		return -ESRCH;
194884d179dSJan Kara 	}
195884d179dSJan Kara 	fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
196884d179dSJan Kara 	up_read(&sb_dqopt(sb)->dqptr_sem);
197884d179dSJan Kara 	if (copy_to_user(addr, &fmt, sizeof(fmt)))
198884d179dSJan Kara 		return -EFAULT;
199884d179dSJan Kara 	return 0;
200884d179dSJan Kara }
201c411e5f6SChristoph Hellwig 
202c411e5f6SChristoph Hellwig static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
203c411e5f6SChristoph Hellwig {
204884d179dSJan Kara 	struct if_dqinfo info;
205c411e5f6SChristoph Hellwig 	int ret;
206884d179dSJan Kara 
207f450d4feSChristoph Hellwig 	if (!sb_has_quota_active(sb, type))
208f450d4feSChristoph Hellwig 		return -ESRCH;
209f450d4feSChristoph Hellwig 	if (!sb->s_qcop->get_info)
210f450d4feSChristoph Hellwig 		return -ENOSYS;
211268157baSJan Kara 	ret = sb->s_qcop->get_info(sb, type, &info);
212c411e5f6SChristoph Hellwig 	if (!ret && copy_to_user(addr, &info, sizeof(info)))
213884d179dSJan Kara 		return -EFAULT;
214c411e5f6SChristoph Hellwig 	return ret;
215884d179dSJan Kara }
216c411e5f6SChristoph Hellwig 
217c411e5f6SChristoph Hellwig static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
218c411e5f6SChristoph Hellwig {
219884d179dSJan Kara 	struct if_dqinfo info;
220884d179dSJan Kara 
221884d179dSJan Kara 	if (copy_from_user(&info, addr, sizeof(info)))
222884d179dSJan Kara 		return -EFAULT;
223f450d4feSChristoph Hellwig 	if (!sb_has_quota_active(sb, type))
224f450d4feSChristoph Hellwig 		return -ESRCH;
225f450d4feSChristoph Hellwig 	if (!sb->s_qcop->set_info)
226f450d4feSChristoph Hellwig 		return -ENOSYS;
227884d179dSJan Kara 	return sb->s_qcop->set_info(sb, type, &info);
228884d179dSJan Kara }
229c411e5f6SChristoph Hellwig 
230c411e5f6SChristoph Hellwig static int quota_getquota(struct super_block *sb, int type, qid_t id,
231c411e5f6SChristoph Hellwig 			  void __user *addr)
232c411e5f6SChristoph Hellwig {
233884d179dSJan Kara 	struct if_dqblk idq;
234c411e5f6SChristoph Hellwig 	int ret;
235884d179dSJan Kara 
236f450d4feSChristoph Hellwig 	if (!sb_has_quota_active(sb, type))
237f450d4feSChristoph Hellwig 		return -ESRCH;
238f450d4feSChristoph Hellwig 	if (!sb->s_qcop->get_dqblk)
239f450d4feSChristoph Hellwig 		return -ENOSYS;
240268157baSJan Kara 	ret = sb->s_qcop->get_dqblk(sb, type, id, &idq);
241268157baSJan Kara 	if (ret)
242884d179dSJan Kara 		return ret;
243884d179dSJan Kara 	if (copy_to_user(addr, &idq, sizeof(idq)))
244884d179dSJan Kara 		return -EFAULT;
245884d179dSJan Kara 	return 0;
246884d179dSJan Kara }
247c411e5f6SChristoph Hellwig 
248c411e5f6SChristoph Hellwig static int quota_setquota(struct super_block *sb, int type, qid_t id,
249c411e5f6SChristoph Hellwig 			  void __user *addr)
250c411e5f6SChristoph Hellwig {
251884d179dSJan Kara 	struct if_dqblk idq;
252884d179dSJan Kara 
253884d179dSJan Kara 	if (copy_from_user(&idq, addr, sizeof(idq)))
254884d179dSJan Kara 		return -EFAULT;
255f450d4feSChristoph Hellwig 	if (!sb_has_quota_active(sb, type))
256f450d4feSChristoph Hellwig 		return -ESRCH;
257f450d4feSChristoph Hellwig 	if (!sb->s_qcop->set_dqblk)
258f450d4feSChristoph Hellwig 		return -ENOSYS;
259884d179dSJan Kara 	return sb->s_qcop->set_dqblk(sb, type, id, &idq);
260884d179dSJan Kara }
261884d179dSJan Kara 
262c411e5f6SChristoph Hellwig static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
263c411e5f6SChristoph Hellwig {
264884d179dSJan Kara 	__u32 flags;
265884d179dSJan Kara 
266884d179dSJan Kara 	if (copy_from_user(&flags, addr, sizeof(flags)))
267884d179dSJan Kara 		return -EFAULT;
268f450d4feSChristoph Hellwig 	if (!sb->s_qcop->set_xstate)
269f450d4feSChristoph Hellwig 		return -ENOSYS;
270884d179dSJan Kara 	return sb->s_qcop->set_xstate(sb, flags, cmd);
271884d179dSJan Kara }
272884d179dSJan Kara 
273c411e5f6SChristoph Hellwig static int quota_getxstate(struct super_block *sb, void __user *addr)
274c411e5f6SChristoph Hellwig {
275c411e5f6SChristoph Hellwig 	struct fs_quota_stat fqs;
276c411e5f6SChristoph Hellwig 	int ret;
277c411e5f6SChristoph Hellwig 
278f450d4feSChristoph Hellwig 	if (!sb->s_qcop->get_xstate)
279f450d4feSChristoph Hellwig 		return -ENOSYS;
280c411e5f6SChristoph Hellwig 	ret = sb->s_qcop->get_xstate(sb, &fqs);
281c411e5f6SChristoph Hellwig 	if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
282884d179dSJan Kara 		return -EFAULT;
283c411e5f6SChristoph Hellwig 	return ret;
284884d179dSJan Kara }
285c411e5f6SChristoph Hellwig 
286c411e5f6SChristoph Hellwig static int quota_setxquota(struct super_block *sb, int type, qid_t id,
287c411e5f6SChristoph Hellwig 			   void __user *addr)
288c411e5f6SChristoph Hellwig {
289884d179dSJan Kara 	struct fs_disk_quota fdq;
290884d179dSJan Kara 
291884d179dSJan Kara 	if (copy_from_user(&fdq, addr, sizeof(fdq)))
292884d179dSJan Kara 		return -EFAULT;
293f450d4feSChristoph Hellwig 	if (!sb->s_qcop->set_xquota)
294f450d4feSChristoph Hellwig 		return -ENOSYS;
295884d179dSJan Kara 	return sb->s_qcop->set_xquota(sb, type, id, &fdq);
296884d179dSJan Kara }
297c411e5f6SChristoph Hellwig 
298c411e5f6SChristoph Hellwig static int quota_getxquota(struct super_block *sb, int type, qid_t id,
299c411e5f6SChristoph Hellwig 			   void __user *addr)
300c411e5f6SChristoph Hellwig {
301884d179dSJan Kara 	struct fs_disk_quota fdq;
302c411e5f6SChristoph Hellwig 	int ret;
303884d179dSJan Kara 
304f450d4feSChristoph Hellwig 	if (!sb->s_qcop->get_xquota)
305f450d4feSChristoph Hellwig 		return -ENOSYS;
306268157baSJan Kara 	ret = sb->s_qcop->get_xquota(sb, type, id, &fdq);
307c411e5f6SChristoph Hellwig 	if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
308884d179dSJan Kara 		return -EFAULT;
309c411e5f6SChristoph Hellwig 	return ret;
310884d179dSJan Kara }
311c411e5f6SChristoph Hellwig 
312c411e5f6SChristoph Hellwig /* Copy parameters and call proper function */
313c411e5f6SChristoph Hellwig static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
314c411e5f6SChristoph Hellwig 		       void __user *addr)
315c411e5f6SChristoph Hellwig {
316c411e5f6SChristoph Hellwig 	switch (cmd) {
317c411e5f6SChristoph Hellwig 	case Q_QUOTAON:
318c411e5f6SChristoph Hellwig 		return quota_quotaon(sb, type, cmd, id, addr);
319c411e5f6SChristoph Hellwig 	case Q_QUOTAOFF:
320f450d4feSChristoph Hellwig 		if (!sb->s_qcop->quota_off)
321f450d4feSChristoph Hellwig 			return -ENOSYS;
322c411e5f6SChristoph Hellwig 		return sb->s_qcop->quota_off(sb, type, 0);
323c411e5f6SChristoph Hellwig 	case Q_GETFMT:
324c411e5f6SChristoph Hellwig 		return quota_getfmt(sb, type, addr);
325c411e5f6SChristoph Hellwig 	case Q_GETINFO:
326c411e5f6SChristoph Hellwig 		return quota_getinfo(sb, type, addr);
327c411e5f6SChristoph Hellwig 	case Q_SETINFO:
328c411e5f6SChristoph Hellwig 		return quota_setinfo(sb, type, addr);
329c411e5f6SChristoph Hellwig 	case Q_GETQUOTA:
330c411e5f6SChristoph Hellwig 		return quota_getquota(sb, type, id, addr);
331c411e5f6SChristoph Hellwig 	case Q_SETQUOTA:
332c411e5f6SChristoph Hellwig 		return quota_setquota(sb, type, id, addr);
333c411e5f6SChristoph Hellwig 	case Q_SYNC:
334f450d4feSChristoph Hellwig 		if (!sb->s_qcop->quota_sync)
335f450d4feSChristoph Hellwig 			return -ENOSYS;
336c411e5f6SChristoph Hellwig 		sync_quota_sb(sb, type);
337c411e5f6SChristoph Hellwig 		return 0;
338c411e5f6SChristoph Hellwig 	case Q_XQUOTAON:
339c411e5f6SChristoph Hellwig 	case Q_XQUOTAOFF:
340c411e5f6SChristoph Hellwig 	case Q_XQUOTARM:
341c411e5f6SChristoph Hellwig 		return quota_setxstate(sb, cmd, addr);
342c411e5f6SChristoph Hellwig 	case Q_XGETQSTAT:
343c411e5f6SChristoph Hellwig 		return quota_getxstate(sb, addr);
344c411e5f6SChristoph Hellwig 	case Q_XSETQLIM:
345c411e5f6SChristoph Hellwig 		return quota_setxquota(sb, type, id, addr);
346c411e5f6SChristoph Hellwig 	case Q_XGETQUOTA:
347c411e5f6SChristoph Hellwig 		return quota_getxquota(sb, type, id, addr);
348884d179dSJan Kara 	case Q_XQUOTASYNC:
349f450d4feSChristoph Hellwig 		if (!sb->s_qcop->quota_sync)
350f450d4feSChristoph Hellwig 			return -ENOSYS;
351884d179dSJan Kara 		return sb->s_qcop->quota_sync(sb, type);
352884d179dSJan Kara 	default:
353f450d4feSChristoph Hellwig 		return -EINVAL;
354884d179dSJan Kara 	}
355884d179dSJan Kara }
356884d179dSJan Kara 
357884d179dSJan Kara /*
358884d179dSJan Kara  * look up a superblock on which quota ops will be performed
359884d179dSJan Kara  * - use the name of a block device to find the superblock thereon
360884d179dSJan Kara  */
3617a2435d8SJan Kara static struct super_block *quotactl_block(const char __user *special)
362884d179dSJan Kara {
363884d179dSJan Kara #ifdef CONFIG_BLOCK
364884d179dSJan Kara 	struct block_device *bdev;
365884d179dSJan Kara 	struct super_block *sb;
366884d179dSJan Kara 	char *tmp = getname(special);
367884d179dSJan Kara 
368884d179dSJan Kara 	if (IS_ERR(tmp))
369884d179dSJan Kara 		return ERR_CAST(tmp);
370884d179dSJan Kara 	bdev = lookup_bdev(tmp);
371884d179dSJan Kara 	putname(tmp);
372884d179dSJan Kara 	if (IS_ERR(bdev))
373884d179dSJan Kara 		return ERR_CAST(bdev);
374884d179dSJan Kara 	sb = get_super(bdev);
375884d179dSJan Kara 	bdput(bdev);
376884d179dSJan Kara 	if (!sb)
377884d179dSJan Kara 		return ERR_PTR(-ENODEV);
378884d179dSJan Kara 
379884d179dSJan Kara 	return sb;
380884d179dSJan Kara #else
381884d179dSJan Kara 	return ERR_PTR(-ENODEV);
382884d179dSJan Kara #endif
383884d179dSJan Kara }
384884d179dSJan Kara 
385884d179dSJan Kara /*
386884d179dSJan Kara  * This is the system call interface. This communicates with
387884d179dSJan Kara  * the user-level programs. Currently this only supports diskquota
388884d179dSJan Kara  * calls. Maybe we need to add the process quotas etc. in the future,
389884d179dSJan Kara  * but we probably should use rlimits for that.
390884d179dSJan Kara  */
391884d179dSJan Kara SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
392884d179dSJan Kara 		qid_t, id, void __user *, addr)
393884d179dSJan Kara {
394884d179dSJan Kara 	uint cmds, type;
395884d179dSJan Kara 	struct super_block *sb = NULL;
396884d179dSJan Kara 	int ret;
397884d179dSJan Kara 
398884d179dSJan Kara 	cmds = cmd >> SUBCMDSHIFT;
399884d179dSJan Kara 	type = cmd & SUBCMDMASK;
400884d179dSJan Kara 
401*6ae09575SChristoph Hellwig 	/*
402*6ae09575SChristoph Hellwig 	 * As a special case Q_SYNC can be called without a specific device.
403*6ae09575SChristoph Hellwig 	 * It will iterate all superblocks that have quota enabled and call
404*6ae09575SChristoph Hellwig 	 * the sync action on each of them.
405*6ae09575SChristoph Hellwig 	 */
406*6ae09575SChristoph Hellwig 	if (!special) {
407*6ae09575SChristoph Hellwig 		if (cmds == Q_SYNC)
408*6ae09575SChristoph Hellwig 			return quota_sync_all(type);
409*6ae09575SChristoph Hellwig 		return -ENODEV;
410*6ae09575SChristoph Hellwig 	}
411*6ae09575SChristoph Hellwig 
412884d179dSJan Kara 	sb = quotactl_block(special);
413884d179dSJan Kara 	if (IS_ERR(sb))
414884d179dSJan Kara 		return PTR_ERR(sb);
415884d179dSJan Kara 
416884d179dSJan Kara 	ret = check_quotactl_valid(sb, type, cmds, id);
417884d179dSJan Kara 	if (ret >= 0)
418884d179dSJan Kara 		ret = do_quotactl(sb, type, cmds, id, addr);
419884d179dSJan Kara 
420*6ae09575SChristoph Hellwig 	drop_super(sb);
421884d179dSJan Kara 	return ret;
422884d179dSJan Kara }
423884d179dSJan Kara 
424884d179dSJan Kara #if defined(CONFIG_COMPAT_FOR_U64_ALIGNMENT)
425884d179dSJan Kara /*
426884d179dSJan Kara  * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
427884d179dSJan Kara  * and is necessary due to alignment problems.
428884d179dSJan Kara  */
429884d179dSJan Kara struct compat_if_dqblk {
430884d179dSJan Kara 	compat_u64 dqb_bhardlimit;
431884d179dSJan Kara 	compat_u64 dqb_bsoftlimit;
432884d179dSJan Kara 	compat_u64 dqb_curspace;
433884d179dSJan Kara 	compat_u64 dqb_ihardlimit;
434884d179dSJan Kara 	compat_u64 dqb_isoftlimit;
435884d179dSJan Kara 	compat_u64 dqb_curinodes;
436884d179dSJan Kara 	compat_u64 dqb_btime;
437884d179dSJan Kara 	compat_u64 dqb_itime;
438884d179dSJan Kara 	compat_uint_t dqb_valid;
439884d179dSJan Kara };
440884d179dSJan Kara 
441884d179dSJan Kara /* XFS structures */
442884d179dSJan Kara struct compat_fs_qfilestat {
443884d179dSJan Kara 	compat_u64 dqb_bhardlimit;
444884d179dSJan Kara 	compat_u64 qfs_nblks;
445884d179dSJan Kara 	compat_uint_t qfs_nextents;
446884d179dSJan Kara };
447884d179dSJan Kara 
448884d179dSJan Kara struct compat_fs_quota_stat {
449884d179dSJan Kara 	__s8		qs_version;
450884d179dSJan Kara 	__u16		qs_flags;
451884d179dSJan Kara 	__s8		qs_pad;
452884d179dSJan Kara 	struct compat_fs_qfilestat	qs_uquota;
453884d179dSJan Kara 	struct compat_fs_qfilestat	qs_gquota;
454884d179dSJan Kara 	compat_uint_t	qs_incoredqs;
455884d179dSJan Kara 	compat_int_t	qs_btimelimit;
456884d179dSJan Kara 	compat_int_t	qs_itimelimit;
457884d179dSJan Kara 	compat_int_t	qs_rtbtimelimit;
458884d179dSJan Kara 	__u16		qs_bwarnlimit;
459884d179dSJan Kara 	__u16		qs_iwarnlimit;
460884d179dSJan Kara };
461884d179dSJan Kara 
462884d179dSJan Kara asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
463884d179dSJan Kara 						qid_t id, void __user *addr)
464884d179dSJan Kara {
465884d179dSJan Kara 	unsigned int cmds;
466884d179dSJan Kara 	struct if_dqblk __user *dqblk;
467884d179dSJan Kara 	struct compat_if_dqblk __user *compat_dqblk;
468884d179dSJan Kara 	struct fs_quota_stat __user *fsqstat;
469884d179dSJan Kara 	struct compat_fs_quota_stat __user *compat_fsqstat;
470884d179dSJan Kara 	compat_uint_t data;
471884d179dSJan Kara 	u16 xdata;
472884d179dSJan Kara 	long ret;
473884d179dSJan Kara 
474884d179dSJan Kara 	cmds = cmd >> SUBCMDSHIFT;
475884d179dSJan Kara 
476884d179dSJan Kara 	switch (cmds) {
477884d179dSJan Kara 	case Q_GETQUOTA:
478884d179dSJan Kara 		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
479884d179dSJan Kara 		compat_dqblk = addr;
480884d179dSJan Kara 		ret = sys_quotactl(cmd, special, id, dqblk);
481884d179dSJan Kara 		if (ret)
482884d179dSJan Kara 			break;
483884d179dSJan Kara 		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
484884d179dSJan Kara 			get_user(data, &dqblk->dqb_valid) ||
485884d179dSJan Kara 			put_user(data, &compat_dqblk->dqb_valid))
486884d179dSJan Kara 			ret = -EFAULT;
487884d179dSJan Kara 		break;
488884d179dSJan Kara 	case Q_SETQUOTA:
489884d179dSJan Kara 		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
490884d179dSJan Kara 		compat_dqblk = addr;
491884d179dSJan Kara 		ret = -EFAULT;
492884d179dSJan Kara 		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
493884d179dSJan Kara 			get_user(data, &compat_dqblk->dqb_valid) ||
494884d179dSJan Kara 			put_user(data, &dqblk->dqb_valid))
495884d179dSJan Kara 			break;
496884d179dSJan Kara 		ret = sys_quotactl(cmd, special, id, dqblk);
497884d179dSJan Kara 		break;
498884d179dSJan Kara 	case Q_XGETQSTAT:
499884d179dSJan Kara 		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
500884d179dSJan Kara 		compat_fsqstat = addr;
501884d179dSJan Kara 		ret = sys_quotactl(cmd, special, id, fsqstat);
502884d179dSJan Kara 		if (ret)
503884d179dSJan Kara 			break;
504884d179dSJan Kara 		ret = -EFAULT;
505884d179dSJan Kara 		/* Copying qs_version, qs_flags, qs_pad */
506884d179dSJan Kara 		if (copy_in_user(compat_fsqstat, fsqstat,
507884d179dSJan Kara 			offsetof(struct compat_fs_quota_stat, qs_uquota)))
508884d179dSJan Kara 			break;
509884d179dSJan Kara 		/* Copying qs_uquota */
510884d179dSJan Kara 		if (copy_in_user(&compat_fsqstat->qs_uquota,
511884d179dSJan Kara 			&fsqstat->qs_uquota,
512884d179dSJan Kara 			sizeof(compat_fsqstat->qs_uquota)) ||
513884d179dSJan Kara 			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
514884d179dSJan Kara 			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
515884d179dSJan Kara 			break;
516884d179dSJan Kara 		/* Copying qs_gquota */
517884d179dSJan Kara 		if (copy_in_user(&compat_fsqstat->qs_gquota,
518884d179dSJan Kara 			&fsqstat->qs_gquota,
519884d179dSJan Kara 			sizeof(compat_fsqstat->qs_gquota)) ||
520884d179dSJan Kara 			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
521884d179dSJan Kara 			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
522884d179dSJan Kara 			break;
523884d179dSJan Kara 		/* Copying the rest */
524884d179dSJan Kara 		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
525884d179dSJan Kara 			&fsqstat->qs_incoredqs,
526884d179dSJan Kara 			sizeof(struct compat_fs_quota_stat) -
527884d179dSJan Kara 			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
528884d179dSJan Kara 			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
529884d179dSJan Kara 			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
530884d179dSJan Kara 			break;
531884d179dSJan Kara 		ret = 0;
532884d179dSJan Kara 		break;
533884d179dSJan Kara 	default:
534884d179dSJan Kara 		ret = sys_quotactl(cmd, special, id, addr);
535884d179dSJan Kara 	}
536884d179dSJan Kara 	return ret;
537884d179dSJan Kara }
538884d179dSJan Kara #endif
53986e931a3SSteven Whitehouse 
54086e931a3SSteven Whitehouse 
54186e931a3SSteven Whitehouse #ifdef CONFIG_QUOTA_NETLINK_INTERFACE
54286e931a3SSteven Whitehouse 
54386e931a3SSteven Whitehouse /* Netlink family structure for quota */
54486e931a3SSteven Whitehouse static struct genl_family quota_genl_family = {
54586e931a3SSteven Whitehouse 	.id = GENL_ID_GENERATE,
54686e931a3SSteven Whitehouse 	.hdrsize = 0,
54786e931a3SSteven Whitehouse 	.name = "VFS_DQUOT",
54886e931a3SSteven Whitehouse 	.version = 1,
54986e931a3SSteven Whitehouse 	.maxattr = QUOTA_NL_A_MAX,
55086e931a3SSteven Whitehouse };
55186e931a3SSteven Whitehouse 
55286e931a3SSteven Whitehouse /**
55386e931a3SSteven Whitehouse  * quota_send_warning - Send warning to userspace about exceeded quota
55486e931a3SSteven Whitehouse  * @type: The quota type: USRQQUOTA, GRPQUOTA,...
55586e931a3SSteven Whitehouse  * @id: The user or group id of the quota that was exceeded
55686e931a3SSteven Whitehouse  * @dev: The device on which the fs is mounted (sb->s_dev)
55786e931a3SSteven Whitehouse  * @warntype: The type of the warning: QUOTA_NL_...
55886e931a3SSteven Whitehouse  *
55986e931a3SSteven Whitehouse  * This can be used by filesystems (including those which don't use
56086e931a3SSteven Whitehouse  * dquot) to send a message to userspace relating to quota limits.
56186e931a3SSteven Whitehouse  *
56286e931a3SSteven Whitehouse  */
56386e931a3SSteven Whitehouse 
56486e931a3SSteven Whitehouse void quota_send_warning(short type, unsigned int id, dev_t dev,
56586e931a3SSteven Whitehouse 			const char warntype)
56686e931a3SSteven Whitehouse {
56786e931a3SSteven Whitehouse 	static atomic_t seq;
56886e931a3SSteven Whitehouse 	struct sk_buff *skb;
56986e931a3SSteven Whitehouse 	void *msg_head;
57086e931a3SSteven Whitehouse 	int ret;
57186e931a3SSteven Whitehouse 	int msg_size = 4 * nla_total_size(sizeof(u32)) +
57286e931a3SSteven Whitehouse 		       2 * nla_total_size(sizeof(u64));
57386e931a3SSteven Whitehouse 
57486e931a3SSteven Whitehouse 	/* We have to allocate using GFP_NOFS as we are called from a
57586e931a3SSteven Whitehouse 	 * filesystem performing write and thus further recursion into
57686e931a3SSteven Whitehouse 	 * the fs to free some data could cause deadlocks. */
57786e931a3SSteven Whitehouse 	skb = genlmsg_new(msg_size, GFP_NOFS);
57886e931a3SSteven Whitehouse 	if (!skb) {
57986e931a3SSteven Whitehouse 		printk(KERN_ERR
58086e931a3SSteven Whitehouse 		  "VFS: Not enough memory to send quota warning.\n");
58186e931a3SSteven Whitehouse 		return;
58286e931a3SSteven Whitehouse 	}
58386e931a3SSteven Whitehouse 	msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
58486e931a3SSteven Whitehouse 			&quota_genl_family, 0, QUOTA_NL_C_WARNING);
58586e931a3SSteven Whitehouse 	if (!msg_head) {
58686e931a3SSteven Whitehouse 		printk(KERN_ERR
58786e931a3SSteven Whitehouse 		  "VFS: Cannot store netlink header in quota warning.\n");
58886e931a3SSteven Whitehouse 		goto err_out;
58986e931a3SSteven Whitehouse 	}
59086e931a3SSteven Whitehouse 	ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type);
59186e931a3SSteven Whitehouse 	if (ret)
59286e931a3SSteven Whitehouse 		goto attr_err_out;
59386e931a3SSteven Whitehouse 	ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id);
59486e931a3SSteven Whitehouse 	if (ret)
59586e931a3SSteven Whitehouse 		goto attr_err_out;
59686e931a3SSteven Whitehouse 	ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
59786e931a3SSteven Whitehouse 	if (ret)
59886e931a3SSteven Whitehouse 		goto attr_err_out;
59986e931a3SSteven Whitehouse 	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
60086e931a3SSteven Whitehouse 	if (ret)
60186e931a3SSteven Whitehouse 		goto attr_err_out;
60286e931a3SSteven Whitehouse 	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
60386e931a3SSteven Whitehouse 	if (ret)
60486e931a3SSteven Whitehouse 		goto attr_err_out;
60586e931a3SSteven Whitehouse 	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
60686e931a3SSteven Whitehouse 	if (ret)
60786e931a3SSteven Whitehouse 		goto attr_err_out;
60886e931a3SSteven Whitehouse 	genlmsg_end(skb, msg_head);
60986e931a3SSteven Whitehouse 
61086e931a3SSteven Whitehouse 	genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
61186e931a3SSteven Whitehouse 	return;
61286e931a3SSteven Whitehouse attr_err_out:
61386e931a3SSteven Whitehouse 	printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
61486e931a3SSteven Whitehouse err_out:
61586e931a3SSteven Whitehouse 	kfree_skb(skb);
61686e931a3SSteven Whitehouse }
61786e931a3SSteven Whitehouse EXPORT_SYMBOL(quota_send_warning);
61886e931a3SSteven Whitehouse 
61986e931a3SSteven Whitehouse static int __init quota_init(void)
62086e931a3SSteven Whitehouse {
62186e931a3SSteven Whitehouse 	if (genl_register_family(&quota_genl_family) != 0)
62286e931a3SSteven Whitehouse 		printk(KERN_ERR
62386e931a3SSteven Whitehouse 		       "VFS: Failed to create quota netlink interface.\n");
62486e931a3SSteven Whitehouse 	return 0;
62586e931a3SSteven Whitehouse };
62686e931a3SSteven Whitehouse 
62786e931a3SSteven Whitehouse module_init(quota_init);
62886e931a3SSteven Whitehouse #endif
62986e931a3SSteven Whitehouse 
630