This source file includes following definitions.
- hashfn
- hash
- has_quota_enabled
- insert_dquot_free
- remove_dquot_free
- insert_dquot_hash
- remove_dquot_hash
- put_last_free
- grow_dquots
- __wait_on_dquot
- wait_on_dquot
- lock_dquot
- unlock_dquot
- clear_dquot
- write_dquot
- read_dquot
- sync_dquots
- invalidate_dquots
- dquot_incr_inodes
- dquot_incr_blocks
- dquot_decr_inodes
- dquot_decr_blocks
- need_print_warning
- check_idq
- check_bdq
- dqput
- get_empty_dquot
- dqget
- set_dqblk
- get_quota
- get_stats
- dquot_initialize
- dquot_drop
- isize_to_blocks
- dquot_alloc_block
- dquot_alloc_inode
- dquot_free_block
- dquot_free_inode
- dquot_transfer
- dquot_init
- quota_off
- quota_on
- sys_quotactl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <linux/errno.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/types.h>
31 #include <linux/string.h>
32 #include <linux/fcntl.h>
33 #include <linux/stat.h>
34 #include <linux/tty.h>
35 #include <linux/malloc.h>
36 #include <linux/mount.h>
37
38 #include <asm/segment.h>
39
40 #define __DQUOT_VERSION__ "dquot_5.6.0"
41
42 static char quotamessage[MAX_QUOTA_MESSAGE];
43 static char *quotatypes[] = INITQFNAMES;
44
45 static int nr_dquots = 0, nr_free_dquots = 0;
46 static struct dquot *hash_table[NR_DQHASH];
47 static struct dquot *first_dquot;
48 static struct dqstats dqstats;
49
50 static struct wait_queue *dquot_wait = (struct wait_queue *)NULL;
51
52 extern void add_dquot_ref(kdev_t dev, short type);
53 extern void reset_dquot_ptrs(kdev_t dev, short type);
54
55 #ifndef min
56 #define min(a,b) ((a) < (b)) ? (a) : (b)
57 #endif
58
59
60
61
62 static inline int const hashfn(kdev_t dev, unsigned int id, short type)
63 {
64 return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
65 }
66
67 static inline struct dquot **const hash(kdev_t dev, unsigned int id, short type)
68 {
69 return(hash_table + hashfn(dev, id, type));
70 }
71
72 static inline int has_quota_enabled(kdev_t dev, short type)
73 {
74 struct vfsmount *vfsmnt;
75
76 return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL &&
77 (vfsmnt->mnt_quotas[type] != (struct file *)NULL));
78 }
79
80 static void insert_dquot_free(struct dquot *dquot)
81 {
82 dquot->dq_next = first_dquot;
83 dquot->dq_prev = first_dquot->dq_prev;
84 dquot->dq_next->dq_prev = dquot;
85 dquot->dq_prev->dq_next = dquot;
86 first_dquot = dquot;
87 }
88
89 static void remove_dquot_free(struct dquot *dquot)
90 {
91 if (first_dquot == dquot)
92 first_dquot = first_dquot->dq_next;
93 if (dquot->dq_next)
94 dquot->dq_next->dq_prev = dquot->dq_prev;
95 if (dquot->dq_prev)
96 dquot->dq_prev->dq_next = dquot->dq_next;
97 dquot->dq_next = dquot->dq_prev = NODQUOT;
98 }
99
100 static void insert_dquot_hash(struct dquot *dquot)
101 {
102 struct dquot **hash_ent;
103
104 hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
105 dquot->dq_hash_next = *hash_ent;
106 dquot->dq_hash_prev = NODQUOT;
107 if (dquot->dq_hash_next)
108 dquot->dq_hash_next->dq_hash_prev = dquot;
109 *hash_ent = dquot;
110 }
111
112 static void remove_dquot_hash(struct dquot *dquot)
113 {
114 struct dquot **hash_ent;
115
116 hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
117 if (*hash_ent == dquot)
118 *hash_ent = dquot->dq_hash_next;
119 if (dquot->dq_hash_next)
120 dquot->dq_hash_next->dq_hash_prev = dquot->dq_hash_prev;
121 if (dquot->dq_hash_prev)
122 dquot->dq_hash_prev->dq_hash_next = dquot->dq_hash_next;
123 dquot->dq_hash_prev = dquot->dq_hash_next = NODQUOT;
124 }
125
126 static void put_last_free(struct dquot *dquot)
127 {
128 remove_dquot_free(dquot);
129 dquot->dq_prev = first_dquot->dq_prev;
130 dquot->dq_prev->dq_next = dquot;
131 dquot->dq_next = first_dquot;
132 dquot->dq_next->dq_prev = dquot;
133 }
134
135 static void grow_dquots(void)
136 {
137 struct dquot *dquot;
138 int cnt;
139
140 if (!(dquot = (struct dquot*) get_free_page(GFP_KERNEL)))
141 return;
142 dqstats.pages_allocated++;
143 cnt = PAGE_SIZE / sizeof(struct dquot);
144 nr_dquots += cnt;
145 nr_free_dquots += cnt;
146 if (!first_dquot) {
147 dquot->dq_next = dquot->dq_prev = first_dquot = dquot++;
148 cnt--;
149 }
150 for (; cnt; cnt--)
151 insert_dquot_free(dquot++);
152 }
153
154
155
156
157 static void __wait_on_dquot(struct dquot *dquot)
158 {
159 struct wait_queue wait = {current, NULL};
160
161 add_wait_queue(&dquot->dq_wait, &wait);
162 repeat:
163 current->state = TASK_UNINTERRUPTIBLE;
164 if (dquot->dq_flags & DQ_LOCKED) {
165 dquot->dq_flags |= DQ_WANT;
166 schedule();
167 goto repeat;
168 }
169 remove_wait_queue(&dquot->dq_wait, &wait);
170 current->state = TASK_RUNNING;
171 }
172
173 static inline void wait_on_dquot(struct dquot *dquot)
174 {
175 if (dquot->dq_flags & DQ_LOCKED)
176 __wait_on_dquot(dquot);
177 }
178
179 static inline void lock_dquot(struct dquot *dquot)
180 {
181 wait_on_dquot(dquot);
182 dquot->dq_flags |= DQ_LOCKED;
183 }
184
185 static inline void unlock_dquot(struct dquot *dquot)
186 {
187 dquot->dq_flags &= ~DQ_LOCKED;
188 if (dquot->dq_flags & DQ_WANT) {
189 dquot->dq_flags &= ~DQ_WANT;
190 wake_up(&dquot->dq_wait);
191 }
192 }
193
194
195
196
197
198
199
200 static void clear_dquot(struct dquot * dquot)
201 {
202 struct wait_queue *wait;
203
204 wait_on_dquot(dquot);
205 remove_dquot_hash(dquot);
206 remove_dquot_free(dquot);
207 wait = ((volatile struct dquot *) dquot)->dq_wait;
208 if (dquot->dq_count)
209 nr_free_dquots++;
210 memset(dquot, 0, sizeof(*dquot));
211 ((volatile struct dquot *) dquot)->dq_wait = wait;
212 insert_dquot_free(dquot);
213 }
214
215 static void write_dquot(struct dquot *dquot)
216 {
217 short type = dquot->dq_type;
218 struct file *filp = dquot->dq_mnt->mnt_quotas[type];
219 unsigned short fs;
220
221 if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL))
222 return;
223 lock_dquot(dquot);
224 down(&dquot->dq_mnt->mnt_sem);
225 if (filp->f_op->lseek) {
226 if (filp->f_op->lseek(filp->f_inode, filp,
227 dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
228 up(&dquot->dq_mnt->mnt_sem);
229 unlock_dquot(dquot);
230 return;
231 }
232 } else
233 filp->f_pos = dqoff(dquot->dq_id);
234 fs = get_fs();
235 set_fs(KERNEL_DS);
236 if (filp->f_op->write(filp->f_inode, filp,
237 (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
238 dquot->dq_flags &= ~DQ_MOD;
239 up(&dquot->dq_mnt->mnt_sem);
240 set_fs(fs);
241 unlock_dquot(dquot);
242 dqstats.writes++;
243 }
244
245 static void read_dquot(struct dquot *dquot)
246 {
247 short type = dquot->dq_type;
248 struct file *filp = dquot->dq_mnt->mnt_quotas[type];
249 unsigned short fs;
250
251 if (filp == (struct file *)NULL)
252 return;
253 lock_dquot(dquot);
254 down(&dquot->dq_mnt->mnt_sem);
255 if (filp->f_op->lseek) {
256 if (filp->f_op->lseek(filp->f_inode, filp,
257 dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
258 up(&dquot->dq_mnt->mnt_sem);
259 unlock_dquot(dquot);
260 return;
261 }
262 } else
263 filp->f_pos = dqoff(dquot->dq_id);
264 fs = get_fs();
265 set_fs(KERNEL_DS);
266 filp->f_op->read(filp->f_inode, filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
267 up(&dquot->dq_mnt->mnt_sem);
268 set_fs(fs);
269 if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
270 dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
271 dquot->dq_flags |= DQ_FAKE;
272 unlock_dquot(dquot);
273 dqstats.reads++;
274 }
275
276 int sync_dquots(kdev_t dev, short type)
277 {
278 struct dquot *dquot = first_dquot;
279 int i;
280
281 dqstats.syncs++;
282 for (i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) {
283 if (dev == NODEV || dquot->dq_count == 0 || dquot->dq_dev != dev)
284 continue;
285 if (type != -1 && dquot->dq_type != type)
286 continue;
287 wait_on_dquot(dquot);
288 if (dquot->dq_flags & DQ_MOD)
289 write_dquot(dquot);
290 }
291 return(0);
292 }
293
294
295
296
297 void invalidate_dquots(kdev_t dev, short type)
298 {
299 struct dquot *dquot, *next;
300 int cnt;
301
302 next = first_dquot;
303 for (cnt = nr_dquots ; cnt > 0 ; cnt--) {
304 dquot = next;
305 next = dquot->dq_next;
306 if (dquot->dq_dev != dev || dquot->dq_type != type)
307 continue;
308 if (dquot->dq_flags & DQ_LOCKED) {
309 printk("VFS: dquot busy on removed device %s\n", kdevname(dev));
310 continue;
311 }
312 if (dquot->dq_flags & DQ_MOD)
313 write_dquot(dquot);
314 dqstats.drops++;
315 clear_dquot(dquot);
316 }
317 }
318
319 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
320 {
321 lock_dquot(dquot);
322 dquot->dq_curinodes += number;
323 dquot->dq_flags |= DQ_MOD;
324 unlock_dquot(dquot);
325 }
326
327 static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
328 {
329 lock_dquot(dquot);
330 dquot->dq_curblocks += number;
331 dquot->dq_flags |= DQ_MOD;
332 unlock_dquot(dquot);
333 }
334
335 static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
336 {
337 lock_dquot(dquot);
338 if (dquot->dq_curinodes > number)
339 dquot->dq_curinodes -= number;
340 else
341 dquot->dq_curinodes = 0;
342 if (dquot->dq_curinodes < dquot->dq_isoftlimit)
343 dquot->dq_itime = (time_t) 0;
344 dquot->dq_flags &= ~DQ_INODES;
345 dquot->dq_flags |= DQ_MOD;
346 unlock_dquot(dquot);
347 }
348
349 static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
350 {
351 lock_dquot(dquot);
352 if (dquot->dq_curblocks > number)
353 dquot->dq_curblocks -= number;
354 else
355 dquot->dq_curblocks = 0;
356 if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
357 dquot->dq_btime = (time_t) 0;
358 dquot->dq_flags &= ~DQ_BLKS;
359 dquot->dq_flags |= DQ_MOD;
360 unlock_dquot(dquot);
361 }
362
363 static inline int need_print_warning(short type, struct dquot *dquot)
364 {
365 switch (type) {
366 case USRQUOTA:
367 return(current->fsuid == dquot->dq_id);
368 case GRPQUOTA:
369 return(current->fsgid == dquot->dq_id);
370 }
371 return(0);
372 }
373
374 static int check_idq(struct dquot *dquot, short type, u_long short inodes)
375 {
376 if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
377 return(QUOTA_OK);
378 if (dquot->dq_ihardlimit &&
379 (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && !fsuser()) {
380 if ((dquot->dq_flags & DQ_INODES) == 0 &&
381 need_print_warning(type, dquot)) {
382 sprintf(quotamessage, "%s: write failed, %s file limit reached\r\n",
383 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
384 tty_write_message(current->tty, quotamessage);
385 dquot->dq_flags |= DQ_INODES;
386 }
387 return(NO_QUOTA);
388 }
389 if (dquot->dq_isoftlimit &&
390 (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
391 dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && !fsuser()) {
392 if (need_print_warning(type, dquot)) {
393 sprintf(quotamessage, "%s: warning, %s file quota exceeded to long.\r\n",
394 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
395 tty_write_message(current->tty, quotamessage);
396 }
397 return(NO_QUOTA);
398 }
399 if (dquot->dq_isoftlimit &&
400 (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
401 dquot->dq_itime == 0 && !fsuser()) {
402 if (need_print_warning(type, dquot)) {
403 sprintf(quotamessage, "%s: warning, %s file quota exceeded\r\n",
404 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
405 tty_write_message(current->tty, quotamessage);
406 }
407 dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
408 }
409 return(QUOTA_OK);
410 }
411
412 static int check_bdq(struct dquot *dquot, short type, u_long blocks)
413 {
414 if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
415 return(QUOTA_OK);
416 if (dquot->dq_bhardlimit &&
417 (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && !fsuser()) {
418 if ((dquot->dq_flags & DQ_BLKS) == 0 &&
419 need_print_warning(type, dquot)) {
420 sprintf(quotamessage, "%s: write failed, %s disk limit reached.\r\n",
421 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
422 tty_write_message(current->tty, quotamessage);
423 dquot->dq_flags |= DQ_BLKS;
424 }
425 return(NO_QUOTA);
426 }
427 if (dquot->dq_bsoftlimit &&
428 (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
429 dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && !fsuser()) {
430 if (need_print_warning(type, dquot)) {
431 sprintf(quotamessage, "%s: write failed, %s disk quota exceeded to long.\r\n",
432 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
433 tty_write_message(current->tty, quotamessage);
434 }
435 return(NO_QUOTA);
436 }
437 if (dquot->dq_bsoftlimit &&
438 (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
439 dquot->dq_btime == 0 && !fsuser()) {
440 if (need_print_warning(type, dquot)) {
441 sprintf(quotamessage, "%s: warning, %s disk quota exceeded\r\n",
442 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
443 tty_write_message(current->tty, quotamessage);
444 }
445 dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
446 }
447 return(QUOTA_OK);
448 }
449
450 static void dqput(struct dquot *dquot)
451 {
452 if (!dquot)
453 return;
454
455
456
457
458
459 if (dquot->dq_mnt != (struct vfsmount *)NULL) {
460 dqstats.drops++;
461 wait_on_dquot(dquot);
462 if (!dquot->dq_count) {
463 printk("VFS: dqput: trying to free free dquot\n");
464 printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev),
465 quotatypes[dquot->dq_type], dquot->dq_id);
466 return;
467 }
468 repeat:
469 if (dquot->dq_count > 1) {
470 dquot->dq_count--;
471 return;
472 }
473 wake_up(&dquot_wait);
474 if (dquot->dq_flags & DQ_MOD) {
475 write_dquot(dquot);
476 wait_on_dquot(dquot);
477 goto repeat;
478 }
479 }
480 if (dquot->dq_count) {
481 dquot->dq_count--;
482 nr_free_dquots++;
483 }
484 return;
485 }
486
487 static struct dquot *get_empty_dquot(void)
488 {
489 struct dquot *dquot, *best;
490 int cnt;
491
492 if (nr_dquots < NR_DQUOTS && nr_free_dquots < (nr_dquots >> 2))
493 grow_dquots();
494
495 repeat:
496 dquot = first_dquot;
497 best = NODQUOT;
498 for (cnt = 0; cnt < nr_dquots; dquot = dquot->dq_next, cnt++) {
499 if (!dquot->dq_count) {
500 if (!best)
501 best = dquot;
502 if (!(dquot->dq_flags & DQ_MOD) && !(dquot->dq_flags & DQ_LOCKED)) {
503 best = dquot;
504 break;
505 }
506 }
507 }
508 if (!best || best->dq_flags & DQ_MOD || best->dq_flags & DQ_LOCKED)
509 if (nr_dquots < NR_DQUOTS) {
510 grow_dquots();
511 goto repeat;
512 }
513 dquot = best;
514 if (!dquot) {
515 printk("VFS: No free dquots - contact mvw@mcs.ow.org\n");
516 sleep_on(&dquot_wait);
517 goto repeat;
518 }
519 if (dquot->dq_flags & DQ_LOCKED) {
520 wait_on_dquot(dquot);
521 goto repeat;
522 }
523 if (dquot->dq_flags & DQ_MOD) {
524 write_dquot(dquot);
525 goto repeat;
526 }
527 if (dquot->dq_count)
528 goto repeat;
529 clear_dquot(dquot);
530 dquot->dq_count = 1;
531 nr_free_dquots--;
532 if (nr_free_dquots < 0) {
533 printk ("VFS: get_empty_dquot: bad free dquot count.\n");
534 nr_free_dquots = 0;
535 }
536 return(dquot);
537 }
538
539 static struct dquot *dqget(kdev_t dev, unsigned int id, short type)
540 {
541 struct dquot *dquot, *empty;
542 struct vfsmount *vfsmnt;
543
544 if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL ||
545 (vfsmnt->mnt_quotas[type] == (struct file *)0))
546 return(NODQUOT);
547 dqstats.lookups++;
548 empty = get_empty_dquot();
549 repeat:
550 dquot = *(hash(dev, id, type));
551 while (dquot) {
552 if (dquot->dq_dev != dev || dquot->dq_id != id) {
553 dquot = dquot->dq_hash_next;
554 continue;
555 }
556 wait_on_dquot(dquot);
557 if (dquot->dq_dev != dev || dquot->dq_id != id)
558 goto repeat;
559 if (!dquot->dq_count)
560 nr_free_dquots--;
561 dquot->dq_count++;
562 if (empty)
563 dqput(empty);
564 dqstats.cache_hits++;
565 return(dquot);
566 }
567 if (!empty)
568 return(NODQUOT);
569 dquot = empty;
570 dquot->dq_id = id;
571 dquot->dq_type = type;
572 dquot->dq_dev = dev;
573 dquot->dq_mnt = vfsmnt;
574 put_last_free(dquot);
575 insert_dquot_hash(dquot);
576 read_dquot(dquot);
577 return(dquot);
578 }
579
580
581
582
583
584 static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk)
585 {
586 struct dquot *dquot;
587 struct dqblk dq_dqblk;
588 int error;
589
590 if (dqblk == (struct dqblk *)NULL)
591 return(-EFAULT);
592
593 if (flags & QUOTA_SYSCALL) {
594 if ((error = verify_area(VERIFY_READ, dqblk, sizeof(struct dqblk))) != 0)
595 return(error);
596 memcpy_fromfs(&dq_dqblk, dqblk, sizeof(struct dqblk));
597 } else {
598 memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk));
599 }
600 if ((dquot = dqget(dev, id, type)) != NODQUOT) {
601 lock_dquot(dquot);
602 if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
603 dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
604 dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
605 dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
606 dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
607 }
608 if ((flags & SET_QUOTA) || (flags & SET_USE)) {
609 if (dquot->dq_isoftlimit &&
610 dquot->dq_curinodes < dquot->dq_isoftlimit &&
611 dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
612 dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
613 dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
614 if (dquot->dq_curinodes < dquot->dq_isoftlimit)
615 dquot->dq_flags &= ~DQ_INODES;
616 if (dquot->dq_bsoftlimit &&
617 dquot->dq_curblocks < dquot->dq_bsoftlimit &&
618 dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
619 dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
620 dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
621 if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
622 dquot->dq_flags &= ~DQ_BLKS;
623 }
624 if (id == 0) {
625
626
627
628 dquot->dq_mnt->mnt_bexp[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
629 dquot->dq_mnt->mnt_iexp[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
630 }
631 if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
632 dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
633 dquot->dq_flags |= DQ_FAKE;
634 else
635 dquot->dq_flags &= ~DQ_FAKE;
636 dquot->dq_flags |= DQ_MOD;
637 unlock_dquot(dquot);
638 dqput(dquot);
639 }
640 return(0);
641 }
642
643 static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk)
644 {
645 struct dquot *dquot;
646 int error;
647
648 if (has_quota_enabled(dev, type)) {
649 if (dqblk == (struct dqblk *)NULL)
650 return(-EFAULT);
651
652 if ((error = verify_area(VERIFY_WRITE, dqblk, sizeof(struct dqblk))) != 0)
653 return(error);
654
655 if ((dquot = dqget(dev, id, type)) != NODQUOT) {
656 memcpy_tofs(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
657 dqput(dquot);
658 return(0);
659 }
660 }
661 return(-ESRCH);
662 }
663
664 static int get_stats(caddr_t addr)
665 {
666 int error;
667
668 if ((error = verify_area(VERIFY_WRITE, addr, sizeof(struct dqstats))) != 0)
669 return(error);
670
671 dqstats.allocated_dquots = nr_dquots;
672 dqstats.free_dquots = nr_free_dquots;
673 memcpy_tofs(addr, (caddr_t)&dqstats, sizeof(struct dqstats));
674 return(0);
675 }
676
677
678
679
680 void dquot_initialize(struct inode *inode, short type)
681 {
682 unsigned int id = 0;
683 short cnt;
684 struct dquot *tmp;
685
686 if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
687 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
688 if (type != -1 && cnt != type)
689 continue;
690 if (!has_quota_enabled(inode->i_dev, cnt))
691 continue;
692 if (inode->i_dquot[cnt] == NODQUOT) {
693 switch (cnt) {
694 case USRQUOTA:
695 id = inode->i_uid;
696 break;
697 case GRPQUOTA:
698 id = inode->i_gid;
699 break;
700 }
701
702 tmp = dqget(inode->i_dev, id, cnt);
703
704
705
706 if (inode->i_dquot[cnt] != NODQUOT) {
707 dqput(tmp);
708 continue;
709 }
710 inode->i_dquot[cnt] = tmp;
711 inode->i_flags |= S_WRITE;
712 }
713 }
714 }
715 }
716
717 void dquot_drop(struct inode *inode)
718 {
719 short cnt;
720 struct dquot * tmp;
721
722 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
723 if (inode->i_dquot[cnt] == NODQUOT)
724 continue;
725
726
727
728 tmp = inode->i_dquot[cnt];
729 inode->i_dquot[cnt] = NODQUOT;
730 dqput(tmp);
731 }
732 inode->i_flags &= ~S_WRITE;
733 }
734
735
736
737
738
739 static u_long isize_to_blocks(size_t isize, size_t blksize)
740 {
741 u_long blocks;
742 u_long indirect;
743
744 if (!blksize)
745 blksize = BLOCK_SIZE;
746 blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
747 if (blocks > 10) {
748 indirect = ((blocks - 11) >> 8) + 1;
749 if (blocks > (10 + 256)) {
750 indirect += ((blocks - 267) >> 16) + 1;
751 if (blocks > (10 + 256 + (256 << 8)))
752 indirect++;
753 }
754 blocks += indirect;
755 }
756 return(blocks);
757 }
758
759
760
761
762 int dquot_alloc_block(const struct inode *inode, unsigned long number)
763 {
764 unsigned short cnt;
765
766 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
767 if (inode->i_dquot[cnt] == NODQUOT)
768 continue;
769 if (check_bdq(inode->i_dquot[cnt], cnt, number))
770 return(NO_QUOTA);
771 }
772 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
773 if (inode->i_dquot[cnt] == NODQUOT)
774 continue;
775 dquot_incr_blocks(inode->i_dquot[cnt], number);
776 }
777 return(QUOTA_OK);
778 }
779
780 int dquot_alloc_inode(const struct inode *inode, unsigned long number)
781 {
782 unsigned short cnt;
783
784 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
785 if (inode->i_dquot[cnt] == NODQUOT)
786 continue;
787 if (check_idq(inode->i_dquot[cnt], cnt, number))
788 return(NO_QUOTA);
789 }
790 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
791 if (inode->i_dquot[cnt] == NODQUOT)
792 continue;
793 dquot_incr_inodes(inode->i_dquot[cnt], number);
794 }
795 return(QUOTA_OK);
796 }
797
798 void dquot_free_block(const struct inode *inode, unsigned long number)
799 {
800 unsigned short cnt;
801
802 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
803 if (inode->i_dquot[cnt] == NODQUOT)
804 continue;
805 dquot_decr_blocks(inode->i_dquot[cnt], number);
806 }
807 }
808
809 void dquot_free_inode(const struct inode *inode, unsigned long number)
810 {
811 unsigned short cnt;
812
813 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
814 if (inode->i_dquot[cnt] == NODQUOT)
815 continue;
816 dquot_decr_inodes(inode->i_dquot[cnt], number);
817 }
818 }
819
820
821
822
823 int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction)
824 {
825 unsigned long blocks;
826 struct dquot *transfer_from[MAXQUOTAS];
827 struct dquot *transfer_to[MAXQUOTAS];
828 short cnt, disc;
829
830
831
832
833 if (inode->i_blksize == 0)
834 blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE);
835 else
836 blocks = (inode->i_blocks / 2);
837
838
839
840
841
842 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
843 transfer_from[cnt] = NODQUOT;
844 transfer_to[cnt] = NODQUOT;
845
846 if (!has_quota_enabled(inode->i_dev, cnt))
847 continue;
848
849 switch (cnt) {
850 case USRQUOTA:
851 if (inode->i_uid == iattr->ia_uid)
852 continue;
853 transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_uid : inode->i_uid, cnt);
854 transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_uid : iattr->ia_uid, cnt);
855 break;
856 case GRPQUOTA:
857 if (inode->i_gid == iattr->ia_gid)
858 continue;
859 transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_gid : inode->i_gid, cnt);
860 transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_gid : iattr->ia_gid, cnt);
861 break;
862 }
863
864 if (check_idq(transfer_to[cnt], cnt, 1) == NO_QUOTA ||
865 check_bdq(transfer_to[cnt], cnt, blocks) == NO_QUOTA) {
866 for (disc = 0; disc <= cnt; disc++) {
867 dqput(transfer_from[disc]);
868 dqput(transfer_to[disc]);
869 }
870 return(NO_QUOTA);
871 }
872 }
873
874
875
876
877
878 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
879
880
881
882 if (transfer_from[cnt] == NODQUOT && transfer_to[cnt] == NODQUOT)
883 continue;
884
885 if (transfer_from[cnt] != NODQUOT) {
886 dquot_decr_inodes(transfer_from[cnt], 1);
887 dquot_decr_blocks(transfer_from[cnt], blocks);
888 }
889 if (transfer_to[cnt] != NODQUOT) {
890 dquot_incr_inodes(transfer_to[cnt], 1);
891 dquot_incr_blocks(transfer_to[cnt], blocks);
892 }
893 if (inode->i_dquot[cnt] != NODQUOT) {
894 dqput(transfer_from[cnt]);
895 dqput(inode->i_dquot[cnt]);
896 inode->i_dquot[cnt] = transfer_to[cnt];
897 } else {
898 dqput(transfer_from[cnt]);
899 dqput(transfer_to[cnt]);
900 }
901 }
902 return(QUOTA_OK);
903 }
904
905 void dquot_init(void)
906 {
907 printk("VFS: Diskquotas version %s initialized\r\n", __DQUOT_VERSION__);
908 memset(hash_table, 0, sizeof(hash_table));
909 memset((caddr_t)&dqstats, 0, sizeof(dqstats));
910 first_dquot = NODQUOT;
911 }
912
913
914
915
916 struct dquot_operations dquot_operations = {
917 dquot_initialize,
918 dquot_drop,
919 dquot_alloc_block,
920 dquot_alloc_inode,
921 dquot_free_block,
922 dquot_free_inode,
923 dquot_transfer
924 };
925
926
927
928
929 int quota_off(kdev_t dev, short type)
930 {
931 struct vfsmount *vfsmnt;
932 short cnt;
933
934 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
935 if (type != -1 && cnt != type)
936 continue;
937 if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL ||
938 vfsmnt->mnt_quotas[cnt] == (struct file *)NULL)
939 continue;
940 vfsmnt->mnt_sb->dq_op = (struct dquot_operations *)NULL;
941 reset_dquot_ptrs(dev, cnt);
942 invalidate_dquots(dev, cnt);
943 close_fp(vfsmnt->mnt_quotas[cnt]);
944 vfsmnt->mnt_quotas[cnt] = (struct file *)NULL;
945 vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)NULL;
946 }
947 return(0);
948 }
949
950 int quota_on(kdev_t dev, short type, char *path)
951 {
952 struct file *filp = (struct file *)NULL;
953 struct vfsmount *vfsmnt;
954 struct inode *inode;
955 struct dquot *dquot;
956 char *tmp;
957 int error;
958
959 if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL)
960 return(-ENODEV);
961 if (vfsmnt->mnt_quotas[type] != (struct file *)NULL)
962 return(-EBUSY);
963 if ((error = getname(path, &tmp)) != 0)
964 return(error);
965 error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
966 putname(tmp);
967 if (error)
968 return(error);
969 if (!S_ISREG(inode->i_mode)) {
970 iput(inode);
971 return(-EACCES);
972 }
973 if ((filp = get_empty_filp()) != (struct file *)NULL) {
974 filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
975 filp->f_flags = O_RDWR;
976 filp->f_inode = inode;
977 filp->f_pos = 0;
978 filp->f_reada = 0;
979 filp->f_op = inode->i_op->default_file_ops;
980 if (filp->f_op->read || filp->f_op->write) {
981 if ((error = get_write_access(inode)) == 0) {
982 if (filp->f_op && filp->f_op->open)
983 error = filp->f_op->open(inode, filp);
984 if (error == 0) {
985 vfsmnt->mnt_quotas[type] = filp;
986 dquot = dqget(dev, 0, type);
987 vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
988 vfsmnt->mnt_bexp[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
989 dqput(dquot);
990 vfsmnt->mnt_sb->dq_op = &dquot_operations;
991 add_dquot_ref(dev, type);
992 return(0);
993 }
994 put_write_access(inode);
995 }
996 } else
997 error = -EIO;
998 filp->f_count--;
999 } else
1000 error = -EMFILE;
1001 iput(inode);
1002 return(error);
1003 }
1004
1005
1006
1007
1008
1009
1010
1011 asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
1012 {
1013 int cmds = 0, type = 0, flags = 0;
1014 struct inode *ino;
1015 kdev_t dev;
1016
1017 cmds = cmd >> SUBCMDSHIFT;
1018 type = cmd & SUBCMDMASK;
1019
1020 if ((u_int) type >= MAXQUOTAS)
1021 return(-EINVAL);
1022 switch (cmds) {
1023 case Q_SYNC:
1024 case Q_GETSTATS:
1025 break;
1026 case Q_GETQUOTA:
1027 if (((type == USRQUOTA && current->uid != id) ||
1028 (type == GRPQUOTA && current->gid != id)) && !fsuser())
1029 return(-EPERM);
1030 break;
1031 default:
1032 if (!fsuser())
1033 return(-EPERM);
1034 }
1035
1036 if (special == (char *)NULL && (cmds == Q_SYNC || cmds == Q_GETSTATS))
1037 dev = 0;
1038 else {
1039 if (namei(special, &ino))
1040 return(-EINVAL);
1041 dev = ino->i_rdev;
1042 if (!S_ISBLK(ino->i_mode)) {
1043 iput(ino);
1044 return(-ENOTBLK);
1045 }
1046 iput(ino);
1047 }
1048
1049 switch (cmds) {
1050 case Q_QUOTAON:
1051 return(quota_on(dev, type, (char *) addr));
1052 case Q_QUOTAOFF:
1053 return(quota_off(dev, type));
1054 case Q_GETQUOTA:
1055 return(get_quota(dev, id, type, (struct dqblk *) addr));
1056 case Q_SETQUOTA:
1057 flags |= SET_QUOTA;
1058 break;
1059 case Q_SETUSE:
1060 flags |= SET_USE;
1061 break;
1062 case Q_SETQLIM:
1063 flags |= SET_QLIMIT;
1064 break;
1065 case Q_SYNC:
1066 return(sync_dquots(dev, type));
1067 case Q_GETSTATS:
1068 return(get_stats(addr));
1069 default:
1070 return(-EINVAL);
1071 }
1072
1073 flags |= QUOTA_SYSCALL;
1074 if (has_quota_enabled(dev, type))
1075 return(set_dqblk(dev, id, type, flags, (struct dqblk *) addr));
1076 return(-ESRCH);
1077 }