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
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 997
Valid CSS Valid XHTML 1.0 Strict