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