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