This source file includes following definitions.
- dqref
- getinoquota
- ufs_quota_alloc_blocks2
- ufs_quota_free_blocks2
- chkdqchg
- ufs_quota_alloc_inode2
- ufs_quota_free_inode2
- chkiqchg
- chkdquot
- quotaon_vnode
- quotaon
- quotaoff_vnode
- quotaoff
- getquota
- setquota
- setuse
- qsync_vnode
- qsync
- ufs_quota_init
- dqget
- dqrele
- dqsync
- ufs_quota_delete
- ufs_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
28
29
30
31
32
33
34
35
36
37
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/namei.h>
42 #include <sys/malloc.h>
43 #include <sys/file.h>
44 #include <sys/proc.h>
45 #include <sys/vnode.h>
46 #include <sys/mount.h>
47
48 #include <ufs/ufs/quota.h>
49 #include <ufs/ufs/inode.h>
50 #include <ufs/ufs/ufsmount.h>
51 #include <ufs/ufs/ufs_extern.h>
52
53 #include <sys/queue.h>
54
55
56
57
58
59
60
61 struct dquot {
62 LIST_ENTRY(dquot) dq_hash;
63 TAILQ_ENTRY(dquot) dq_freelist;
64 u_int16_t dq_flags;
65 u_int16_t dq_type;
66 u_int32_t dq_cnt;
67 u_int32_t dq_id;
68 struct vnode *dq_vp;
69 struct ucred *dq_cred;
70 struct dqblk dq_dqb;
71 };
72
73
74
75
76 #define DQ_LOCK 0x01
77 #define DQ_WANT 0x02
78 #define DQ_MOD 0x04
79 #define DQ_FAKE 0x08
80 #define DQ_BLKS 0x10
81 #define DQ_INODS 0x20
82
83
84
85
86 #define dq_bhardlimit dq_dqb.dqb_bhardlimit
87 #define dq_bsoftlimit dq_dqb.dqb_bsoftlimit
88 #define dq_curblocks dq_dqb.dqb_curblocks
89 #define dq_ihardlimit dq_dqb.dqb_ihardlimit
90 #define dq_isoftlimit dq_dqb.dqb_isoftlimit
91 #define dq_curinodes dq_dqb.dqb_curinodes
92 #define dq_btime dq_dqb.dqb_btime
93 #define dq_itime dq_dqb.dqb_itime
94
95
96
97
98
99
100 #define NODQUOT NULL
101
102 void dqref(struct dquot *);
103 void dqrele(struct vnode *, struct dquot *);
104 int dqsync(struct vnode *, struct dquot *);
105
106 #ifdef DIAGNOSTIC
107 void chkdquot(struct inode *);
108 #endif
109
110 int getquota(struct mount *, u_long, int, caddr_t);
111 int quotaon(struct proc *, struct mount *, int, caddr_t);
112 int setquota(struct mount *, u_long, int, caddr_t);
113 int setuse(struct mount *, u_long, int, caddr_t);
114
115 int chkdqchg(struct inode *, long, struct ucred *, int);
116 int chkiqchg(struct inode *, long, struct ucred *, int);
117
118 int dqget(struct vnode *, u_long, struct ufsmount *, int,
119 struct dquot **);
120
121 int quotaon_vnode(struct vnode *, void *);
122 int quotaoff_vnode(struct vnode *, void *);
123 int qsync_vnode(struct vnode *, void *);
124
125
126
127
128 static char *quotatypes[] = INITQFNAMES;
129
130
131
132
133 void
134 dqref(struct dquot *dq)
135 {
136 dq->dq_cnt++;
137 }
138
139
140
141
142
143
144
145
146
147 int
148 getinoquota(struct inode *ip)
149 {
150 struct ufsmount *ump;
151 struct vnode *vp = ITOV(ip);
152 int error;
153
154 ump = ip->i_ump;
155
156
157
158
159 if (ip->i_dquot[USRQUOTA] == NODQUOT &&
160 (error =
161 dqget(vp, DIP(ip, uid), ump, USRQUOTA, &ip->i_dquot[USRQUOTA])) &&
162 error != EINVAL)
163 return (error);
164
165
166
167
168 if (ip->i_dquot[GRPQUOTA] == NODQUOT &&
169 (error =
170 dqget(vp, DIP(ip, gid), ump, GRPQUOTA, &ip->i_dquot[GRPQUOTA])) &&
171 error != EINVAL)
172 return (error);
173 return (0);
174 }
175
176
177
178
179 int
180 ufs_quota_alloc_blocks2(struct inode *ip, int32_t change,
181 struct ucred *cred, enum ufs_quota_flags flags)
182 {
183 struct dquot *dq;
184 int i;
185 int error;
186
187 #ifdef DIAGNOSTIC
188 chkdquot(ip);
189 #endif
190
191 if (change == 0)
192 return (0);
193
194 if ((flags & UFS_QUOTA_FORCE) == 0 &&
195 (cred != NOCRED && cred->cr_uid != 0)) {
196 for (i = 0; i < MAXQUOTAS; i++) {
197 if (flags & (1 << i))
198 continue;
199 if ((dq = ip->i_dquot[i]) == NODQUOT)
200 continue;
201 if ((error = chkdqchg(ip, change, cred, i)) != 0)
202 return (error);
203 }
204 }
205 for (i = 0; i < MAXQUOTAS; i++) {
206 if (flags & (1 << i))
207 continue;
208 if ((dq = ip->i_dquot[i]) == NODQUOT)
209 continue;
210 while (dq->dq_flags & DQ_LOCK) {
211 dq->dq_flags |= DQ_WANT;
212 (void) tsleep(dq, PINOD+1, "chkdq", 0);
213 }
214 dq->dq_curblocks += change;
215 dq->dq_flags |= DQ_MOD;
216 }
217 return (0);
218 }
219
220 int
221 ufs_quota_free_blocks2(struct inode *ip, int32_t change,
222 struct ucred *cred, enum ufs_quota_flags flags)
223 {
224 struct dquot *dq;
225 int i;
226
227 #ifdef DIAGNOSTIC
228 if (!VOP_ISLOCKED(ITOV(ip)))
229 panic ("ufs_quota_free_blocks2: vnode is not locked");
230 #endif
231
232 if (change == 0)
233 return (0);
234
235 for (i = 0; i < MAXQUOTAS; i++) {
236 if (flags & (1 << i))
237 continue;
238 if ((dq = ip->i_dquot[i]) == NODQUOT)
239 continue;
240 while (dq->dq_flags & DQ_LOCK) {
241 dq->dq_flags |= DQ_WANT;
242 (void) tsleep(dq, PINOD+1, "chkdq", 0);
243 }
244 if (dq->dq_curblocks >= change)
245 dq->dq_curblocks -= change;
246 else
247 dq->dq_curblocks = 0;
248 dq->dq_flags &= ~DQ_BLKS;
249 dq->dq_flags |= DQ_MOD;
250 }
251 return (0);
252 }
253
254
255
256
257
258 int
259 chkdqchg(struct inode *ip, long change, struct ucred *cred, int type)
260 {
261 struct dquot *dq = ip->i_dquot[type];
262 long ncurblocks = dq->dq_curblocks + change;
263
264
265
266
267 if (ncurblocks >= dq->dq_bhardlimit && dq->dq_bhardlimit) {
268 if ((dq->dq_flags & DQ_BLKS) == 0 &&
269 DIP(ip, uid) == cred->cr_uid) {
270 uprintf("\n%s: write failed, %s disk limit reached\n",
271 ITOV(ip)->v_mount->mnt_stat.f_mntonname,
272 quotatypes[type]);
273 dq->dq_flags |= DQ_BLKS;
274 }
275 return (EDQUOT);
276 }
277
278
279
280
281 if (ncurblocks >= dq->dq_bsoftlimit && dq->dq_bsoftlimit) {
282 if (dq->dq_curblocks < dq->dq_bsoftlimit) {
283 dq->dq_btime = time_second +
284 ip->i_ump->um_btime[type];
285 if (DIP(ip, uid) == cred->cr_uid)
286 uprintf("\n%s: warning, %s %s\n",
287 ITOV(ip)->v_mount->mnt_stat.f_mntonname,
288 quotatypes[type], "disk quota exceeded");
289 return (0);
290 }
291 if (time_second > dq->dq_btime) {
292 if ((dq->dq_flags & DQ_BLKS) == 0 &&
293 DIP(ip, uid) == cred->cr_uid) {
294 uprintf("\n%s: write failed, %s %s\n",
295 ITOV(ip)->v_mount->mnt_stat.f_mntonname,
296 quotatypes[type],
297 "disk quota exceeded for too long");
298 dq->dq_flags |= DQ_BLKS;
299 }
300 return (EDQUOT);
301 }
302 }
303 return (0);
304 }
305
306
307
308
309 int
310 ufs_quota_alloc_inode2(struct inode *ip, struct ucred *cred,
311 enum ufs_quota_flags flags)
312 {
313 struct dquot *dq;
314 int i;
315 int error;
316
317 #ifdef DIAGNOSTIC
318 chkdquot(ip);
319 #endif
320
321 if ((flags & UFS_QUOTA_FORCE) == 0 && cred->cr_uid != 0) {
322 for (i = 0; i < MAXQUOTAS; i++) {
323 if (flags & (1 << i))
324 continue;
325 if ((dq = ip->i_dquot[i]) == NODQUOT)
326 continue;
327 if ((error = chkiqchg(ip, 1, cred, i)) != 0)
328 return (error);
329 }
330 }
331 for (i = 0; i < MAXQUOTAS; i++) {
332 if (flags & (1 << i))
333 continue;
334 if ((dq = ip->i_dquot[i]) == NODQUOT)
335 continue;
336 while (dq->dq_flags & DQ_LOCK) {
337 dq->dq_flags |= DQ_WANT;
338 (void) tsleep(dq, PINOD+1, "chkiq", 0);
339 }
340 dq->dq_curinodes++;
341 dq->dq_flags |= DQ_MOD;
342 }
343 return (0);
344 }
345
346 int
347 ufs_quota_free_inode2(struct inode *ip, struct ucred *cred,
348 enum ufs_quota_flags flags)
349 {
350 struct dquot *dq;
351 int i;
352
353 #ifdef DIAGNOSTIC
354 if (!VOP_ISLOCKED(ITOV(ip)))
355 panic ("ufs_quota_free_blocks2: vnode is not locked");
356 #endif
357
358 for (i = 0; i < MAXQUOTAS; i++) {
359 if (flags & (1 << i))
360 continue;
361 if ((dq = ip->i_dquot[i]) == NODQUOT)
362 continue;
363 while (dq->dq_flags & DQ_LOCK) {
364 dq->dq_flags |= DQ_WANT;
365 (void) tsleep(dq, PINOD+1, "chkiq", 0);
366 }
367 if (dq->dq_curinodes > 0)
368 dq->dq_curinodes--;
369 dq->dq_flags &= ~DQ_INODS;
370 dq->dq_flags |= DQ_MOD;
371 }
372 return (0);
373 }
374
375
376
377
378
379 int
380 chkiqchg(struct inode *ip, long change, struct ucred *cred, int type)
381 {
382 struct dquot *dq = ip->i_dquot[type];
383 long ncurinodes = dq->dq_curinodes + change;
384
385
386
387
388 if (ncurinodes >= dq->dq_ihardlimit && dq->dq_ihardlimit) {
389 if ((dq->dq_flags & DQ_INODS) == 0 &&
390 DIP(ip, uid) == cred->cr_uid) {
391 uprintf("\n%s: write failed, %s inode limit reached\n",
392 ITOV(ip)->v_mount->mnt_stat.f_mntonname,
393 quotatypes[type]);
394 dq->dq_flags |= DQ_INODS;
395 }
396 return (EDQUOT);
397 }
398
399
400
401
402 if (ncurinodes >= dq->dq_isoftlimit && dq->dq_isoftlimit) {
403 if (dq->dq_curinodes < dq->dq_isoftlimit) {
404 dq->dq_itime = time_second +
405 ip->i_ump->um_itime[type];
406 if (DIP(ip, uid) == cred->cr_uid)
407 uprintf("\n%s: warning, %s %s\n",
408 ITOV(ip)->v_mount->mnt_stat.f_mntonname,
409 quotatypes[type], "inode quota exceeded");
410 return (0);
411 }
412 if (time_second > dq->dq_itime) {
413 if ((dq->dq_flags & DQ_INODS) == 0 &&
414 DIP(ip, uid) == cred->cr_uid) {
415 uprintf("\n%s: write failed, %s %s\n",
416 ITOV(ip)->v_mount->mnt_stat.f_mntonname,
417 quotatypes[type],
418 "inode quota exceeded for too long");
419 dq->dq_flags |= DQ_INODS;
420 }
421 return (EDQUOT);
422 }
423 }
424 return (0);
425 }
426
427 #ifdef DIAGNOSTIC
428
429
430
431
432 void
433 chkdquot(struct inode *ip)
434 {
435 struct ufsmount *ump = ip->i_ump;
436 int i;
437 struct vnode *vp = ITOV(ip);
438
439 if (!VOP_ISLOCKED(vp))
440 panic ("chkdquot: vnode is not locked");
441
442 for (i = 0; i < MAXQUOTAS; i++) {
443 if (ump->um_quotas[i] == NULLVP ||
444 (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING)))
445 continue;
446 if (ip->i_dquot[i] == NODQUOT) {
447 vprint("chkdquot: missing dquot", ITOV(ip));
448 panic("missing dquot");
449 }
450 }
451 }
452 #endif
453
454
455
456
457
458 int
459 quotaon_vnode(struct vnode *vp, void *arg)
460 {
461 int error;
462 struct proc *p = (struct proc *)arg;
463
464 if (vp->v_type == VNON || vp->v_writecount == 0)
465 return (0);
466
467 if (vget(vp, LK_EXCLUSIVE, p)) {
468 return (0);
469 }
470
471 error = getinoquota(VTOI(vp));
472 vput(vp);
473
474 return (error);
475 }
476
477
478
479
480 int
481 quotaon(struct proc *p, struct mount *mp, int type, caddr_t fname)
482 {
483 struct ufsmount *ump = VFSTOUFS(mp);
484 struct vnode *vp, **vpp;
485 struct dquot *dq;
486 int error;
487 struct nameidata nd;
488
489 #ifdef DIAGNOSTIC
490 if (!vfs_isbusy(mp))
491 panic ("quotaon: mount point not busy");
492 #endif
493
494 vpp = &ump->um_quotas[type];
495 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, p);
496 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0)
497 return (error);
498 vp = nd.ni_vp;
499 VOP_UNLOCK(vp, 0, p);
500 if (vp->v_type != VREG) {
501 (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
502 return (EACCES);
503 }
504 if (*vpp != vp)
505 quotaoff(p, mp, type);
506 ump->um_qflags[type] |= QTF_OPENING;
507 mp->mnt_flag |= MNT_QUOTA;
508 vp->v_flag |= VSYSTEM;
509 *vpp = vp;
510
511
512
513
514 crhold(p->p_ucred);
515 ump->um_cred[type] = p->p_ucred;
516 ump->um_btime[type] = MAX_DQ_TIME;
517 ump->um_itime[type] = MAX_IQ_TIME;
518 if (dqget(NULLVP, 0, ump, type, &dq) == 0) {
519 if (dq->dq_btime > 0)
520 ump->um_btime[type] = dq->dq_btime;
521 if (dq->dq_itime > 0)
522 ump->um_itime[type] = dq->dq_itime;
523 dqrele(NULLVP, dq);
524 }
525
526
527
528
529
530 error = vfs_mount_foreach_vnode(mp, quotaon_vnode, p);
531
532 ump->um_qflags[type] &= ~QTF_OPENING;
533 if (error)
534 quotaoff(p, mp, type);
535 return (error);
536 }
537
538 struct quotaoff_arg {
539 struct proc *p;
540 int type;
541 };
542
543 int
544 quotaoff_vnode(struct vnode *vp, void *arg)
545 {
546 struct quotaoff_arg *qa = (struct quotaoff_arg *)arg;
547 struct inode *ip;
548 struct dquot *dq;
549
550 if (vp->v_type == VNON)
551 return (0);
552
553
554 if (vget(vp, LK_EXCLUSIVE, qa->p))
555 return (0);
556 ip = VTOI(vp);
557 dq = ip->i_dquot[qa->type];
558 ip->i_dquot[qa->type] = NODQUOT;
559 dqrele(vp, dq);
560 vput(vp);
561 return (0);
562 }
563
564
565
566
567 int
568 quotaoff(struct proc *p, struct mount *mp, int type)
569 {
570 struct vnode *qvp;
571 struct ufsmount *ump = VFSTOUFS(mp);
572 struct quotaoff_arg qa;
573 int error;
574
575 #ifdef DIAGNOSTIC
576 if (!vfs_isbusy(mp))
577 panic ("quotaoff: mount point not busy");
578 #endif
579 if ((qvp = ump->um_quotas[type]) == NULLVP)
580 return (0);
581 ump->um_qflags[type] |= QTF_CLOSING;
582
583
584
585
586 qa.p = p;
587 qa.type = type;
588 vfs_mount_foreach_vnode(mp, quotaoff_vnode, &qa);
589
590 error = vn_close(qvp, FREAD|FWRITE, p->p_ucred, p);
591 ump->um_quotas[type] = NULLVP;
592 crfree(ump->um_cred[type]);
593 ump->um_cred[type] = NOCRED;
594 ump->um_qflags[type] &= ~QTF_CLOSING;
595 for (type = 0; type < MAXQUOTAS; type++)
596 if (ump->um_quotas[type] != NULLVP)
597 break;
598 if (type == MAXQUOTAS)
599 mp->mnt_flag &= ~MNT_QUOTA;
600 return (error);
601 }
602
603
604
605
606 int
607 getquota(struct mount *mp, u_long id, int type, caddr_t addr)
608 {
609 struct dquot *dq;
610 int error;
611
612 if ((error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq)) != 0)
613 return (error);
614 error = copyout((caddr_t)&dq->dq_dqb, addr, sizeof (struct dqblk));
615 dqrele(NULLVP, dq);
616 return (error);
617 }
618
619
620
621
622 int
623 setquota(struct mount *mp, u_long id, int type, caddr_t addr)
624 {
625 struct dquot *dq;
626 struct dquot *ndq;
627 struct ufsmount *ump = VFSTOUFS(mp);
628 struct dqblk newlim;
629 int error;
630
631 error = copyin(addr, (caddr_t)&newlim, sizeof (struct dqblk));
632 if (error)
633 return (error);
634 if ((error = dqget(NULLVP, id, ump, type, &ndq)) != 0)
635 return (error);
636 dq = ndq;
637 while (dq->dq_flags & DQ_LOCK) {
638 dq->dq_flags |= DQ_WANT;
639 (void) tsleep(dq, PINOD+1, "setquota", 0);
640 }
641
642
643
644
645
646 newlim.dqb_curblocks = dq->dq_curblocks;
647 newlim.dqb_curinodes = dq->dq_curinodes;
648 if (dq->dq_id != 0) {
649 newlim.dqb_btime = dq->dq_btime;
650 newlim.dqb_itime = dq->dq_itime;
651 }
652 if (newlim.dqb_bsoftlimit &&
653 dq->dq_curblocks >= newlim.dqb_bsoftlimit &&
654 (dq->dq_bsoftlimit == 0 || dq->dq_curblocks < dq->dq_bsoftlimit))
655 newlim.dqb_btime = time_second + ump->um_btime[type];
656 if (newlim.dqb_isoftlimit &&
657 dq->dq_curinodes >= newlim.dqb_isoftlimit &&
658 (dq->dq_isoftlimit == 0 || dq->dq_curinodes < dq->dq_isoftlimit))
659 newlim.dqb_itime = time_second + ump->um_itime[type];
660 dq->dq_dqb = newlim;
661 if (dq->dq_curblocks < dq->dq_bsoftlimit)
662 dq->dq_flags &= ~DQ_BLKS;
663 if (dq->dq_curinodes < dq->dq_isoftlimit)
664 dq->dq_flags &= ~DQ_INODS;
665 if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 &&
666 dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0)
667 dq->dq_flags |= DQ_FAKE;
668 else
669 dq->dq_flags &= ~DQ_FAKE;
670 dq->dq_flags |= DQ_MOD;
671 dqrele(NULLVP, dq);
672 return (0);
673 }
674
675
676
677
678 int
679 setuse(struct mount *mp, u_long id, int type, caddr_t addr)
680 {
681 struct dquot *dq;
682 struct ufsmount *ump = VFSTOUFS(mp);
683 struct dquot *ndq;
684 struct dqblk usage;
685 int error;
686
687 error = copyin(addr, (caddr_t)&usage, sizeof (struct dqblk));
688 if (error)
689 return (error);
690 if ((error = dqget(NULLVP, id, ump, type, &ndq)) != 0)
691 return (error);
692 dq = ndq;
693 while (dq->dq_flags & DQ_LOCK) {
694 dq->dq_flags |= DQ_WANT;
695 (void) tsleep(dq, PINOD+1, "setuse", 0);
696 }
697
698
699
700
701 if (dq->dq_bsoftlimit && dq->dq_curblocks < dq->dq_bsoftlimit &&
702 usage.dqb_curblocks >= dq->dq_bsoftlimit)
703 dq->dq_btime = time_second + ump->um_btime[type];
704 if (dq->dq_isoftlimit && dq->dq_curinodes < dq->dq_isoftlimit &&
705 usage.dqb_curinodes >= dq->dq_isoftlimit)
706 dq->dq_itime = time_second + ump->um_itime[type];
707 dq->dq_curblocks = usage.dqb_curblocks;
708 dq->dq_curinodes = usage.dqb_curinodes;
709 if (dq->dq_curblocks < dq->dq_bsoftlimit)
710 dq->dq_flags &= ~DQ_BLKS;
711 if (dq->dq_curinodes < dq->dq_isoftlimit)
712 dq->dq_flags &= ~DQ_INODS;
713 dq->dq_flags |= DQ_MOD;
714 dqrele(NULLVP, dq);
715 return (0);
716 }
717
718 int
719 qsync_vnode(struct vnode *vp, void *arg)
720 {
721 int i;
722 struct proc *p = curproc;
723 struct dquot *dq;
724
725 if (vp->v_type == VNON)
726 return (0);
727
728 if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, p))
729 return (0);
730
731 for (i = 0; i < MAXQUOTAS; i++) {
732 dq = VTOI(vp)->i_dquot[i];
733 if (dq != NODQUOT && (dq->dq_flags & DQ_MOD))
734 dqsync(vp, dq);
735 }
736 vput(vp);
737 return (0);
738 }
739
740
741
742
743 int
744 qsync(struct mount *mp)
745 {
746 struct ufsmount *ump = VFSTOUFS(mp);
747 int i;
748
749
750
751
752
753 for (i = 0; i < MAXQUOTAS; i++)
754 if (ump->um_quotas[i] != NULLVP)
755 break;
756 if (i == MAXQUOTAS)
757 return (0);
758
759
760
761
762 vfs_mount_foreach_vnode(mp, qsync_vnode, NULL);
763 return (0);
764 }
765
766
767
768
769 #define DQHASH(dqvp, id) \
770 (&dqhashtbl[((((long)(dqvp)) >> 8) + id) & dqhash])
771 LIST_HEAD(dqhash, dquot) *dqhashtbl;
772 u_long dqhash;
773
774
775
776
777 #define DQUOTINC 5
778 TAILQ_HEAD(dqfreelist, dquot) dqfreelist;
779 long numdquot, desireddquot = DQUOTINC;
780
781
782
783
784 void
785 ufs_quota_init(void)
786 {
787 dqhashtbl = hashinit(desiredvnodes, M_DQUOT, M_WAITOK, &dqhash);
788 TAILQ_INIT(&dqfreelist);
789 }
790
791
792
793
794
795 int
796 dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type,
797 struct dquot **dqp)
798 {
799 struct proc *p = curproc;
800 struct dquot *dq;
801 struct dqhash *dqh;
802 struct vnode *dqvp;
803 struct iovec aiov;
804 struct uio auio;
805 int error;
806
807 dqvp = ump->um_quotas[type];
808 if (dqvp == NULLVP || (ump->um_qflags[type] & QTF_CLOSING)) {
809 *dqp = NODQUOT;
810 return (EINVAL);
811 }
812
813
814
815 dqh = DQHASH(dqvp, id);
816 LIST_FOREACH(dq, dqh, dq_hash) {
817 if (dq->dq_id != id ||
818 dq->dq_vp != dqvp)
819 continue;
820
821
822
823
824 if (dq->dq_cnt == 0)
825 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
826 dqref(dq);
827 *dqp = dq;
828 return (0);
829 }
830
831
832
833 if (TAILQ_FIRST(&dqfreelist) == NODQUOT &&
834 numdquot < MAXQUOTAS * desiredvnodes)
835 desireddquot += DQUOTINC;
836 if (numdquot < desireddquot) {
837 dq = (struct dquot *)malloc(sizeof *dq, M_DQUOT, M_WAITOK);
838 bzero((char *)dq, sizeof *dq);
839 numdquot++;
840 } else {
841 if ((dq = TAILQ_FIRST(&dqfreelist)) == NULL) {
842 tablefull("dquot");
843 *dqp = NODQUOT;
844 return (EUSERS);
845 }
846 if (dq->dq_cnt || (dq->dq_flags & DQ_MOD))
847 panic("free dquot isn't");
848 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
849 LIST_REMOVE(dq, dq_hash);
850 crfree(dq->dq_cred);
851 dq->dq_cred = NOCRED;
852 }
853
854
855
856 if (vp != dqvp)
857 vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p);
858 LIST_INSERT_HEAD(dqh, dq, dq_hash);
859 dqref(dq);
860 dq->dq_flags = DQ_LOCK;
861 dq->dq_id = id;
862 dq->dq_vp = dqvp;
863 dq->dq_type = type;
864 crhold(ump->um_cred[type]);
865 dq->dq_cred = ump->um_cred[type];
866 auio.uio_iov = &aiov;
867 auio.uio_iovcnt = 1;
868 aiov.iov_base = (caddr_t)&dq->dq_dqb;
869 aiov.iov_len = sizeof (struct dqblk);
870 auio.uio_resid = sizeof (struct dqblk);
871 auio.uio_offset = (off_t)(id * sizeof (struct dqblk));
872 auio.uio_segflg = UIO_SYSSPACE;
873 auio.uio_rw = UIO_READ;
874 auio.uio_procp = (struct proc *)0;
875 error = VOP_READ(dqvp, &auio, 0, dq->dq_cred);
876 if (auio.uio_resid == sizeof(struct dqblk) && error == 0)
877 bzero((caddr_t)&dq->dq_dqb, sizeof(struct dqblk));
878 if (vp != dqvp)
879 VOP_UNLOCK(dqvp, 0, p);
880 if (dq->dq_flags & DQ_WANT)
881 wakeup(dq);
882 dq->dq_flags = 0;
883
884
885
886
887 if (error) {
888 LIST_REMOVE(dq, dq_hash);
889 dqrele(vp, dq);
890 *dqp = NODQUOT;
891 return (error);
892 }
893
894
895
896
897 if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 &&
898 dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0)
899 dq->dq_flags |= DQ_FAKE;
900 if (dq->dq_id != 0) {
901 if (dq->dq_btime == 0)
902 dq->dq_btime = time_second + ump->um_btime[type];
903 if (dq->dq_itime == 0)
904 dq->dq_itime = time_second + ump->um_itime[type];
905 }
906 *dqp = dq;
907 return (0);
908 }
909
910
911
912
913 void
914 dqrele(struct vnode *vp, struct dquot *dq)
915 {
916
917 if (dq == NODQUOT)
918 return;
919 if (dq->dq_cnt > 1) {
920 dq->dq_cnt--;
921 return;
922 }
923 if (dq->dq_flags & DQ_MOD)
924 (void) dqsync(vp, dq);
925 if (--dq->dq_cnt > 0)
926 return;
927 TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist);
928 }
929
930
931
932
933 int
934 dqsync(struct vnode *vp, struct dquot *dq)
935 {
936 struct proc *p = curproc;
937 struct vnode *dqvp;
938 struct iovec aiov;
939 struct uio auio;
940 int error;
941
942 if (dq == NODQUOT)
943 panic("dqsync: dquot");
944 if ((dq->dq_flags & DQ_MOD) == 0)
945 return (0);
946 if ((dqvp = dq->dq_vp) == NULLVP)
947 panic("dqsync: file");
948
949 if (vp != dqvp)
950 vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p);
951 while (dq->dq_flags & DQ_LOCK) {
952 dq->dq_flags |= DQ_WANT;
953 (void) tsleep(dq, PINOD+2, "dqsync", 0);
954 if ((dq->dq_flags & DQ_MOD) == 0) {
955 if (vp != dqvp)
956 VOP_UNLOCK(dqvp, 0, p);
957 return (0);
958 }
959 }
960 dq->dq_flags |= DQ_LOCK;
961 auio.uio_iov = &aiov;
962 auio.uio_iovcnt = 1;
963 aiov.iov_base = (caddr_t)&dq->dq_dqb;
964 aiov.iov_len = sizeof (struct dqblk);
965 auio.uio_resid = sizeof (struct dqblk);
966 auio.uio_offset = (off_t)(dq->dq_id * sizeof (struct dqblk));
967 auio.uio_segflg = UIO_SYSSPACE;
968 auio.uio_rw = UIO_WRITE;
969 auio.uio_procp = (struct proc *)0;
970 error = VOP_WRITE(dqvp, &auio, 0, dq->dq_cred);
971 if (auio.uio_resid && error == 0)
972 error = EIO;
973 if (dq->dq_flags & DQ_WANT)
974 wakeup(dq);
975 dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT);
976 if (vp != dqvp)
977 VOP_UNLOCK(dqvp, 0, p);
978 return (error);
979 }
980
981 int
982 ufs_quota_delete(struct inode *ip)
983 {
984 struct vnode *vp = ITOV(ip);
985 int i;
986 for (i = 0; i < MAXQUOTAS; i++) {
987 if (ip->i_dquot[i] != NODQUOT) {
988 dqrele(vp, ip->i_dquot[i]);
989 ip->i_dquot[i] = NODQUOT;
990 }
991 }
992
993 return (0);
994 }
995
996
997
998
999 int
1000 ufs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
1001 struct proc *p)
1002 {
1003 int cmd, type, error;
1004
1005 if (uid == -1)
1006 uid = p->p_cred->p_ruid;
1007 cmd = cmds >> SUBCMDSHIFT;
1008
1009 switch (cmd) {
1010 case Q_SYNC:
1011 break;
1012 case Q_GETQUOTA:
1013 if (uid == p->p_cred->p_ruid)
1014 break;
1015
1016 default:
1017 if ((error = suser(p, 0)) != 0)
1018 return (error);
1019 }
1020
1021 type = cmds & SUBCMDMASK;
1022 if ((u_int)type >= MAXQUOTAS)
1023 return (EINVAL);
1024
1025 if (vfs_busy(mp, VB_READ|VB_NOWAIT))
1026 return (0);
1027
1028
1029 switch (cmd) {
1030
1031 case Q_QUOTAON:
1032 error = quotaon(p, mp, type, arg);
1033 break;
1034
1035 case Q_QUOTAOFF:
1036 error = quotaoff(p, mp, type);
1037 break;
1038
1039 case Q_SETQUOTA:
1040 error = setquota(mp, uid, type, arg) ;
1041 break;
1042
1043 case Q_SETUSE:
1044 error = setuse(mp, uid, type, arg);
1045 break;
1046
1047 case Q_GETQUOTA:
1048 error = getquota(mp, uid, type, arg);
1049 break;
1050
1051 case Q_SYNC:
1052 error = qsync(mp);
1053 break;
1054
1055 default:
1056 error = EINVAL;
1057 break;
1058 }
1059
1060 vfs_unbusy(mp);
1061 return (error);
1062 }