Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d892d586 authored by Chandra Seetharaman's avatar Chandra Seetharaman Committed by Ben Myers
Browse files

xfs: Start using pquotaino from the superblock.



Start using pquotino and define a macro to check if the
superblock has pquotino.

Keep backward compatibilty by alowing mount of older superblock
with no separate pquota inode.

Signed-off-by: default avatarChandra Seetharaman <sekharan@us.ibm.com>
Reviewed-by: default avatarBen Myers <bpm@sgi.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 01026297
Loading
Loading
Loading
Loading
+54 −8
Original line number Original line Diff line number Diff line
@@ -336,14 +336,6 @@ xfs_mount_validate_sb(
		return XFS_ERROR(EWRONGFS);
		return XFS_ERROR(EWRONGFS);
	}
	}


	if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
			(sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
				XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
		xfs_notice(mp,
"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
		return XFS_ERROR(EFSCORRUPTED);
	}

	/*
	/*
	 * Version 5 superblock feature mask validation. Reject combinations the
	 * Version 5 superblock feature mask validation. Reject combinations the
	 * kernel cannot support up front before checking anything else. For
	 * kernel cannot support up front before checking anything else. For
@@ -387,6 +379,19 @@ xfs_mount_validate_sb(
		}
		}
	}
	}


	if (xfs_sb_version_has_pquotino(sbp)) {
		if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
			xfs_notice(mp,
			   "Version 5 of Super block has XFS_OQUOTA bits.\n");
			return XFS_ERROR(EFSCORRUPTED);
		}
	} else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
				XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
			xfs_notice(mp,
"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n");
			return XFS_ERROR(EFSCORRUPTED);
	}

	if (unlikely(
	if (unlikely(
	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
		xfs_warn(mp,
		xfs_warn(mp,
@@ -590,6 +595,13 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
	if (sbp->sb_pquotino == 0)
	if (sbp->sb_pquotino == 0)
		sbp->sb_pquotino = NULLFSINO;
		sbp->sb_pquotino = NULLFSINO;


	/*
	 * We need to do these manipilations only if we are working
	 * with an older version of on-disk superblock.
	 */
	if (xfs_sb_version_has_pquotino(sbp))
		return;

	if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
	if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
		sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
		sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
					XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
					XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
@@ -597,6 +609,18 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
		sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
		sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
					XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
					XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
	sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
	sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);

	if (sbp->sb_qflags & XFS_PQUOTA_ACCT)  {
		/*
		 * In older version of superblock, on-disk superblock only
		 * has sb_gquotino, and in-core superblock has both sb_gquotino
		 * and sb_pquotino. But, only one of them is supported at any
		 * point of time. So, if PQUOTA is set in disk superblock,
		 * copy over sb_gquotino to sb_pquotino.
		 */
		sbp->sb_pquotino = sbp->sb_gquotino;
		sbp->sb_gquotino = NULLFSINO;
	}
}
}


