⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gfs_kernquota.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Allocate a dquot structure.  If there are * no free slots in the cache, flush LRU entry from * the cache to the appropriate quota file on disk. */struct dquot *dqalloc(uid, dev)	int uid;	dev_t dev;{	register struct dquot *dq;	register struct dqhead *dh;	register struct dquot *dp;	register struct quota *q;	register struct mount *mp;	static struct dqblk zdqb = { 0 };	struct gnode *rgp;	struct gnode *trgp;#ifdef SMP_DEBUG	if (smp_owner(&lk_quota) || smp_owner(&lk_dquot))		panic("dqalloc: cannot hold table locks");#endif 	/*	 * Locate inode of quotas file for	 * indicated file system, return	 * if file doesn't exist.	 */	GETMP(mp, dev);	rgp = (struct gnode *)fref(mp, dev);	if (mp->m_qinod == NULL) {		if (rgp)			grele(rgp);		u.u_error = EINVAL;		return (NODQUOT);	}		/*	 * Check the cache first.	 */search:	smp_lock(&lk_quota, LK_RETRY);	smp_lock(&lk_dquot, LK_RETRY);	dh = &dqhead[DQHASH(uid, dev)];	for (dq = (DQptr)dh->dqh_forw; dq != (DQptr)dh; dq = dq->dq_forw) {		if (!dquot_test_lock(dq)) {			smp_unlock(&lk_dquot);			smp_unlock(&lk_quota);			sleep_unlock((caddr_t)dq, PINOD+1, &lk_dquotlocks);			goto search;		}		if (dq->dq_uid != uid || dq->dq_dev != dev) {			dquot_unlock(dq);			continue;		}		/*		 * Cache hit with no references.  Take		 * the structure off the free list.		 */		if (dq->dq_cnt++ == 0) {			dp = dq->dq_freef;			if (dp != NODQUOT)				dp->dq_freeb = dq->dq_freeb;			else				dqback = dq->dq_freeb;			*dq->dq_freeb = dp;			dq->dq_own = NOQUOTA;		}		smp_unlock(&lk_quota);		smp_unlock(&lk_dquot);		dq->dq_flags |= DQ_HASH;		if (rgp)			grele(rgp);		return (dq);	}	/*	 * Check free list.  If table is full, pull entries	 * off the quota free list and flush any associated	 * dquot references until something frees up on the	 * dquot free list.	 */	if ((dq = dqfreel) == NODQUOT && (q = qfreelist) != NOQUOTA) {		do {			register struct dquot **dqq;			register struct mount *mountp = mount;			dqq = q->q_dq;			quota_lock(q);			while (dqq < &q->q_dq[NMOUNT]) {				trgp = (struct gnode *)fref(mountp, NULL);				if (!dquot_test_lock((*dqq))) {					smp_unlock(&lk_dquotlocks);					mountp++;					dqq++;					if (trgp)						grele(trgp);					continue;				}				if ((dq = *dqq) != NODQUOT &&				    dq != LOSTDQUOT) {					/*					 * Mark entry as "lost" due to					 * scavenging operation.					 */					if (dq->dq_cnt == 1) {						*dqq = LOSTDQUOT;						smp_unlock(&lk_quota);						smp_unlock(&lk_dquot);						putdq(mountp, dq, 1);						dquot_unlock(dq);						quota_unlock(q);						if (trgp)							grele(trgp);						goto search;					}				}				mountp++;				dquot_unlock((*dqq));				dqq++;				if (trgp)					grele(trgp);			}			quota_unlock(q);			q = q->q_freef;		} while ((dq = dqfreel) == NODQUOT && q != NOQUOTA);	}	smp_unlock(&lk_quota);	if (dq == NODQUOT) {		tablefull("dquot");		u.u_error = EUSERS;		smp_unlock(&lk_dquot);		if (rgp)			grele(rgp);		return (dq);	}	/*	 * This shouldn't happen, as we sync	 * dquot before freeing it up.	 */	if (dq->dq_flags & DQ_MOD)		panic("discquota");	/*	 * Now take the dquot off the free list,	 */	dp = dq->dq_freef;	if (dp != NODQUOT)		dp->dq_freeb = &dqfreel;	dqfreel = dp;	/*	 * and off the hash chain it was on, & onto the new one.	 */	dh = &dqhead[DQHASH(uid, dev)];	remque(dq);	dquot_lock(dq);	dq->dq_cnt = 1;	dq->dq_flags = 0;	dq->dq_uid = uid;	dq->dq_dev = dev;	dq->dq_dqb = zdqb;	dq->dq_own = NOQUOTA;	insque(dq, dh);	smp_unlock(&lk_dquot);	if (rgp)		grele(rgp);	return (dq);}/* * dqrele - layman's interface to putdq. */dqrele(dq)	register struct dquot *dq;{	register struct mount *mp;	register struct gnode *rgp;	if (dq == NODQUOT || dq == LOSTDQUOT)		return;#ifdef SMP_DEBUG	if ((dq->dq_state & DQ_LOCK) == 0)		panic("dqrele: Dquot should be locked");#endif	if (dq->dq_cnt > 1) {		dq->dq_cnt--;		return;	}	/*	 * I/O required, find appropriate file system	 * to sync the quota information to.	 */	GETMP(mp, dq->dq_dev);	rgp = (struct gnode *)fref(mp, NULL);	putdq(mp, dq, 1);	if (rgp)		grele(rgp);}/* * Update the disc quota in the quota file. */putdq(mp, dq, free)	register struct mount *mp;	register struct dquot *dq;{	register struct gnode *gp;	if (dq == NODQUOT || dq == LOSTDQUOT)		return;#ifdef SMP_DEBUG	if ((dq->dq_state & DQ_LOCK) == 0) 		panic("putdq: dquot must be locked");	if (smp_owner(&lk_quota) || smp_owner(&lk_dquot))		panic("putdq: cannot hold table locks");#endif	if (free && dq->dq_cnt > 1) {		dq->dq_cnt--;		return;	}	/*	 * Disk quota not modified, just discard	 * or return (having adjusted the reference	 * count), as indicated by the "free" param.	 */	if ((dq->dq_flags & DQ_MOD) == 0) {		if (free) {			dq->dq_cnt = 0; release:			smp_lock(&lk_dquot, LK_RETRY);			if (dqfreel != NODQUOT) {				*dqback = dq;				dq->dq_freeb = dqback;			} else {				dqfreel = dq;				dq->dq_freeb = &dqfreel;			}			dq->dq_freef = NODQUOT;			dqback = &dq->dq_freef;			smp_unlock(&lk_dquot);		}		return;	}	/*	 * Quota modified, write back to disk.	 */	if ((gp = mp->m_qinod) == NULL)		panic("lost quota file");	gfs_lock(gp);	(void) rdwri(UIO_WRITE, gp, (caddr_t)&dq->dq_dqb, sizeof (struct dqblk),	    dq->dq_uid * sizeof (struct dqblk), 1, (int *)0);	gfs_unlock(gp);	dq->dq_flags &= ~DQ_MOD;	if (free && --dq->dq_cnt == 0)		goto release;}/* * See if there is a quota struct in core for user 'uid'. */struct quota *qfind(uid)	register int uid;{	register struct quota *q;	register struct qhash *qh;#ifdef SMP_DEBUG	if (smp_owner(&lk_quota))		panic("qfind: Cannot hold quota table lock");#endif	/* 	 * Check common cases first: asking for own quota,	 * or that of the super user (has reserved slot 0	 * in the table).	 */	q = u.u_quota;	if (q != NOQUOTA && q->q_uid == uid) {		quota_lock(q);		return (q);	}	if (uid == 0) {		/* the second most likely case */		quota_lock(quota);		return (quota);	}	/*	 * Search cache.	 */top:	smp_lock(&lk_quota, LK_RETRY);	qh = &qhash[QHASH(uid)];	for (q = (Qptr)qh->qh_forw; q != (Qptr)qh; q = q->q_forw) {		if (!quota_test_lock(q)) {			smp_unlock(&lk_quota);			sleep_unlock((caddr_t)q, PINOD+1, &lk_quotalocks);			goto top;		}		if (q->q_uid == uid) {			smp_unlock(&lk_quota);			return (q);		}		quota_unlock(q);	}	smp_unlock(&lk_quota);	return (NOQUOTA);}/* * Set the quota file up for a particular file system. * Called as the result of a setquota system call. */opendq(mp, fname)	register struct mount *mp;	caddr_t fname;{	register struct gnode *gp;	register struct quota *q; 	register struct nameidata *ndp = &u.u_nd;	register struct dquot *dq;	register int i = mp - mount;again:	smp_lock(&lk_gnode, LK_RETRY);	if (qactive[i].atv_cnt) {		sleep_unlock((caddr_t)qactive[i].atv_cnt, 		     PINOD+1, &lk_gnode);		goto again;	}	if (qactive[i].atv_flag & QMP_UNSAFE) {		sleep_unlock((caddr_t)qactive[i].atv_flag, 		     PINOD+1, &lk_gnode);		goto again;	}	qactive[i].atv_flag |= QMP_UNSAFE;	smp_unlock(&lk_gnode);	if (mp->m_qinod)		closedq(mp, 1); 	ndp->ni_nameiop = LOOKUP | FOLLOW;	ndp->ni_dirp = fname; 	gp = gfs_namei(ndp);		if (gp == NULL)		goto out;	gfs_unlock(gp);	if (gp->g_dev != mp->m_dev) {		u.u_error = EACCES;		goto out;	}	if ((gp->g_mode & GFMT) != GFREG) {		u.u_error = EACCES;		goto out;	}	/*	 * Flush in-core references to any previous	 * quota file for this file system.	 */	mp->m_qinod = gp;	i = mp - mount;	for (q = quota; q < quotaNQUOTA; q++) {		quota_lock(q);		if ((q->q_flags & Q_NDQ) == 0) {			if (q->q_cnt == 0)				q->q_dq[i] = LOSTDQUOT;			else {				q->q_cnt++;	/* cannot be released */				dq = discquota(q->q_uid, gp);				q->q_dq[i] = dq;				if (dq != NODQUOT) {					dq->dq_own = q;					dquot_unlock(dq);				}				delquota(q);			}		}		quota_unlock(q);	}out:	smp_lock(&lk_gnode, LK_RETRY);	qactive[i].atv_flag = qactive[i].atv_cnt = 0;	smp_unlock(&lk_gnode);	wakeup(qactive[i].atv_flag);	wakeup(qactive[i].atv_cnt);}/* * Close off disc quotas for a file system. */closedq(mp, bypass)	register struct mount *mp;	int bypass;{	register struct dquot *dq;	register int i = mp - mount;	register struct quota *q;	register struct gnode *gp;	if (mp->m_qinod == NULL)		return;try:	if (bypass == 0) {		smp_lock(&lk_gnode, LK_RETRY);		if (qactive[i].atv_cnt) {			sleep_unlock((caddr_t)qactive[i].atv_cnt, 				     PINOD+1, &lk_gnode);			goto try;		}		if (qactive[i].atv_flag & QMP_UNSAFE) {			sleep_unlock((caddr_t)qactive[i].atv_flag, 				     PINOD+1, &lk_gnode);			goto try;		}		qactive[i].atv_flag |= QMP_UNSAFE;		smp_unlock(&lk_gnode);	}		/*	 * Search inode table, delete any references	 * to quota file being closed.	 */       top:	smp_lock(&lk_gnode, LK_RETRY);	for (gp = gnode; gp < gnodeNGNODE; gp++) {		if (gp->g_dev == mp->m_dev) {			if (gp->g_dquot == NODQUOT)				continue;			dq = gp->g_dquot;			gp->g_dquot = NODQUOT;			smp_unlock(&lk_gnode);			dquot_lock(dq);			putdq(mp, dq, 1);			dquot_unlock(dq);			goto top;		}	}	smp_unlock(&lk_gnode);	/*	 * Search quota table, flush any pending	 * quota info to disk and also delete	 * references to closing quota file.	 */again:	smp_lock(&lk_quota, LK_RETRY);	for (q = quota; q < quotaNQUOTA; q++) {		if (!quota_test_lock(q)) {			smp_unlock(&lk_quota);			sleep_unlock((caddr_t)q, PINOD+1, &lk_quotalocks);			goto again;		}		if (q->q_dq[i] == NODQUOT) {			quota_unlock(q);			continue;		}		if ((q->q_flags & Q_NDQ) == 0) {			if (q->q_cnt) {				q->q_cnt++;				smp_unlock(&lk_quota);				dquot_lock(q->q_dq[i]);				putdq(mp, q->q_dq[i], 1);				dquot_unlock(q->q_dq[i]);				delquota(q);			} else {				smp_unlock(&lk_quota);				dquot_lock(q->q_dq[i]);				putdq(mp, q->q_dq[i], 1);				dquot_unlock(q->q_dq[i]);			}		}		q->q_dq[i] = NODQUOT;		quota_unlock(q);		goto again;	}	smp_unlock(&lk_quota);	/*	 * Move all dquot's that used to refer to this quota	 * file of into the never-never (they will eventually	 * fall off the head of the free list and be re-used).	 */	smp_lock(&lk_dquot, LK_RETRY);	for (dq = dquot; dq < dquotNDQUOT; dq++) {		if (dq->dq_dev == mp->m_dev) {			if (!dquot_test_lock(dq))				panic("closedq: dq should not be locked");			if (dq->dq_cnt)				panic("closedq: stray dquot");			remque(dq);			dq->dq_forw = dq;			dq->dq_back = dq;			dq->dq_dev = NODEV;			dquot_unlock(dq);		}	}	smp_unlock(&lk_dquot);	grele(mp->m_qinod);	mp->m_qinod = NULL;	if (bypass)	/* We were called by opendq */		return;	smp_lock(&lk_gnode, LK_RETRY);	qactive[i].atv_flag = qactive[i].atv_cnt = 0;	smp_unlock(&lk_gnode);	wakeup((caddr_t)qactive[i].atv_flag);	wakeup((caddr_t)qactive[i].atv_cnt);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -