diff options
-rw-r--r-- | fs/quota/Makefile | 2 | ||||
-rw-r--r-- | fs/quota/kqid.c | 132 | ||||
-rw-r--r-- | include/linux/quota.h | 125 |
3 files changed, 258 insertions, 1 deletions
diff --git a/fs/quota/Makefile b/fs/quota/Makefile index 5f9e9e276af0..c66c37cdaa39 100644 --- a/fs/quota/Makefile +++ b/fs/quota/Makefile | |||
@@ -2,6 +2,6 @@ obj-$(CONFIG_QUOTA) += dquot.o | |||
2 | obj-$(CONFIG_QFMT_V1) += quota_v1.o | 2 | obj-$(CONFIG_QFMT_V1) += quota_v1.o |
3 | obj-$(CONFIG_QFMT_V2) += quota_v2.o | 3 | obj-$(CONFIG_QFMT_V2) += quota_v2.o |
4 | obj-$(CONFIG_QUOTA_TREE) += quota_tree.o | 4 | obj-$(CONFIG_QUOTA_TREE) += quota_tree.o |
5 | obj-$(CONFIG_QUOTACTL) += quota.o | 5 | obj-$(CONFIG_QUOTACTL) += quota.o kqid.o |
6 | obj-$(CONFIG_QUOTACTL_COMPAT) += compat.o | 6 | obj-$(CONFIG_QUOTACTL_COMPAT) += compat.o |
7 | obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o | 7 | obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o |
diff --git a/fs/quota/kqid.c b/fs/quota/kqid.c new file mode 100644 index 000000000000..2f97b0e2c501 --- /dev/null +++ b/fs/quota/kqid.c | |||
@@ -0,0 +1,132 @@ | |||
1 | #include <linux/fs.h> | ||
2 | #include <linux/quota.h> | ||
3 | #include <linux/export.h> | ||
4 | |||
5 | /** | ||
6 | * qid_eq - Test to see if to kquid values are the same | ||
7 | * @left: A qid value | ||
8 | * @right: Another quid value | ||
9 | * | ||
10 | * Return true if the two qid values are equal and false otherwise. | ||
11 | */ | ||
12 | bool qid_eq(struct kqid left, struct kqid right) | ||
13 | { | ||
14 | if (left.type != right.type) | ||
15 | return false; | ||
16 | switch(left.type) { | ||
17 | case USRQUOTA: | ||
18 | return uid_eq(left.uid, right.uid); | ||
19 | case GRPQUOTA: | ||
20 | return gid_eq(left.gid, right.gid); | ||
21 | case PRJQUOTA: | ||
22 | return projid_eq(left.projid, right.projid); | ||
23 | default: | ||
24 | BUG(); | ||
25 | } | ||
26 | } | ||
27 | EXPORT_SYMBOL(qid_eq); | ||
28 | |||
29 | /** | ||
30 | * qid_lt - Test to see if one qid value is less than another | ||
31 | * @left: The possibly lesser qid value | ||
32 | * @right: The possibly greater qid value | ||
33 | * | ||
34 | * Return true if left is less than right and false otherwise. | ||
35 | */ | ||
36 | bool qid_lt(struct kqid left, struct kqid right) | ||
37 | { | ||
38 | if (left.type < right.type) | ||
39 | return true; | ||
40 | if (left.type > right.type) | ||
41 | return false; | ||
42 | switch (left.type) { | ||
43 | case USRQUOTA: | ||
44 | return uid_lt(left.uid, right.uid); | ||
45 | case GRPQUOTA: | ||
46 | return gid_lt(left.gid, right.gid); | ||
47 | case PRJQUOTA: | ||
48 | return projid_lt(left.projid, right.projid); | ||
49 | default: | ||
50 | BUG(); | ||
51 | } | ||
52 | } | ||
53 | EXPORT_SYMBOL(qid_lt); | ||
54 | |||
55 | /** | ||
56 | * from_kqid - Create a qid from a kqid user-namespace pair. | ||
57 | * @targ: The user namespace we want a qid in. | ||
58 | * @kuid: The kernel internal quota identifier to start with. | ||
59 | * | ||
60 | * Map @kqid into the user-namespace specified by @targ and | ||
61 | * return the resulting qid. | ||
62 | * | ||
63 | * There is always a mapping into the initial user_namespace. | ||
64 | * | ||
65 | * If @kqid has no mapping in @targ (qid_t)-1 is returned. | ||
66 | */ | ||
67 | qid_t from_kqid(struct user_namespace *targ, struct kqid kqid) | ||
68 | { | ||
69 | switch (kqid.type) { | ||
70 | case USRQUOTA: | ||
71 | return from_kuid(targ, kqid.uid); | ||
72 | case GRPQUOTA: | ||
73 | return from_kgid(targ, kqid.gid); | ||
74 | case PRJQUOTA: | ||
75 | return from_kprojid(targ, kqid.projid); | ||
76 | default: | ||
77 | BUG(); | ||
78 | } | ||
79 | } | ||
80 | EXPORT_SYMBOL(from_kqid); | ||
81 | |||
82 | /** | ||
83 | * from_kqid_munged - Create a qid from a kqid user-namespace pair. | ||
84 | * @targ: The user namespace we want a qid in. | ||
85 | * @kqid: The kernel internal quota identifier to start with. | ||
86 | * | ||
87 | * Map @kqid into the user-namespace specified by @targ and | ||
88 | * return the resulting qid. | ||
89 | * | ||
90 | * There is always a mapping into the initial user_namespace. | ||
91 | * | ||
92 | * Unlike from_kqid from_kqid_munged never fails and always | ||
93 | * returns a valid projid. This makes from_kqid_munged | ||
94 | * appropriate for use in places where failing to provide | ||
95 | * a qid_t is not a good option. | ||
96 | * | ||
97 | * If @kqid has no mapping in @targ the kqid.type specific | ||
98 | * overflow identifier is returned. | ||
99 | */ | ||
100 | qid_t from_kqid_munged(struct user_namespace *targ, struct kqid kqid) | ||
101 | { | ||
102 | switch (kqid.type) { | ||
103 | case USRQUOTA: | ||
104 | return from_kuid_munged(targ, kqid.uid); | ||
105 | case GRPQUOTA: | ||
106 | return from_kgid_munged(targ, kqid.gid); | ||
107 | case PRJQUOTA: | ||
108 | return from_kprojid_munged(targ, kqid.projid); | ||
109 | default: | ||
110 | BUG(); | ||
111 | } | ||
112 | } | ||
113 | EXPORT_SYMBOL(from_kqid_munged); | ||
114 | |||
115 | /** | ||
116 | * qid_valid - Report if a valid value is stored in a kqid. | ||
117 | * @qid: The kernel internal quota identifier to test. | ||
118 | */ | ||
119 | bool qid_valid(struct kqid qid) | ||
120 | { | ||
121 | switch (qid.type) { | ||
122 | case USRQUOTA: | ||
123 | return uid_valid(qid.uid); | ||
124 | case GRPQUOTA: | ||
125 | return gid_valid(qid.gid); | ||
126 | case PRJQUOTA: | ||
127 | return projid_valid(qid.projid); | ||
128 | default: | ||
129 | BUG(); | ||
130 | } | ||
131 | } | ||
132 | EXPORT_SYMBOL(qid_valid); | ||
diff --git a/include/linux/quota.h b/include/linux/quota.h index 524ede8a160a..00ac8d846c14 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -181,10 +181,135 @@ enum { | |||
181 | #include <linux/dqblk_v2.h> | 181 | #include <linux/dqblk_v2.h> |
182 | 182 | ||
183 | #include <linux/atomic.h> | 183 | #include <linux/atomic.h> |
184 | #include <linux/uidgid.h> | ||
185 | #include <linux/projid.h> | ||
186 | |||
187 | #undef USRQUOTA | ||
188 | #undef GRPQUOTA | ||
189 | enum quota_type { | ||
190 | USRQUOTA = 0, /* element used for user quotas */ | ||
191 | GRPQUOTA = 1, /* element used for group quotas */ | ||
192 | PRJQUOTA = 2, /* element used for project quotas */ | ||
193 | }; | ||
184 | 194 | ||
185 | typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */ | 195 | typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */ |
186 | typedef long long qsize_t; /* Type in which we store sizes */ | 196 | typedef long long qsize_t; /* Type in which we store sizes */ |
187 | 197 | ||
198 | struct kqid { /* Type in which we store the quota identifier */ | ||
199 | union { | ||
200 | kuid_t uid; | ||
201 | kgid_t gid; | ||
202 | kprojid_t projid; | ||
203 | }; | ||
204 | enum quota_type type; /* USRQUOTA (uid) or GRPQUOTA (gid) or PRJQUOTA (projid) */ | ||
205 | }; | ||
206 | |||
207 | extern bool qid_eq(struct kqid left, struct kqid right); | ||
208 | extern bool qid_lt(struct kqid left, struct kqid right); | ||
209 | extern qid_t from_kqid(struct user_namespace *to, struct kqid qid); | ||
210 | extern qid_t from_kqid_munged(struct user_namespace *to, struct kqid qid); | ||
211 | extern bool qid_valid(struct kqid qid); | ||
212 | |||
213 | /** | ||
214 | * make_kqid - Map a user-namespace, type, qid tuple into a kqid. | ||
215 | * @from: User namespace that the qid is in | ||
216 | * @type: The type of quota | ||
217 | * @qid: Quota identifier | ||
218 | * | ||
219 | * Maps a user-namespace, type qid tuple into a kernel internal | ||
220 | * kqid, and returns that kqid. | ||
221 | * | ||
222 | * When there is no mapping defined for the user-namespace, type, | ||
223 | * qid tuple an invalid kqid is returned. Callers are expected to | ||
224 | * test for and handle handle invalid kqids being returned. | ||
225 | * Invalid kqids may be tested for using qid_valid(). | ||
226 | */ | ||
227 | static inline struct kqid make_kqid(struct user_namespace *from, | ||
228 | enum quota_type type, qid_t qid) | ||
229 | { | ||
230 | struct kqid kqid; | ||
231 | |||
232 | kqid.type = type; | ||
233 | switch (type) { | ||
234 | case USRQUOTA: | ||
235 | kqid.uid = make_kuid(from, qid); | ||
236 | break; | ||
237 | case GRPQUOTA: | ||
238 | kqid.gid = make_kgid(from, qid); | ||
239 | break; | ||
240 | case PRJQUOTA: | ||
241 | kqid.projid = make_kprojid(from, qid); | ||
242 | break; | ||
243 | default: | ||
244 | BUG(); | ||
245 | } | ||
246 | return kqid; | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * make_kqid_invalid - Explicitly make an invalid kqid | ||
251 | * @type: The type of quota identifier | ||
252 | * | ||
253 | * Returns an invalid kqid with the specified type. | ||
254 | */ | ||
255 | static inline struct kqid make_kqid_invalid(enum quota_type type) | ||
256 | { | ||
257 | struct kqid kqid; | ||
258 | |||
259 | kqid.type = type; | ||
260 | switch (type) { | ||
261 | case USRQUOTA: | ||
262 | kqid.uid = INVALID_UID; | ||
263 | break; | ||
264 | case GRPQUOTA: | ||
265 | kqid.gid = INVALID_GID; | ||
266 | break; | ||
267 | case PRJQUOTA: | ||
268 | kqid.projid = INVALID_PROJID; | ||
269 | break; | ||
270 | default: | ||
271 | BUG(); | ||
272 | } | ||
273 | return kqid; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * make_kqid_uid - Make a kqid from a kuid | ||
278 | * @uid: The kuid to make the quota identifier from | ||
279 | */ | ||
280 | static inline struct kqid make_kqid_uid(kuid_t uid) | ||
281 | { | ||
282 | struct kqid kqid; | ||
283 | kqid.type = USRQUOTA; | ||
284 | kqid.uid = uid; | ||
285 | return kqid; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * make_kqid_gid - Make a kqid from a kgid | ||
290 | * @gid: The kgid to make the quota identifier from | ||
291 | */ | ||
292 | static inline struct kqid make_kqid_gid(kgid_t gid) | ||
293 | { | ||
294 | struct kqid kqid; | ||
295 | kqid.type = GRPQUOTA; | ||
296 | kqid.gid = gid; | ||
297 | return kqid; | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * make_kqid_projid - Make a kqid from a projid | ||
302 | * @projid: The kprojid to make the quota identifier from | ||
303 | */ | ||
304 | static inline struct kqid make_kqid_projid(kprojid_t projid) | ||
305 | { | ||
306 | struct kqid kqid; | ||
307 | kqid.type = PRJQUOTA; | ||
308 | kqid.projid = projid; | ||
309 | return kqid; | ||
310 | } | ||
311 | |||
312 | |||
188 | extern spinlock_t dq_data_lock; | 313 | extern spinlock_t dq_data_lock; |
189 | 314 | ||
190 | /* Maximal numbers of writes for quota operation (insert/delete/update) | 315 | /* Maximal numbers of writes for quota operation (insert/delete/update) |