void
void
@@ -668,6 +692,13 @@ xfs_sb_quota_to_disk(
{
{
	__uint16_t	qflags = from->sb_qflags;
	__uint16_t	qflags = from->sb_qflags;


	/*
	 * We need to do these manipilations only if we are working
	 * with an older version of on-disk superblock.
	 */
	if (xfs_sb_version_has_pquotino(from))
		return;

	if (*fields & XFS_SB_QFLAGS) {
	if (*fields & XFS_SB_QFLAGS) {
		/*
		/*
		 * The in-core version of sb_qflags do not have
		 * The in-core version of sb_qflags do not have
@@ -687,6 +718,21 @@ xfs_sb_quota_to_disk(
		to->sb_qflags = cpu_to_be16(qflags);
		to->sb_qflags = cpu_to_be16(qflags);
		*fields &= ~XFS_SB_QFLAGS;
		*fields &= ~XFS_SB_QFLAGS;
	}
	}

	/*
	 * GQUOTINO and PQUOTINO cannot be used together in versions
	 * of superblock that do not have pquotino. from->sb_flags
	 * tells us which quota is active and should be copied to
	 * disk.
	 */
	if ((*fields & XFS_SB_GQUOTINO) &&
				(from->sb_qflags & XFS_GQUOTA_ACCT))
		to->sb_gquotino = cpu_to_be64(from->sb_gquotino);
	else if ((*fields & XFS_SB_PQUOTINO) &&
				(from->sb_qflags & XFS_PQUOTA_ACCT))
		to->sb_gquotino = cpu_to_be64(from->sb_pquotino);

	*fields &= ~(XFS_SB_PQUOTINO | XFS_SB_GQUOTINO);
}
}


/*
/*
+54 −18
Original line number Original line Diff line number Diff line
@@ -834,6 +834,36 @@ xfs_qm_qino_alloc(
	int		error;
	int		error;
	int		committed;
	int		committed;


	*ip = NULL;
	/*
	 * With superblock that doesn't have separate pquotino, we
	 * share an inode between gquota and pquota. If the on-disk
	 * superblock has GQUOTA and the filesystem is now mounted
	 * with PQUOTA, just use sb_gquotino for sb_pquotino and
	 * vice-versa.
	 */
	if (!xfs_sb_version_has_pquotino(&mp->m_sb) &&
			(flags & (XFS_QMOPT_PQUOTA|XFS_QMOPT_GQUOTA))) {
		xfs_ino_t ino = NULLFSINO;

		if ((flags & XFS_QMOPT_PQUOTA) &&
			     (mp->m_sb.sb_gquotino != NULLFSINO)) {
			ino = mp->m_sb.sb_gquotino;
			ASSERT(mp->m_sb.sb_pquotino == NULLFSINO);
		} else if ((flags & XFS_QMOPT_GQUOTA) &&
			     (mp->m_sb.sb_pquotino != NULLFSINO)) {
			ino = mp->m_sb.sb_pquotino;
			ASSERT(mp->m_sb.sb_gquotino == NULLFSINO);
		}
		if (ino != NULLFSINO) {
			error = xfs_iget(mp, NULL, ino, 0, 0, ip);
			if (error)
				return error;
			mp->m_sb.sb_gquotino = NULLFSINO;
			mp->m_sb.sb_pquotino = NULLFSINO;
		}
	}

	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
	if ((error = xfs_trans_reserve(tp,
	if ((error = xfs_trans_reserve(tp,
				      XFS_QM_QINOCREATE_SPACE_RES(mp),
				      XFS_QM_QINOCREATE_SPACE_RES(mp),
@@ -844,12 +874,15 @@ xfs_qm_qino_alloc(
		return error;
		return error;
	}
	}


	error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
	if (!*ip) {
		error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip,
								&committed);
		if (error) {
		if (error) {
			xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
			xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
					 XFS_TRANS_ABORT);
					 XFS_TRANS_ABORT);
			return error;
			return error;
		}
		}
	}


	/*
	/*
	 * Make the changes in the superblock, and log those too.
	 * Make the changes in the superblock, and log those too.
@@ -860,21 +893,25 @@ xfs_qm_qino_alloc(
	if (flags & XFS_QMOPT_SBVERSION) {
	if (flags & XFS_QMOPT_SBVERSION) {
		ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
		ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
		ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
		ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
				   XFS_SB_GQUOTINO | XFS_SB_QFLAGS)) ==
			XFS_SB_GQUOTINO | XFS_SB_PQUOTINO | XFS_SB_QFLAGS)) ==
				(XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
				(XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
			XFS_SB_GQUOTINO | XFS_SB_QFLAGS));
				 XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |
				 XFS_SB_QFLAGS));


		xfs_sb_version_addquota(&mp->m_sb);
		xfs_sb_version_addquota(&mp->m_sb);
		mp->m_sb.sb_uquotino = NULLFSINO;
		mp->m_sb.sb_uquotino = NULLFSINO;
		mp->m_sb.sb_gquotino = NULLFSINO;
		mp->m_sb.sb_gquotino = NULLFSINO;
		mp->m_sb.sb_pquotino = NULLFSINO;


		/* qflags will get updated _after_ quotacheck */
		/* qflags will get updated fully _after_ quotacheck */
		mp->m_sb.sb_qflags = 0;
		mp->m_sb.sb_qflags = mp->m_qflags & XFS_ALL_QUOTA_ACCT;
	}
	}
	if (flags & XFS_QMOPT_UQUOTA)
	if (flags & XFS_QMOPT_UQUOTA)
		mp->m_sb.sb_uquotino = (*ip)->i_ino;
		mp->m_sb.sb_uquotino = (*ip)->i_ino;
	else
	else if (flags & XFS_QMOPT_GQUOTA)
		mp->m_sb.sb_gquotino = (*ip)->i_ino;
		mp->m_sb.sb_gquotino = (*ip)->i_ino;
	else
		mp->m_sb.sb_pquotino = (*ip)->i_ino;
	spin_unlock(&mp->m_sb_lock);
	spin_unlock(&mp->m_sb_lock);
	xfs_mod_sb(tp, sbfields);
	xfs_mod_sb(tp, sbfields);


@@ -1484,11 +1521,10 @@ xfs_qm_init_quotainos(
			if (error)
			if (error)
				goto error_rele;
				goto error_rele;
		}
		}
		/* XXX: Use gquotino for now */
		if (XFS_IS_PQUOTA_ON(mp) &&
		if (XFS_IS_PQUOTA_ON(mp) &&
		    mp->m_sb.sb_gquotino != NULLFSINO) {
		    mp->m_sb.sb_pquotino != NULLFSINO) {
			ASSERT(mp->m_sb.sb_gquotino > 0);
			ASSERT(mp->m_sb.sb_pquotino > 0);
			error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
			error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
					     0, 0, &pip);
					     0, 0, &pip);
			if (error)
			if (error)
				goto error_rele;
				goto error_rele;
@@ -1496,7 +1532,8 @@ xfs_qm_init_quotainos(
	} else {
	} else {
		flags |= XFS_QMOPT_SBVERSION;
		flags |= XFS_QMOPT_SBVERSION;
		sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
		sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
			    XFS_SB_GQUOTINO | XFS_SB_QFLAGS);
			    XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |
			    XFS_SB_QFLAGS);
	}
	}


	/*
	/*
@@ -1524,9 +1561,8 @@ xfs_qm_init_quotainos(
		flags &= ~XFS_QMOPT_SBVERSION;
		flags &= ~XFS_QMOPT_SBVERSION;
	}
	}
	if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
	if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
		/* XXX: Use XFS_SB_GQUOTINO for now */
		error = xfs_qm_qino_alloc(mp, &pip,
		error = xfs_qm_qino_alloc(mp, &pip,
					  sbflags | XFS_SB_GQUOTINO,
					  sbflags | XFS_SB_PQUOTINO,
					  flags | XFS_QMOPT_PQUOTA);
					  flags | XFS_QMOPT_PQUOTA);
		if (error)
		if (error)
			goto error_rele;
			goto error_rele;
