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

📄 xfs_qm_syscalls.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (uflags & XFS_QUOTA_GDQ_ACCT)		flags |= XFS_GQUOTA_ACCT;	if (uflags & XFS_QUOTA_UDQ_ENFD)		flags |= XFS_UQUOTA_ENFD;	if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))		flags |= XFS_OQUOTA_ENFD;	return (flags);}STATIC uintxfs_qm_export_flags(	uint flags){	uint uflags;	uflags = 0;	if (flags & XFS_UQUOTA_ACCT)		uflags |= XFS_QUOTA_UDQ_ACCT;	if (flags & XFS_PQUOTA_ACCT)		uflags |= XFS_QUOTA_PDQ_ACCT;	if (flags & XFS_GQUOTA_ACCT)		uflags |= XFS_QUOTA_GDQ_ACCT;	if (flags & XFS_UQUOTA_ENFD)		uflags |= XFS_QUOTA_UDQ_ENFD;	if (flags & (XFS_OQUOTA_ENFD)) {		uflags |= (flags & XFS_GQUOTA_ACCT) ?			XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;	}	return (uflags);}/* * Go thru all the inodes in the file system, releasing their dquots. * Note that the mount structure gets modified to indicate that quotas are off * AFTER this, in the case of quotaoff. This also gets called from * xfs_rootumount. */voidxfs_qm_dqrele_all_inodes(	struct xfs_mount *mp,	uint		 flags){	xfs_inode_t	*ip, *topino;	uint		ireclaims;	vnode_t		*vp;	boolean_t	vnode_refd;	ASSERT(mp->m_quotainfo);	XFS_MOUNT_ILOCK(mp);again:	ip = mp->m_inodes;	if (ip == NULL) {		XFS_MOUNT_IUNLOCK(mp);		return;	}	do {		/* Skip markers inserted by xfs_sync */		if (ip->i_mount == NULL) {			ip = ip->i_mnext;			continue;		}		/* Root inode, rbmip and rsumip have associated blocks */		if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) {			ASSERT(ip->i_udquot == NULL);			ASSERT(ip->i_gdquot == NULL);			ip = ip->i_mnext;			continue;		}		vp = XFS_ITOV_NULL(ip);		if (!vp) {			ASSERT(ip->i_udquot == NULL);			ASSERT(ip->i_gdquot == NULL);			ip = ip->i_mnext;			continue;		}		vnode_refd = B_FALSE;		if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {			ireclaims = mp->m_ireclaims;			topino = mp->m_inodes;			vp = vn_grab(vp);			if (!vp)				goto again;			XFS_MOUNT_IUNLOCK(mp);			/* XXX restart limit ? */			xfs_ilock(ip, XFS_ILOCK_EXCL);			vnode_refd = B_TRUE;		} else {			ireclaims = mp->m_ireclaims;			topino = mp->m_inodes;			XFS_MOUNT_IUNLOCK(mp);		}		/*		 * We don't keep the mountlock across the dqrele() call,		 * since it can take a while..		 */		if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {			xfs_qm_dqrele(ip->i_udquot);			ip->i_udquot = NULL;		}		if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {			xfs_qm_dqrele(ip->i_gdquot);			ip->i_gdquot = NULL;		}		xfs_iunlock(ip, XFS_ILOCK_EXCL);		/*		 * Wait until we've dropped the ilock and mountlock to		 * do the vn_rele. Or be condemned to an eternity in the		 * inactive code in hell.		 */		if (vnode_refd)			VN_RELE(vp);		XFS_MOUNT_ILOCK(mp);		/*		 * If an inode was inserted or removed, we gotta		 * start over again.		 */		if (topino != mp->m_inodes || mp->m_ireclaims != ireclaims) {			/* XXX use a sentinel */			goto again;		}		ip = ip->i_mnext;	} while (ip != mp->m_inodes);	XFS_MOUNT_IUNLOCK(mp);}/*------------------------------------------------------------------------*/#ifdef DEBUG/* * This contains all the test functions for XFS disk quotas. * Currently it does a quota accounting check. ie. it walks through * all inodes in the file system, calculating the dquot accounting fields, * and prints out any inconsistencies. */xfs_dqhash_t *qmtest_udqtab;xfs_dqhash_t *qmtest_gdqtab;int	      qmtest_hashmask;int	      qmtest_nfails;mutex_t	      qcheck_lock;#define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \				 (__psunsigned_t)(id)) & \				(qmtest_hashmask - 1))#define DQTEST_HASH(mp, id, type)   ((type & XFS_DQ_USER) ? \				     (qmtest_udqtab + \				      DQTEST_HASHVAL(mp, id)) : \				     (qmtest_gdqtab + \				      DQTEST_HASHVAL(mp, id)))#define DQTEST_LIST_PRINT(l, NXT, title) \{ \	  xfs_dqtest_t	*dqp; int i = 0;\	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \	       dqp = (xfs_dqtest_t *)dqp->NXT) { \		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \			 dqp->d_bcount, dqp->d_icount); } \}typedef struct dqtest {	xfs_dqmarker_t	q_lists;	xfs_dqhash_t	*q_hash;	/* the hashchain header */	xfs_mount_t	*q_mount;	/* filesystem this relates to */	xfs_dqid_t	d_id;		/* user id or group id */	xfs_qcnt_t	d_bcount;	/* # disk blocks owned by the user */	xfs_qcnt_t	d_icount;	/* # inodes owned by the user */} xfs_dqtest_t;STATIC voidxfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp){	xfs_dquot_t *d;	if (((d) = (h)->qh_next))		(d)->HL_PREVP = &((dqp)->HL_NEXT);	(dqp)->HL_NEXT = d;	(dqp)->HL_PREVP = &((h)->qh_next);	(h)->qh_next = (xfs_dquot_t *)dqp;	(h)->qh_version++;	(h)->qh_nelems++;}STATIC voidxfs_qm_dqtest_print(	xfs_dqtest_t	*d){	cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");	cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);	cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount);	cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)",		d->d_bcount, (int)d->d_bcount);	cmn_err(CE_DEBUG, "---- icount   = %Lu (0x%x)",		d->d_icount, (int)d->d_icount);	cmn_err(CE_DEBUG, "---------------------------");}STATIC voidxfs_qm_dqtest_failed(	xfs_dqtest_t	*d,	xfs_dquot_t	*dqp,	char		*reason,	xfs_qcnt_t	a,	xfs_qcnt_t	b,	int		error){	qmtest_nfails++;	if (error)		cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s",		       d->d_id, error, reason);	else		cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]",		       d->d_id, reason, (int)a, (int)b);	xfs_qm_dqtest_print(d);	if (dqp)		xfs_qm_dqprint(dqp);}STATIC intxfs_dqtest_cmp2(	xfs_dqtest_t	*d,	xfs_dquot_t	*dqp){	int err = 0;	if (be64_to_cpu(dqp->q_core.d_icount) != d->d_icount) {		xfs_qm_dqtest_failed(d, dqp, "icount mismatch",			be64_to_cpu(dqp->q_core.d_icount),			d->d_icount, 0);		err++;	}	if (be64_to_cpu(dqp->q_core.d_bcount) != d->d_bcount) {		xfs_qm_dqtest_failed(d, dqp, "bcount mismatch",			be64_to_cpu(dqp->q_core.d_bcount),			d->d_bcount, 0);		err++;	}	if (dqp->q_core.d_blk_softlimit &&	    be64_to_cpu(dqp->q_core.d_bcount) >=	    be64_to_cpu(dqp->q_core.d_blk_softlimit)) {		if (!dqp->q_core.d_btimer && dqp->q_core.d_id) {			cmn_err(CE_DEBUG,				"%d [%s] [0x%p] BLK TIMER NOT STARTED",				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);			err++;		}	}	if (dqp->q_core.d_ino_softlimit &&	    be64_to_cpu(dqp->q_core.d_icount) >=	    be64_to_cpu(dqp->q_core.d_ino_softlimit)) {		if (!dqp->q_core.d_itimer && dqp->q_core.d_id) {			cmn_err(CE_DEBUG,				"%d [%s] [0x%p] INO TIMER NOT STARTED",				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);			err++;		}	}#ifdef QUOTADEBUG	if (!err) {		cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",			d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);	}#endif	return (err);}STATIC voidxfs_dqtest_cmp(	xfs_dqtest_t	*d){	xfs_dquot_t	*dqp;	int		error;	/* xfs_qm_dqtest_print(d); */	if ((error = xfs_qm_dqget(d->q_mount, NULL, d->d_id, d->dq_flags, 0,				 &dqp))) {		xfs_qm_dqtest_failed(d, NULL, "dqget failed", 0, 0, error);		return;	}	xfs_dqtest_cmp2(d, dqp);	xfs_qm_dqput(dqp);}STATIC intxfs_qm_internalqcheck_dqget(	xfs_mount_t	*mp,	xfs_dqid_t	id,	uint		type,	xfs_dqtest_t	**O_dq){	xfs_dqtest_t	*d;	xfs_dqhash_t	*h;	h = DQTEST_HASH(mp, id, type);	for (d = (xfs_dqtest_t *) h->qh_next; d != NULL;	     d = (xfs_dqtest_t *) d->HL_NEXT) {		/* DQTEST_LIST_PRINT(h, HL_NEXT, "@@@@@ dqtestlist @@@@@"); */		if (d->d_id == id && mp == d->q_mount) {			*O_dq = d;			return (0);		}	}	d = kmem_zalloc(sizeof(xfs_dqtest_t), KM_SLEEP);	d->dq_flags = type;	d->d_id = id;	d->q_mount = mp;	d->q_hash = h;	xfs_qm_hashinsert(h, d);	*O_dq = d;	return (0);}STATIC voidxfs_qm_internalqcheck_get_dquots(	xfs_mount_t	*mp,	xfs_dqid_t	uid,	xfs_dqid_t	projid,	xfs_dqid_t	gid,	xfs_dqtest_t	**ud,	xfs_dqtest_t	**gd){	if (XFS_IS_UQUOTA_ON(mp))		xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);	if (XFS_IS_GQUOTA_ON(mp))		xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);	else if (XFS_IS_PQUOTA_ON(mp))		xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);}STATIC voidxfs_qm_internalqcheck_dqadjust(	xfs_inode_t		*ip,	xfs_dqtest_t		*d){	d->d_icount++;	d->d_bcount += (xfs_qcnt_t)ip->i_d.di_nblocks;}STATIC intxfs_qm_internalqcheck_adjust(	xfs_mount_t	*mp,		/* mount point for filesystem */	xfs_ino_t	ino,		/* inode number to get data for */	void		__user *buffer,	/* not used */	int		ubsize,		/* not used */	void		*private_data,	/* not used */	xfs_daddr_t	bno,		/* starting block of inode cluster */	int		*ubused,	/* not used */	void		*dip,		/* not used */	int		*res)		/* bulkstat result code */{	xfs_inode_t		*ip;	xfs_dqtest_t		*ud, *gd;	uint			lock_flags;	boolean_t		ipreleased;	int			error;	ASSERT(XFS_IS_QUOTA_RUNNING(mp));	if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {		*res = BULKSTAT_RV_NOTHING;		qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n",			(unsigned long long) ino,			(unsigned long long) mp->m_sb.sb_uquotino,			(unsigned long long) mp->m_sb.sb_gquotino);		return XFS_ERROR(EINVAL);	}	ipreleased = B_FALSE; again:	lock_flags = XFS_ILOCK_SHARED;	if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) {		*res = BULKSTAT_RV_NOTHING;		return (error);	}	if (ip->i_d.di_mode == 0) {		xfs_iput_new(ip, lock_flags);		*res = BULKSTAT_RV_NOTHING;		return XFS_ERROR(ENOENT);	}	/*	 * This inode can have blocks after eof which can get released	 * when we send it to inactive. Since we don't check the dquot	 * until the after all our calculations are done, we must get rid	 * of those now.	 */	if (! ipreleased) {		xfs_iput(ip, lock_flags);		ipreleased = B_TRUE;		goto again;	}	xfs_qm_internalqcheck_get_dquots(mp,					(xfs_dqid_t) ip->i_d.di_uid,					(xfs_dqid_t) ip->i_d.di_projid,					(xfs_dqid_t) ip->i_d.di_gid,					&ud, &gd);	if (XFS_IS_UQUOTA_ON(mp)) {		ASSERT(ud);		xfs_qm_internalqcheck_dqadjust(ip, ud);	}	if (XFS_IS_OQUOTA_ON(mp)) {		ASSERT(gd);		xfs_qm_internalqcheck_dqadjust(ip, gd);	}	xfs_iput(ip, lock_flags);	*res = BULKSTAT_RV_DIDONE;	return (0);}/* PRIVATE, debugging */intxfs_qm_internalqcheck(	xfs_mount_t	*mp){	xfs_ino_t	lastino;	int		done, count;	int		i;	xfs_dqtest_t	*d, *e;	xfs_dqhash_t	*h1;	int		error;	lastino = 0;	qmtest_hashmask = 32;	count = 5;	done = 0;	qmtest_nfails = 0;	if (! XFS_IS_QUOTA_ON(mp))		return XFS_ERROR(ESRCH);	xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);	XFS_bflush(mp->m_ddev_targp);	xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);	XFS_bflush(mp->m_ddev_targp);	mutex_lock(&qcheck_lock, PINOD);	/* There should be absolutely no quota activity while this	   is going on. */	qmtest_udqtab = kmem_zalloc(qmtest_hashmask *				    sizeof(xfs_dqhash_t), KM_SLEEP);	qmtest_gdqtab = kmem_zalloc(qmtest_hashmask *				    sizeof(xfs_dqhash_t), KM_SLEEP);	do {		/*		 * Iterate thru all the inodes in the file system,		 * adjusting the corresponding dquot counters		 */		if ((error = xfs_bulkstat(mp, &lastino, &count,				 xfs_qm_internalqcheck_adjust, NULL,				 0, NULL, BULKSTAT_FG_IGET, &done))) {			break;		}	} while (! done);	if (error) {		cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);	}	cmn_err(CE_DEBUG, "Checking results against system dquots");	for (i = 0; i < qmtest_hashmask; i++) {		h1 = &qmtest_udqtab[i];		for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {			xfs_dqtest_cmp(d);			e = (xfs_dqtest_t *) d->HL_NEXT;			kmem_free(d, sizeof(xfs_dqtest_t));			d = e;		}		h1 = &qmtest_gdqtab[i];		for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {			xfs_dqtest_cmp(d);			e = (xfs_dqtest_t *) d->HL_NEXT;			kmem_free(d, sizeof(xfs_dqtest_t));			d = e;		}	}	if (qmtest_nfails) {		cmn_err(CE_DEBUG, "******** quotacheck failed  ********");		cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails);	} else {		cmn_err(CE_DEBUG, "******** quotacheck successful! ********");	}	kmem_free(qmtest_udqtab, qmtest_hashmask * sizeof(xfs_dqhash_t));	kmem_free(qmtest_gdqtab, qmtest_hashmask * sizeof(xfs_dqhash_t));	mutex_unlock(&qcheck_lock);	return (qmtest_nfails);}#endif /* DEBUG */

⌨️ 快捷键说明

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