/*
 * Increment or reset warnings of a given dquot.
 */
int
xfs_qm_dqwarn(
	xfs_disk_dquot_t	*d,
	uint			flags)
{
	int	warned;

	/*
	 * root's limits are not real limits.
	 */
	if (INT_ISZERO(d->d_id, ARCH_CONVERT))
		return (0);

	warned = 0;
	if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
	    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
	     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
		if (flags & XFS_QMOPT_DOWARN) {
			INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
			warned++;
		}
	} else {
		if (INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
		     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
			INT_ZERO(d->d_bwarns, ARCH_CONVERT);
		}
	}

	if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
	    (INT_GET(d->d_icount, ARCH_CONVERT) >=
	     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
		if (flags & XFS_QMOPT_DOWARN) {
			INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
			warned++;
		}
	} else {
		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT)) ||
		    (INT_GET(d->d_icount, ARCH_CONVERT) <
		     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
			INT_ZERO(d->d_iwarns, ARCH_CONVERT);
		}
	}
#ifdef QUOTADEBUG
	if (INT_GET(d->d_iwarns, ARCH_CONVERT))
		cmn_err(CE_DEBUG,
			"--------@@Inode warnings running : %Lu >= %Lu",
			INT_GET(d->d_icount, ARCH_CONVERT),
			INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
	if (INT_GET(d->d_bwarns, ARCH_CONVERT))
		cmn_err(CE_DEBUG,
			"--------@@Blks warnings running : %Lu >= %Lu",
			INT_GET(d->d_bcount, ARCH_CONVERT),
			INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
#endif
	return (warned);
}
Exemple #2
0
/*
 * Check the limits and timers of a dquot and start or reset timers
 * if necessary.
 * This gets called even when quota enforcement is OFF, which makes our
 * life a little less complicated. (We just don't reject any quota
 * reservations in that case, when enforcement is off).
 * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
 * enforcement's off.
 * In contrast, warnings are a little different in that they don't
 * 'automatically' get started when limits get exceeded.
 */
void
xfs_qm_adjust_dqtimers(
	xfs_mount_t		*mp,
	xfs_disk_dquot_t	*d)
{
	/*
	 * The dquot had better be locked. We are modifying it here.
	 */

	/*
	 * root's limits are not real limits.
	 */
	if (INT_ISZERO(d->d_id, ARCH_CONVERT))
		return;

#ifdef QUOTADEBUG
	if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
	if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
#endif
	if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
		if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
		    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
			INT_SET(d->d_btimer, ARCH_CONVERT, CURRENT_TIME + XFS_QI_BTIMELIMIT(mp));
		}
	} else {
		if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
		    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
			INT_ZERO(d->d_btimer, ARCH_CONVERT);
		}
	}

	if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
		if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
		    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
			INT_SET(d->d_itimer, ARCH_CONVERT, CURRENT_TIME + XFS_QI_ITIMELIMIT(mp));
		}
	} else {
		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
		    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
			INT_ZERO(d->d_itimer, ARCH_CONVERT);
		}
	}
}
/*
 * Check the limits and timers of a dquot and start or reset timers
 * if necessary.
 * This gets called even when quota enforcement is OFF, which makes our
 * life a little less complicated. (We just don't reject any quota
 * reservations in that case, when enforcement is off).
 * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
 * enforcement's off.
 * In contrast, warnings are a little different in that they don't
 * 'automatically' get started when limits get exceeded.
 */
void
xfs_qm_adjust_dqtimers(
	xfs_mount_t		*mp,
	xfs_disk_dquot_t	*d)
{
	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));

#ifdef QUOTADEBUG
	if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <=
			INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
	if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <=
			INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
	if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT))
		ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
			INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
#endif
	if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
		if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
		    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
			INT_SET(d->d_btimer, ARCH_CONVERT,
				get_seconds() + XFS_QI_BTIMELIMIT(mp));
		}
	} else {
		if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
		    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
			INT_ZERO(d->d_btimer, ARCH_CONVERT);
		}
	}

	if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
		if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
				INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
		    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
			INT_SET(d->d_itimer, ARCH_CONVERT,
				get_seconds() + XFS_QI_ITIMELIMIT(mp));
		}
	} else {
		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_icount, ARCH_CONVERT) <
				INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
		    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_icount, ARCH_CONVERT) <
				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
			INT_ZERO(d->d_itimer, ARCH_CONVERT);
		}
	}

	if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
		if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
		    (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) &&
		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
			INT_SET(d->d_rtbtimer, ARCH_CONVERT,
				get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
		}
	} else {
		if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
		    (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
			INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
		}
	}
}
Exemple #4
0
/*
 * Writes a modified inode's changes out to the inode's on disk home.
 * Originally based on xfs_iflush_int() from xfs_inode.c in the kernel.
 */
int
libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp)
{
	xfs_inode_log_item_t	*iip;
	xfs_dinode_t		*dip;
	xfs_mount_t		*mp;

	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
		ip->i_d.di_nextents > ip->i_df.if_ext_max);

	iip = ip->i_itemp;
	mp = ip->i_mount;

	/* set *dip = inode's place in the buffer */
	dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_boffset);

#ifdef DEBUG
	ASSERT(ip->i_d.di_magic == XFS_DINODE_MAGIC);
	if ((ip->i_d.di_mode & IFMT) == IFREG) {
		ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) ||
			(ip->i_d.di_format == XFS_DINODE_FMT_BTREE) );
	}
	else if ((ip->i_d.di_mode & IFMT) == IFDIR) {
		ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) ||
			(ip->i_d.di_format == XFS_DINODE_FMT_BTREE)   ||
			(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) );
	}
	ASSERT(ip->i_d.di_nextents+ip->i_d.di_anextents <= ip->i_d.di_nblocks);
	ASSERT(ip->i_d.di_forkoff <= mp->m_sb.sb_inodesize);
#endif

	/*
	 * Copy the dirty parts of the inode into the on-disk
	 * inode.  We always copy out the core of the inode,
	 * because if the inode is dirty at all the core must
	 * be.
	 */
	xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), -1,
				ARCH_CONVERT);
	/*
	 * If this is really an old format inode and the superblock version
	 * has not been updated to support only new format inodes, then
	 * convert back to the old inode format.  If the superblock version
	 * has been updated, then make the conversion permanent.
	 */
	ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1 ||
		XFS_SB_VERSION_HASNLINK(&mp->m_sb));
	if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
		if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
			/*
			 * Convert it back.
			 */
			ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
			INT_SET(dip->di_core.di_onlink, ARCH_CONVERT,
				ip->i_d.di_nlink);
		} else {
			/*
			 * The superblock version has already been bumped,
			 * so just make the conversion to the new inode
			 * format permanent.
			 */
			ip->i_d.di_version = XFS_DINODE_VERSION_2;
			INT_SET(dip->di_core.di_version, ARCH_CONVERT,
				XFS_DINODE_VERSION_2);
			ip->i_d.di_onlink = 0;
			INT_ZERO(dip->di_core.di_onlink, ARCH_CONVERT);
			bzero(&(ip->i_d.di_pad[0]), sizeof(ip->i_d.di_pad));
			bzero(&(dip->di_core.di_pad[0]),
				sizeof(dip->di_core.di_pad));
			ASSERT(ip->i_d.di_projid == 0);
		}
	}

	if (xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp) == EFSCORRUPTED)
		return EFSCORRUPTED;
	if (XFS_IFORK_Q(ip)) {
		/* The only error from xfs_iflush_fork is on the data fork. */
		xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
	}

	return 0;
}