+30 −5
Original line number Original line Diff line number Diff line
@@ -296,8 +296,10 @@ xfs_qm_scall_trunc_qfiles(


	if (flags & XFS_DQ_USER)
	if (flags & XFS_DQ_USER)
		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
	if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ))
	if (flags & XFS_DQ_GROUP)
		error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
		error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
	if (flags & XFS_DQ_PROJ)
		error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);


	return error ? error : error2;
	return error ? error : error2;
}
}
@@ -413,8 +415,10 @@ xfs_qm_scall_getqstat(
	struct xfs_quotainfo	*q = mp->m_quotainfo;
	struct xfs_quotainfo	*q = mp->m_quotainfo;
	struct xfs_inode	*uip = NULL;
	struct xfs_inode	*uip = NULL;
	struct xfs_inode	*gip = NULL;
	struct xfs_inode	*gip = NULL;
	struct xfs_inode	*pip = NULL;
	bool                    tempuqip = false;
	bool                    tempuqip = false;
	bool                    tempgqip = false;
	bool                    tempgqip = false;
	bool                    temppqip = false;


	memset(out, 0, sizeof(fs_quota_stat_t));
	memset(out, 0, sizeof(fs_quota_stat_t));


@@ -424,16 +428,14 @@ xfs_qm_scall_getqstat(
		out->qs_gquota.qfs_ino = NULLFSINO;
		out->qs_gquota.qfs_ino = NULLFSINO;
		return (0);
		return (0);
	}
	}

	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
							(XFS_ALL_QUOTA_ACCT|
							(XFS_ALL_QUOTA_ACCT|
							 XFS_ALL_QUOTA_ENFD));
							 XFS_ALL_QUOTA_ENFD));
	out->qs_pad = 0;
	out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
	out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;

	if (q) {
	if (q) {
		uip = q->qi_uquotaip;
		uip = q->qi_uquotaip;
		gip = q->qi_gquotaip;
		gip = q->qi_gquotaip;
		pip = q->qi_pquotaip;
	}
	}
	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
