All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <david@fromorbit.com>
To: xfs@oss.sgi.com
Subject: [PATCH 04/30] xfs: split dquot buffer operations out
Date: Wed, 30 Oct 2013 15:30:55 +1100	[thread overview]
Message-ID: <1383107481-28937-5-git-send-email-david@fromorbit.com> (raw)
In-Reply-To: <1383107481-28937-1-git-send-email-david@fromorbit.com>

From: Dave Chinner <dchinner@redhat.com>

Parts of userspace want to be able to read and modify dquot buffers
(e.g. xfs_db) so we need to split out the reading and writing of
these buffers so it is easy to shared code with libxfs in userspace.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 include/libxfs.h       |   9 ++
 libxfs/Makefile        |   1 +
 libxfs/xfs_dquot_buf.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 283 insertions(+)
 create mode 100644 libxfs/xfs_dquot_buf.c

diff --git a/include/libxfs.h b/include/libxfs.h
index 835ba37..f10ab59 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -216,6 +216,15 @@ typedef struct xfs_mount {
 	xfs_dablk_t		m_dirdatablk;	/* blockno of dir data v2 */
 	xfs_dablk_t		m_dirleafblk;	/* blockno of dir non-data v2 */
 	xfs_dablk_t		m_dirfreeblk;	/* blockno of dirfreeindex v2 */
+
+	/*
+	 * anonymous struct to allow xfs_dquot_buf.c to compile.
+	 * Pointer is always null in userspace, so code does not use it at all
+	 */
+	struct {
+		int	qi_dqperchunk;
+	}			*m_quotainfo;
+
 } xfs_mount_t;
 
 /*
diff --git a/libxfs/Makefile b/libxfs/Makefile
index f0cbae3..4522218 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -29,6 +29,7 @@ CFILES = cache.c \
 	xfs_dir2_leaf.c \
 	xfs_dir2_node.c \
 	xfs_dir2_sf.c \
+	xfs_dquot_buf.c \
 	xfs_ialloc.c \
 	xfs_inode_buf.c \
 	xfs_inode_fork.c \
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
new file mode 100644
index 0000000..620d9d3
--- /dev/null
+++ b/libxfs/xfs_dquot_buf.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
+ * Copyright (c) 2013 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "xfs.h"
+
+int
+xfs_calc_dquots_per_chunk(
+	struct xfs_mount	*mp,
+	unsigned int		nbblks)	/* basic block units */
+{
+	unsigned int	ndquots;
+
+	ASSERT(nbblks > 0);
+	ndquots = BBTOB(nbblks);
+	do_div(ndquots, sizeof(xfs_dqblk_t));
+
+	return ndquots;
+}
+
+/*
+ * Do some primitive error checking on ondisk dquot data structures.
+ */
+int
+xfs_dqcheck(
+	struct xfs_mount *mp,
+	xfs_disk_dquot_t *ddq,
+	xfs_dqid_t	 id,
+	uint		 type,	  /* used only when IO_dorepair is true */
+	uint		 flags,
+	char		 *str)
+{
+	xfs_dqblk_t	 *d = (xfs_dqblk_t *)ddq;
+	int		errs = 0;
+
+	/*
+	 * We can encounter an uninitialized dquot buffer for 2 reasons:
+	 * 1. If we crash while deleting the quotainode(s), and those blks got
+	 *    used for user data. This is because we take the path of regular
+	 *    file deletion; however, the size field of quotainodes is never
+	 *    updated, so all the tricks that we play in itruncate_finish
+	 *    don't quite matter.
+	 *
+	 * 2. We don't play the quota buffers when there's a quotaoff logitem.
+	 *    But the allocation will be replayed so we'll end up with an
+	 *    uninitialized quota block.
+	 *
+	 * This is all fine; things are still consistent, and we haven't lost
+	 * any quota information. Just don't complain about bad dquot blks.
+	 */
+	if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) {
+		if (flags & XFS_QMOPT_DOWARN)
+			xfs_alert(mp,
+			"%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
+			str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
+		errs++;
+	}
+	if (ddq->d_version != XFS_DQUOT_VERSION) {
+		if (flags & XFS_QMOPT_DOWARN)
+			xfs_alert(mp,
+			"%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
+			str, id, ddq->d_version, XFS_DQUOT_VERSION);
+		errs++;
+	}
+
+	if (ddq->d_flags != XFS_DQ_USER &&
+	    ddq->d_flags != XFS_DQ_PROJ &&
+	    ddq->d_flags != XFS_DQ_GROUP) {
+		if (flags & XFS_QMOPT_DOWARN)
+			xfs_alert(mp,
+			"%s : XFS dquot ID 0x%x, unknown flags 0x%x",
+			str, id, ddq->d_flags);
+		errs++;
+	}
+
+	if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
+		if (flags & XFS_QMOPT_DOWARN)
+			xfs_alert(mp,
+			"%s : ondisk-dquot 0x%p, ID mismatch: "
+			"0x%x expected, found id 0x%x",
+			str, ddq, id, be32_to_cpu(ddq->d_id));
+		errs++;
+	}
+
+	if (!errs && ddq->d_id) {
+		if (ddq->d_blk_softlimit &&
+		    be64_to_cpu(ddq->d_bcount) >
+				be64_to_cpu(ddq->d_blk_softlimit)) {
+			if (!ddq->d_btimer) {
+				if (flags & XFS_QMOPT_DOWARN)
+					xfs_alert(mp,
+			"%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
+					str, (int)be32_to_cpu(ddq->d_id), ddq);
+				errs++;
+			}
+		}
+		if (ddq->d_ino_softlimit &&
+		    be64_to_cpu(ddq->d_icount) >
+				be64_to_cpu(ddq->d_ino_softlimit)) {
+			if (!ddq->d_itimer) {
+				if (flags & XFS_QMOPT_DOWARN)
+					xfs_alert(mp,
+			"%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
+					str, (int)be32_to_cpu(ddq->d_id), ddq);
+				errs++;
+			}
+		}
+		if (ddq->d_rtb_softlimit &&
+		    be64_to_cpu(ddq->d_rtbcount) >
+				be64_to_cpu(ddq->d_rtb_softlimit)) {
+			if (!ddq->d_rtbtimer) {
+				if (flags & XFS_QMOPT_DOWARN)
+					xfs_alert(mp,
+			"%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
+					str, (int)be32_to_cpu(ddq->d_id), ddq);
+				errs++;
+			}
+		}
+	}
+
+	if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
+		return errs;
+
+	if (flags & XFS_QMOPT_DOWARN)
+		xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
+
+	/*
+	 * Typically, a repair is only requested by quotacheck.
+	 */
+	ASSERT(id != -1);
+	ASSERT(flags & XFS_QMOPT_DQREPAIR);
+	memset(d, 0, sizeof(xfs_dqblk_t));
+
+	d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
+	d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
+	d->dd_diskdq.d_flags = type;
+	d->dd_diskdq.d_id = cpu_to_be32(id);
+
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
+		xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
+				 XFS_DQUOT_CRC_OFF);
+	}
+
+	return errs;
+}
+
+STATIC bool
+xfs_dquot_buf_verify_crc(
+	struct xfs_mount	*mp,
+	struct xfs_buf		*bp)
+{
+	struct xfs_dqblk	*d = (struct xfs_dqblk *)bp->b_addr;
+	int			ndquots;
+	int			i;
+
+	if (!xfs_sb_version_hascrc(&mp->m_sb))
+		return true;
+
+	/*
+	 * if we are in log recovery, the quota subsystem has not been
+	 * initialised so we have no quotainfo structure. In that case, we need
+	 * to manually calculate the number of dquots in the buffer.
+	 */
+	if (mp->m_quotainfo)
+		ndquots = mp->m_quotainfo->qi_dqperchunk;
+	else
+		ndquots = xfs_calc_dquots_per_chunk(mp,
+					XFS_BB_TO_FSB(mp, bp->b_length));
+
+	for (i = 0; i < ndquots; i++, d++) {
+		if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
+				 XFS_DQUOT_CRC_OFF))
+			return false;
+		if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
+			return false;
+	}
+	return true;
+}
+
+STATIC bool
+xfs_dquot_buf_verify(
+	struct xfs_mount	*mp,
+	struct xfs_buf		*bp)
+{
+	struct xfs_dqblk	*d = (struct xfs_dqblk *)bp->b_addr;
+	xfs_dqid_t		id = 0;
+	int			ndquots;
+	int			i;
+
+	/*
+	 * if we are in log recovery, the quota subsystem has not been
+	 * initialised so we have no quotainfo structure. In that case, we need
+	 * to manually calculate the number of dquots in the buffer.
+	 */
+	if (mp->m_quotainfo)
+		ndquots = mp->m_quotainfo->qi_dqperchunk;
+	else
+		ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length);
+
+	/*
+	 * On the first read of the buffer, verify that each dquot is valid.
+	 * We don't know what the id of the dquot is supposed to be, just that
+	 * they should be increasing monotonically within the buffer. If the
+	 * first id is corrupt, then it will fail on the second dquot in the
+	 * buffer so corruptions could point to the wrong dquot in this case.
+	 */
+	for (i = 0; i < ndquots; i++) {
+		struct xfs_disk_dquot	*ddq;
+		int			error;
+
+		ddq = &d[i].dd_diskdq;
+
+		if (i == 0)
+			id = be32_to_cpu(ddq->d_id);
+
+		error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
+				       "xfs_dquot_buf_verify");
+		if (error)
+			return false;
+	}
+	return true;
+}
+
+static void
+xfs_dquot_buf_read_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+
+	if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+/*
+ * we don't calculate the CRC here as that is done when the dquot is flushed to
+ * the buffer after the update is done. This ensures that the dquot in the
+ * buffer always has an up-to-date CRC value.
+ */
+void
+xfs_dquot_buf_write_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+
+	if (!xfs_dquot_buf_verify(mp, bp)) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		return;
+	}
+}
+
+const struct xfs_buf_ops xfs_dquot_buf_ops = {
+	.verify_read = xfs_dquot_buf_read_verify,
+	.verify_write = xfs_dquot_buf_write_verify,
+};
+
-- 
1.8.4.rc3

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  parent reply	other threads:[~2013-10-30  4:31 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-30  4:30 [PATCH 00/30 V3] xfsprogs: CRC write support for xfs_db Dave Chinner
2013-10-30  4:30 ` [PATCH 01/30] xfsprogs: fix automatic dependency generation Dave Chinner
2013-10-31 14:44   ` Christoph Hellwig
2013-10-30  4:30 ` [PATCH 02/30] xfs: fix some minor sparse warnings Dave Chinner
2013-10-31 14:44   ` Christoph Hellwig
2013-10-30  4:30 ` [PATCH 03/30] xfs: create a shared header file for format-related information Dave Chinner
2013-10-31 14:45   ` Christoph Hellwig
2013-10-30  4:30 ` Dave Chinner [this message]
2013-10-31 14:45   ` [PATCH 04/30] xfs: split dquot buffer operations out Christoph Hellwig
2013-10-30  4:30 ` [PATCH 05/30] xfs: decouple inode and bmap btree header files Dave Chinner
2013-10-31 14:45   ` Christoph Hellwig
2013-10-30  4:30 ` [PATCH 06/30] libxfs: unify xfs_btree.c with kernel code Dave Chinner
2013-10-31 14:46   ` Christoph Hellwig
2013-10-30  4:30 ` [PATCH 07/30] libxfs: bmap btree owner swap support Dave Chinner
2013-10-31 14:47   ` Christoph Hellwig
2013-10-30  4:30 ` [PATCH 08/30] libxfs: xfs_rtalloc.c becomes xfs_rtbitmap.c Dave Chinner
2013-10-31 14:48   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 09/30] libxfs: bring across inode buffer readahead verifier changes Dave Chinner
2013-10-31 14:48   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 10/30] libxfs: Minor cleanup and bug fix sync Dave Chinner
2013-10-31 14:48   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 11/30] xfs: remove newlines from strings passed to __xfs_printk Dave Chinner
2013-10-31 14:49   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 12/30] xfs: fix the wrong new_size/rnew_size at xfs_iext_realloc_direct() Dave Chinner
2013-10-31 14:49   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 13/30] xfs: fix node forward in xfs_node_toosmall Dave Chinner
2013-10-31 14:49   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 14/30] xfs: don't emit corruption noise on fs probes Dave Chinner
2013-10-31 14:49   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 15/30] db: separate out straight buffer IO from map based IO Dave Chinner
2013-10-31 14:56   ` Christoph Hellwig
2013-10-31 21:50     ` Dave Chinner
2013-11-01 12:51       ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 16/30] db: rewrite bbmap to use xfs_buf_map Dave Chinner
2013-10-31 15:06   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 17/30] db: rewrite IO engine to use libxfs Dave Chinner
2013-10-31 15:10   ` Christoph Hellwig
2013-10-31 21:59     ` Dave Chinner
2013-10-30  4:31 ` [PATCH 18/30] db: introduce verifier support into set_cur Dave Chinner
2013-11-01 13:07   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 19/30] db: indicate if the CRC on a buffer is correct or not Dave Chinner
2013-11-01 13:09   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 20/30] db: verify and calculate inode CRCs Dave Chinner
2013-11-04  9:05   ` Christoph Hellwig
2013-11-05  0:18     ` Dave Chinner
2013-10-30  4:31 ` [PATCH 21/30] db: verify and calculate dquot CRCs Dave Chinner
2013-11-04  9:06   ` Christoph Hellwig
2013-11-05  0:25     ` Dave Chinner
2013-10-30  4:31 ` [PATCH 22/30] db: add a special directory buffer verifier Dave Chinner
2013-11-04  9:07   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 23/30] db: add a special attribute " Dave Chinner
2013-11-04  9:07   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 24/30] db: re-enable write support for v5 filesystems Dave Chinner
2013-11-04  9:07   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 25/30] libxfs: fix root inode handling inconsistencies Dave Chinner
2013-10-30 10:23   ` Christoph Hellwig
2013-10-30 21:59     ` Dave Chinner
2013-10-31  4:13       ` [PATCH 25/30 V2] " Dave Chinner
2013-10-31 15:00         ` Christoph Hellwig
2013-10-31 22:04           ` Dave Chinner
2013-11-01 13:03             ` Christoph Hellwig
2013-11-04 23:22               ` Dave Chinner
2013-11-05  9:05                 ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 26/30] xfs_db: avoid libxfs buffer lookup warnings Dave Chinner
2013-11-04  9:12   ` Christoph Hellwig
2013-11-05  0:52     ` Dave Chinner
2013-11-05  9:06       ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 27/30] libxfs: work around do_div() not handling 32 bit numerators Dave Chinner
2013-11-04  9:16   ` Christoph Hellwig
2013-11-05  1:55     ` Dave Chinner
2013-10-30  4:31 ` [PATCH 28/30] db: enable metadump on CRC filesystems Dave Chinner
2013-11-04  9:18   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 29/30] xfs: support larger inode clusters on v5 filesystems Dave Chinner
2013-11-04  9:18   ` Christoph Hellwig
2013-10-30  4:31 ` [PATCH 30/30] xfsprogs: kill experimental warnings for " Dave Chinner
2013-11-04  9:19   ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1383107481-28937-5-git-send-email-david@fromorbit.com \
    --to=david@fromorbit.com \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.