1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)quota_ufs.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #ifdef QUOTA
10: /*
11: * MELBOURNE QUOTAS
12: *
13: * Routines used in checking limits on file system usage.
14: */
15: #include "param.h"
16: #include "systm.h"
17: #include "dir.h"
18: #include "user.h"
19: #include "proc.h"
20: #include "inode.h"
21: #include "quota.h"
22: #include "mount.h"
23: #include "fs.h"
24: #include "uio.h"
25:
26: /*
27: * Find the dquot structure that should
28: * be used in checking i/o on inode ip.
29: */
30: struct dquot *
31: inoquota(ip)
32: register struct inode *ip;
33: {
34: register struct quota *q;
35: register struct dquot **dqq;
36: register struct mount *mp;
37: int index;
38:
39: top:
40: q = qfind(ip->i_uid);
41: if (q == NOQUOTA) {
42: for (mp = mount; mp < &mount[NMOUNT]; mp++)
43: if (mp->m_bufp && mp->m_dev == ip->i_dev)
44: return (discquota(ip->i_uid, mp->m_qinod));
45: panic("inoquota");
46: }
47:
48: /*
49: * We have a quota struct in core (most likely our own) that
50: * belongs to the same user as the inode
51: */
52: if (q->q_flags & Q_NDQ)
53: return (NODQUOT);
54: if (q->q_flags & Q_LOCK) {
55: q->q_flags |= Q_WANT;
56: sleep((caddr_t)q, PINOD+1);
57: goto top; /* might just have been freed */
58: }
59: index = getfsx(ip->i_dev);
60: dqq = &q->q_dq[index];
61: if (*dqq == LOSTDQUOT) {
62: q->q_flags |= Q_LOCK;
63: *dqq = discquota(q->q_uid, mount[index].m_qinod);
64: if (*dqq != NODQUOT)
65: (*dqq)->dq_own = q;
66: if (q->q_flags & Q_WANT)
67: wakeup((caddr_t)q);
68: q->q_flags &= ~(Q_LOCK | Q_WANT);
69: }
70: if (*dqq != NODQUOT)
71: (*dqq)->dq_cnt++;
72: return (*dqq);
73: }
74:
75: /*
76: * Update disc usage, and take corrective action.
77: */
78: chkdq(ip, change, force)
79: register struct inode *ip;
80: long change;
81: int force;
82: {
83: register struct dquot *dq;
84:
85: if (change == 0)
86: return (0);
87: dq = ip->i_dquot;
88: if (dq == NODQUOT)
89: return (0);
90: if (dq->dq_bsoftlimit == 0)
91: return (0);
92: dq->dq_flags |= DQ_MOD;
93: /*
94: * reset warnings if below disk quota.
95: */
96: if (dq->dq_bwarn == 0 && dq->dq_bsoftlimit &&
97: (dq->dq_curblocks + change) < dq->dq_bsoftlimit) {
98: dq->dq_bwarn = MAX_DQ_WARN;
99: if (dq->dq_own == u.u_quota) {
100: uprintf("\nUNDER DISC QUOTA: (%s) by %d Kbytes\n",
101: ip->i_fs->fs_fsmnt,
102: dbtob(dq->dq_bsoftlimit -
103: (dq->dq_curblocks + change)) / 1024);
104: }
105: }
106: if (change < 0) {
107: if ((int)dq->dq_curblocks + change >= 0)
108: dq->dq_curblocks += change;
109: else
110: dq->dq_curblocks = 0;
111: dq->dq_flags &= ~DQ_BLKS;
112: return (0);
113: }
114:
115: /*
116: * If user is over quota, or has run out of warnings, then
117: * disallow space allocation (except su's are never stopped).
118: */
119: if (u.u_uid == 0)
120: force = 1;
121: if (!force && dq->dq_bwarn == 0) {
122: if ((dq->dq_flags & DQ_BLKS) == 0 && dq->dq_own == u.u_quota) {
123: uprintf("\nOVER DISC QUOTA: (%s) NO MORE DISC SPACE\n",
124: ip->i_fs->fs_fsmnt);
125: dq->dq_flags |= DQ_BLKS;
126: }
127: return (EDQUOT);
128: }
129: if (dq->dq_curblocks < dq->dq_bsoftlimit) {
130: dq->dq_curblocks += change;
131: if (dq->dq_curblocks < dq->dq_bsoftlimit)
132: return (0);
133: if (dq->dq_own == u.u_quota)
134: uprintf("\nWARNING: disc quota (%s) exceeded\n",
135: ip->i_fs->fs_fsmnt);
136: return (0);
137: }
138: if (!force && dq->dq_bhardlimit &&
139: dq->dq_curblocks + change >= dq->dq_bhardlimit) {
140: if ((dq->dq_flags & DQ_BLKS) == 0 && dq->dq_own == u.u_quota) {
141: uprintf("\nDISC LIMIT REACHED (%s) - WRITE FAILED\n",
142: ip->i_fs->fs_fsmnt);
143: dq->dq_flags |= DQ_BLKS;
144: }
145: return (EDQUOT);
146: }
147: /*
148: * User is over quota, but not over limit
149: * or is over limit, but we have been told
150: * there is nothing we can do.
151: */
152: dq->dq_curblocks += change;
153: return (0);
154: }
155:
156: /*
157: * Check the inode limit, applying corrective action.
158: */
159: chkiq(dev, ip, uid, force)
160: dev_t dev;
161: uid_t uid;
162: register struct inode *ip;
163: int force;
164: {
165: register struct dquot *dq;
166: register struct quota *q;
167:
168: if (ip == NULL) { /* allocation */
169: q = qfind(uid);
170: if (q != NOQUOTA)
171: dq = dqp(q, dev);
172: else
173: dq = discquota(uid, mount[getfsx(dev)].m_qinod);
174: } else { /* free */
175: dq = ip->i_dquot;
176: if (dq != NODQUOT)
177: dq->dq_cnt++;
178: }
179: if (dq == NODQUOT)
180: return (0);
181: if (dq->dq_isoftlimit == 0) {
182: dqrele(dq);
183: return (0);
184: }
185: dq->dq_flags |= DQ_MOD;
186: if (ip) { /* a free */
187: if (dq->dq_curinodes)
188: dq->dq_curinodes--;
189: dq->dq_flags &= ~DQ_INODS;
190: dqrele(dq);
191: return (0);
192: }
193:
194: /*
195: * The following shouldn't be necessary, as if u.u_uid == 0
196: * then dq == NODQUOT & we wouldn't get here at all, but
197: * then again, its not going to harm anything ...
198: */
199: if (u.u_uid == 0) /* su's musn't be stopped */
200: force = 1;
201: if (!force && dq->dq_iwarn == 0) {
202: if ((dq->dq_flags & DQ_INODS) == 0 && dq->dq_own == u.u_quota) {
203: uprintf("\nOVER FILE QUOTA - NO MORE FILES (%s)\n",
204: getfs(dq->dq_dev)->fs_fsmnt);
205: dq->dq_flags |= DQ_INODS;
206: }
207: dqrele(dq);
208: return (EDQUOT);
209: }
210: if (dq->dq_curinodes < dq->dq_isoftlimit) {
211: if (++dq->dq_curinodes >= dq->dq_isoftlimit &&
212: dq->dq_own == u.u_quota)
213: uprintf("\nWARNING - too many files (%s)\n",
214: getfs(dq->dq_dev)->fs_fsmnt);
215: dqrele(dq);
216: return (0);
217: }
218: if (!force && dq->dq_ihardlimit &&
219: dq->dq_curinodes + 1 >= dq->dq_ihardlimit) {
220: if ((dq->dq_flags & DQ_INODS) == 0 && dq->dq_own == u.u_quota) {
221: uprintf("\nFILE LIMIT REACHED - CREATE FAILED (%s)\n",
222: getfs(dq->dq_dev)->fs_fsmnt);
223: dq->dq_flags |= DQ_INODS;
224: }
225: dqrele(dq);
226: return (EDQUOT);
227: }
228: /*
229: * Over quota but not at limit;
230: * or over limit, but we aren't
231: * allowed to stop it.
232: */
233: dq->dq_curinodes++;
234: dqrele(dq);
235: return (0);
236: }
237: #endif
Defined functions
chkdq
defined in line
78; used 5 times