@@ -445,18 +447,41 @@ xfs_qm_scall_getqstat(
					0, 0, &gip) == 0)
					0, 0, &gip) == 0)
			tempgqip = true;
			tempgqip = true;
	}
	}
	/*
	 * Q_XGETQSTAT doesn't have room for both group and project quotas.
	 * So, allow the project quota values to be copied out only if
	 * there is no group quota information available.
	 */
	if (!gip) {
		if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
			if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
						0, 0, &pip) == 0)
				temppqip = true;
		}
	} else
		pip = NULL;
	if (uip) {
	if (uip) {
		out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
		if (tempuqip)
		if (tempuqip)
			IRELE(uip);
			IRELE(uip);
	}
	}

	if (gip) {
	if (gip) {
		out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
		if (tempgqip)
		if (tempgqip)
			IRELE(gip);
			IRELE(gip);
	}
	}
	if (pip) {
		out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
		out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
		out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
		if (temppqip)
			IRELE(pip);
	}
	if (q) {
	if (q) {
		out->qs_incoredqs = q->qi_dquots;
		out->qs_incoredqs = q->qi_dquots;
		out->qs_btimelimit = q->qi_btimelimit;
		out->qs_btimelimit = q->qi_btimelimit;
+10 −3
Original line number Original line Diff line number Diff line
@@ -618,16 +618,23 @@ xfs_sb_has_incompat_log_feature(
	return (sbp->sb_features_log_incompat & feature) != 0;
	return (sbp->sb_features_log_incompat & feature) != 0;
}
}


static inline bool
static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp)
xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
{
{
	return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino);
	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
}
}


/*
/*
 * end of superblock version macros
 * end of superblock version macros
 */
 */


static inline bool
xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
{
	return (ino == sbp->sb_uquotino ||
		ino == sbp->sb_gquotino ||
		ino == sbp->sb_pquotino);
}

#define XFS_SB_DADDR		((xfs_daddr_t)0) /* daddr in filesystem/ag */
#define XFS_SB_DADDR		((xfs_daddr_t)0) /* daddr in filesystem/ag */
#define	XFS_SB_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
#define	XFS_SB_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
#define XFS_BUF_TO_SBP(bp)	((xfs_dsb_t *)((bp)->b_addr))
#define XFS_BUF_TO_SBP(bp)	((xfs_dsb_t *)((bp)->b_addr))
+10 −9
Original line number Original line Diff line number Diff line
@@ -421,12 +421,6 @@ xfs_parseargs(
	}
	}
#endif
#endif


	if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
	    (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) {
		xfs_warn(mp, "cannot mount with both project and group quota");
		return EINVAL;
	}

	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
		xfs_warn(mp, "sunit and swidth must be specified together");
		xfs_warn(mp, "sunit and swidth must be specified together");
		return EINVAL;
		return EINVAL;
@@ -556,14 +550,13 @@ xfs_showargs(
	else if (mp->m_qflags & XFS_UQUOTA_ACCT)
	else if (mp->m_qflags & XFS_UQUOTA_ACCT)
		seq_puts(m, "," MNTOPT_UQUOTANOENF);
		seq_puts(m, "," MNTOPT_UQUOTANOENF);


	/* Either project or group quotas can be active, not both */

	if (mp->m_qflags & XFS_PQUOTA_ACCT) {
	if (mp->m_qflags & XFS_PQUOTA_ACCT) {
		if (mp->m_qflags & XFS_PQUOTA_ENFD)
		if (mp->m_qflags & XFS_PQUOTA_ENFD)
			seq_puts(m, "," MNTOPT_PRJQUOTA);
			seq_puts(m, "," MNTOPT_PRJQUOTA);
		else
		else
			seq_puts(m, "," MNTOPT_PQUOTANOENF);
			seq_puts(m, "," MNTOPT_PQUOTANOENF);
	} else if (mp->m_qflags & XFS_GQUOTA_ACCT) {
	}
	if (mp->m_qflags & XFS_GQUOTA_ACCT) {
		if (mp->m_qflags & XFS_GQUOTA_ENFD)
		if (mp->m_qflags & XFS_GQUOTA_ENFD)
			seq_puts(m, "," MNTOPT_GRPQUOTA);
			seq_puts(m, "," MNTOPT_GRPQUOTA);
		else
		else
@@ -1396,6 +1389,14 @@ xfs_finish_flags(
		return XFS_ERROR(EROFS);
		return XFS_ERROR(EROFS);
	}
	}


	if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
	    (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
	    !xfs_sb_version_has_pquotino(&mp->m_sb)) {
		xfs_warn(mp,
		  "Super block does not support project and group quota together");
		return XFS_ERROR(EINVAL);
	}

	return 0;
	return 0;
}
}