All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] xfsprogs: log format fixes, db command
@ 2015-11-25 20:17 Brian Foster
  2015-11-25 20:17 ` [PATCH 1/4] logprint: use correct ext. header count for unaligned size Brian Foster
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Brian Foster @ 2015-11-25 20:17 UTC (permalink / raw)
  To: xfs

Hi all,

This series includes a few fixes to log formatting/handling code in
xfsprogs. Patch 1 fixes a minor issue in xfs_logprint. Patch 2 fixes the
incorrect formatting issue with larger lsunit alignments noted in the
previously posted torn log write detection series:

  http://oss.sgi.com/pipermail/xfs/2015-November/044845.html

Patch 3 is mostly a refactor to allow the log format command to use
variable sized records rather than unconditionally use 256kB records.
Patch 4 adds the 'logformat' xfs_db command to facilitate testing of the
log formatting mechanism.

This has been lightly tested with xfstests, including via a couple
forthcoming tests that take advantage of the logformat command.
Thoughts, reviews, flames appreciated.

Brian

Brian Foster (4):
  logprint: use correct ext. header count for unaligned size
  libxfs: format the log with valid log record headers
  libxfs: conditionalize log format record size optimization
  db: add the logformat command

 copy/xfs_copy.c     |   2 +-
 db/Makefile         |   4 +-
 db/command.c        |   2 +
 db/logformat.c      | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 db/logformat.h      |  19 +++++++
 db/metadump.c       |   2 +-
 db/sb.c             |   2 +-
 include/libxfs.h    |   2 +-
 libxfs/rdwr.c       |  89 ++++++++++++++++++++++++-------
 logprint/log_misc.c |   2 +
 mkfs/xfs_mkfs.c     |   3 +-
 repair/phase2.c     |   2 +-
 repair/xfs_repair.c |   2 +-
 13 files changed, 251 insertions(+), 29 deletions(-)
 create mode 100644 db/logformat.c
 create mode 100644 db/logformat.h

-- 
2.1.0

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] logprint: use correct ext. header count for unaligned size
  2015-11-25 20:17 [PATCH 0/4] xfsprogs: log format fixes, db command Brian Foster
@ 2015-11-25 20:17 ` Brian Foster
  2015-11-25 20:17 ` [PATCH 2/4] libxfs: format the log with valid log record headers Brian Foster
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Brian Foster @ 2015-11-25 20:17 UTC (permalink / raw)
  To: xfs

A log record has 1 record header and up to 7 additional extended record
headers depending on the size of the record. This is required for log
record packing. A header is required for each 32k of record data.

The header count for a particular record is fixed, based on the log
buffer size (h_size) specified in the record header. logprint calculates
the expected extended header count based on h_size, but does not account
for a log buffer size not aligned with 32k. This results in spurious
invalid header count errors for an otherwise valid log. This can be
reproduced by mounting a filesystem with '-o logbsize=16k' and running
xfs_logprint after a subsequent unmount.

Update xlog_print_extended_headers() to incorporate a non-32k aligned
log buffer size in the expected extended record header count
calculation. This is consistent with how the header count is calculated
in the kernel.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 logprint/log_misc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index 4cdcbec..7378fe1 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -1294,6 +1294,8 @@ xlog_print_extended_headers(
 
 	num_required = howmany(len, XLOG_HEADER_CYCLE_SIZE);
 	num_hdrs = be32_to_cpu(hdr->h_size) / XLOG_HEADER_CYCLE_SIZE;
+	if (be32_to_cpu(hdr->h_size) % XLOG_HEADER_CYCLE_SIZE)
+		num_hdrs++;
 
 	if (num_required > num_hdrs) {
 	    print_xlog_bad_reqd_hdrs((*blkno)-1, num_required, num_hdrs);
-- 
2.1.0

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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] libxfs: format the log with valid log record headers
  2015-11-25 20:17 [PATCH 0/4] xfsprogs: log format fixes, db command Brian Foster
  2015-11-25 20:17 ` [PATCH 1/4] logprint: use correct ext. header count for unaligned size Brian Foster
@ 2015-11-25 20:17 ` Brian Foster
  2015-11-25 20:17 ` [PATCH 3/4] libxfs: conditionalize log format record size optimization Brian Foster
  2015-11-25 20:17 ` [PATCH 4/4] db: add the logformat command Brian Foster
  3 siblings, 0 replies; 5+ messages in thread
From: Brian Foster @ 2015-11-25 20:17 UTC (permalink / raw)
  To: xfs

xfsprogs supports the ability to clear or reformat the log to an
arbitrary cycle number. This functionality is invoked in mkfs,
xfs_repair, etc. The code currently fills the log with unmount records
sized based on the specified log stripe unit alignment. When the stripe
unit is sufficiently larger, however, the resulting log records are
technically invalid. For example, the log buffer size (h_size) field is
always hardcoded to 32k even when the particular record length is
larger.

This has not traditionally been a problem because the kernel does not
fully process the log record when the log is clean. Recent changes to
unconditionally CRC verify the head of the log changes this behavior,
however, which means the log should be valid. Technically, the records
written from userspace are not written with a CRC, but this also helps
support unit testing by writing a log that can be verified with
logprint.

Update libxfs_log_header() to write a valid log record based on the
specified log stripe unit. h_size is updated to the log buffer size
based on the stripe unit and the expected number of extended record
headers are written out based on the log buffer size.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 libxfs/rdwr.c | 74 +++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 57 insertions(+), 17 deletions(-)

diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 0804285..16904d0 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -279,6 +279,7 @@ libxfs_log_header(
 	char			*p = caddr;
 	__be32			cycle_lsn;
 	int			i, len;
+	int			hdrs = 1;
 
 	if (lsn == NULLCOMMITLSN)
 		lsn = xlog_assign_lsn(XLOG_INIT_CYCLE, 0);
@@ -291,41 +292,80 @@ libxfs_log_header(
 	head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
 	head->h_cycle = cpu_to_be32(CYCLE_LSN(lsn));
 	head->h_version = cpu_to_be32(version);
-	if (len != 1)
-		head->h_len = cpu_to_be32(sunit - BBSIZE);
-	else
-		head->h_len = cpu_to_be32(20);
 	head->h_crc = cpu_to_le32(0);
 	head->h_prev_block = cpu_to_be32(-1);
 	head->h_num_logops = cpu_to_be32(1);
 	head->h_fmt = cpu_to_be32(fmt);
-	head->h_size = cpu_to_be32(XLOG_HEADER_CYCLE_SIZE);
+	head->h_size = cpu_to_be32(MAX(sunit, XLOG_BIG_RECORD_BSIZE));
 
 	head->h_lsn = cpu_to_be64(lsn);
 	head->h_tail_lsn = cpu_to_be64(tail_lsn);
 
 	memcpy(&head->h_fs_uuid, fs_uuid, sizeof(uuid_t));
 
-	p = nextfunc(p, BBSIZE, private);
-	unmount_record(p);
-
 	/*
-	 * The kernel expects to see either a log record header magic or the LSN
-	 * cycle at the top of every log block (for example, see
-	 * xlog_[un]pack_data() and xlog_get_cycle()). Pack the unmount record
-	 * block appropriately here.
+	 * The kernel expects to see either a log record header magic value or
+	 * the LSN cycle at the top of every log block. The first word of each
+	 * non-header block is copied to the record headers and replaced with
+	 * the cycle value (see xlog_[un]pack_data() and xlog_get_cycle() for
+	 * details).
+	 *
+	 * Even though we only ever write an unmount record (one block), we
+	 * support writing log records up to the max log buffer size of 256k to
+	 * improve log format performance. This means a record can require up
+	 * to 8 headers (1 rec. header + 7 ext. headers) for the packed cycle
+	 * data (each header supports 32k of data).
 	 */
 	cycle_lsn = CYCLE_LSN_DISK(head->h_lsn);
+	if (version == 2 && sunit > XLOG_HEADER_CYCLE_SIZE) {
+		hdrs = sunit / XLOG_HEADER_CYCLE_SIZE;
+		if (sunit % XLOG_HEADER_CYCLE_SIZE)
+			hdrs++;
+	}
+
+	/*
+	 * A fixed number of extended headers is expected based on h_size. If
+	 * required, format those now so the unmount record is located
+	 * correctly.
+	 *
+	 * Since we only write an unmount record, we only need one h_cycle_data
+	 * entry for the unmount record block. The subsequent record data
+	 * blocks are zeroed, which means we can stamp them directly with the
+	 * cycle and zero the rest of the cycle data in the extended headers.
+	 */
+	if (hdrs > 1) {
+		for (i = 1; i < hdrs; i++) {
+			p = nextfunc(p, BBSIZE, private);
+			memset(p, 0, BBSIZE);
+			/* xlog_rec_ext_header.xh_cycle */
+			*(__be32 *)p = cycle_lsn;
+		}
+	}
+
+	/*
+	 * The total length is the max of the stripe unit or 2 basic block
+	 * minimum (1 hdr blk + 1 data blk). The record length is the total
+	 * minus however many header blocks are required.
+	 */
+	head->h_len = cpu_to_be32(MAX(BBTOB(2), sunit) - hdrs * BBSIZE);
+
+	/*
+	 * Write out the unmount record, pack the first word into the record
+	 * header and stamp the block with the cycle.
+	 */
+	p = nextfunc(p, BBSIZE, private);
+	unmount_record(p);
+
 	head->h_cycle_data[0] = *(__be32 *)p;
 	*(__be32 *)p = cycle_lsn;
 
 	/*
-	 * Now zero any remaining blocks in the record and stamp with the cycle.
-	 * Note that we don't need to swap into h_cycle_data because it has
-	 * already been initialized to zero.
+	 * Finally, zero all remaining blocks in the record and stamp each with
+	 * the cycle. We don't need to pack any of these blocks because the
+	 * cycle data in the headers has already been zeroed.
 	 */
-	len = MAX(len, 2);
-	for (i = 2; i < len; i++) {
+	len = MAX(len, hdrs + 1);
+	for (i = hdrs + 1; i < len; i++) {
 		p = nextfunc(p, BBSIZE, private);
 		memset(p, 0, BBSIZE);
 		*(__be32 *)p = cycle_lsn;
-- 
2.1.0

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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] libxfs: conditionalize log format record size optimization
  2015-11-25 20:17 [PATCH 0/4] xfsprogs: log format fixes, db command Brian Foster
  2015-11-25 20:17 ` [PATCH 1/4] logprint: use correct ext. header count for unaligned size Brian Foster
  2015-11-25 20:17 ` [PATCH 2/4] libxfs: format the log with valid log record headers Brian Foster
@ 2015-11-25 20:17 ` Brian Foster
  2015-11-25 20:17 ` [PATCH 4/4] db: add the logformat command Brian Foster
  3 siblings, 0 replies; 5+ messages in thread
From: Brian Foster @ 2015-11-25 20:17 UTC (permalink / raw)
  To: xfs

The libxfs log clear mechanism includes an optimization to use the
maximum log buffer size (256k) when the log is being fully written
(i.e., cycle != 1). This behavior is always enabled as no current
callers are concerned with the size of the records written to format the
log to a given cycle.

A log format command will be added to xfs_db to facilitate testing of
the userspace log format code (among other things). This command is not
performance oriented and prefers the ability to format the log with
varying record sizes.

Update libxfs_log_clear() to use a new parameter to enable or disable
the record size optimization. Note that the flag is a no-op when the
cycle == XLOG_INIT_CYCLE (e.g., mkfs).

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 copy/xfs_copy.c     |  2 +-
 db/metadump.c       |  2 +-
 db/sb.c             |  2 +-
 include/libxfs.h    |  2 +-
 libxfs/rdwr.c       | 15 ++++++++++++---
 mkfs/xfs_mkfs.c     |  3 ++-
 repair/phase2.c     |  2 +-
 repair/xfs_repair.c |  2 +-
 8 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c
index 1dc7c65..62edfc8 100644
--- a/copy/xfs_copy.c
+++ b/copy/xfs_copy.c
@@ -1328,7 +1328,7 @@ format_log(
 	 */
 	libxfs_log_clear(NULL, buf->data, logstart, length, &buf->owner->uuid,
 			 xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1,
-			 mp->m_sb.sb_logsunit, XLOG_FMT, cycle);
+			 mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true);
 	if (do_write(buf->owner, buf))
 		target[tcarg->id].state = INACTIVE;
 }
diff --git a/db/metadump.c b/db/metadump.c
index 8cdcb92..8455fdd 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -2552,7 +2552,7 @@ copy_log(void)
 
 		libxfs_log_clear(NULL, iocur_top->data, logstart, logblocks,
 				 &mp->m_sb.sb_uuid, logversion,
-				 mp->m_sb.sb_logsunit, XLOG_FMT, cycle);
+				 mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true);
 		break;
 	case 1:
 		/* keep the dirty log */
diff --git a/db/sb.c b/db/sb.c
index 17d446c..ee3927d 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -288,7 +288,7 @@ sb_logzero(uuid_t *uuidp)
 			(xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
 			uuidp,
 			xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1,
-			mp->m_sb.sb_logsunit, XLOG_FMT, cycle);
+			mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true);
 	if (error) {
 		dbprintf(_("ERROR: cannot clear the log\n"));
 		return 0;
diff --git a/include/libxfs.h b/include/libxfs.h
index 04c6f9c..bd51df0 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -154,7 +154,7 @@ typedef char	*(libxfs_get_block_t)(char *, int, void *);
  */
 #define XLOG_INIT_CYCLE	1
 extern int	libxfs_log_clear(struct xfs_buftarg *, char *, xfs_daddr_t,
-				 uint, uuid_t *, int, int, int, int);
+				 uint, uuid_t *, int, int, int, int, bool);
 extern int	libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t,
 				  xfs_lsn_t, libxfs_get_block_t *, void *);
 
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 16904d0..7a04985 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -162,7 +162,8 @@ libxfs_log_clear(
 	int			version,
 	int			sunit,		/* bytes */
 	int			fmt,
-	int			cycle)
+	int			cycle,
+	bool			max)
 {
 	struct xfs_buf		*bp = NULL;
 	int			len;
@@ -218,6 +219,14 @@ libxfs_log_clear(
 		return 0;
 
 	/*
+	 * Bump the record size for a full log format if the caller allows it.
+	 * This is primarily for performance reasons and most callers don't care
+	 * about record size since the log is clean after we're done.
+	 */
+	if (max)
+		len = BTOBB(BDSTRAT_SIZE);
+
+	/*
 	 * Otherwise, fill everything beyond the initial record with records of
 	 * the previous cycle so the kernel head/tail detection works correctly.
 	 *
@@ -233,7 +242,7 @@ libxfs_log_clear(
 		dptr += BBTOB(len);
 	end_blk = start + length;
 
-	len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
+	len = min(end_blk - blk, len);
 	while (blk < end_blk) {
 		lsn = xlog_assign_lsn(cycle, blk - start);
 		tail_lsn = xlog_assign_lsn(cycle, blk - start - len);
@@ -257,7 +266,7 @@ libxfs_log_clear(
 		blk += len;
 		if (dptr)
 			dptr += BBTOB(len);
-		len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
+		len = min(end_blk - blk, len);
 	}
 
 	return 0;
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 7cba41a..546108d 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2713,7 +2713,8 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	libxfs_log_clear(mp->m_logdev_targp, NULL,
 		XFS_FSB_TO_DADDR(mp, logstart),
 		(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
-		&sbp->sb_uuid, logversion, lsunit, XLOG_FMT, XLOG_INIT_CYCLE);
+		&sbp->sb_uuid, logversion, lsunit, XLOG_FMT, XLOG_INIT_CYCLE,
+		false);
 
 	mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
 	if (mp == NULL) {
diff --git a/repair/phase2.c b/repair/phase2.c
index cb24711..e21ffa6 100644
--- a/repair/phase2.c
+++ b/repair/phase2.c
@@ -119,7 +119,7 @@ zero_log(
 			(xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
 			&mp->m_sb.sb_uuid,
 			xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1,
-			mp->m_sb.sb_logsunit, XLOG_FMT, XLOG_INIT_CYCLE);
+			mp->m_sb.sb_logsunit, XLOG_FMT, XLOG_INIT_CYCLE, true);
 
 		/* update the log data structure with new state */
 		error = xlog_find_tail(log, &head_blk, &tail_blk);
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 1aeac5b..3eaced4 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -586,7 +586,7 @@ format_log_max_lsn(
 	do_warn(_("Format log to cycle %d.\n"), new_cycle);
 	libxfs_log_clear(log->l_dev, NULL, logstart, logblocks,
 			 &mp->m_sb.sb_uuid, logversion, mp->m_sb.sb_logsunit,
-			 XLOG_FMT, new_cycle);
+			 XLOG_FMT, new_cycle, true);
 }
 
 int
-- 
2.1.0

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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] db: add the logformat command
  2015-11-25 20:17 [PATCH 0/4] xfsprogs: log format fixes, db command Brian Foster
                   ` (2 preceding siblings ...)
  2015-11-25 20:17 ` [PATCH 3/4] libxfs: conditionalize log format record size optimization Brian Foster
@ 2015-11-25 20:17 ` Brian Foster
  3 siblings, 0 replies; 5+ messages in thread
From: Brian Foster @ 2015-11-25 20:17 UTC (permalink / raw)
  To: xfs

Add the new logformat command to format the log to a specified log cycle
and/or log stripe unit. This command is primarily for testing purposes
and is only available in expert mode.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 db/Makefile    |   4 +-
 db/command.c   |   2 +
 db/logformat.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 db/logformat.h |  19 ++++++++
 4 files changed, 172 insertions(+), 2 deletions(-)
 create mode 100644 db/logformat.c
 create mode 100644 db/logformat.h

diff --git a/db/Makefile b/db/Makefile
index fb01bdd..8260da3 100644
--- a/db/Makefile
+++ b/db/Makefile
@@ -11,8 +11,8 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \
 	btblock.h bmroot.h check.h command.h convert.h debug.h \
 	dir2.h dir2sf.h dquot.h echo.h faddr.h field.h \
 	flist.h fprint.h frag.h freesp.h hash.h help.h init.h inode.h input.h \
-	io.h malloc.h metadump.h output.h print.h quit.h sb.h sig.h strvec.h \
-	text.h type.h write.h attrset.h symlink.h
+	io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \
+	 sig.h strvec.h text.h type.h write.h attrset.h symlink.h
 CFILES = $(HFILES:.h=.c)
 LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh
 
diff --git a/db/command.c b/db/command.c
index 2189e00..3c17a1e 100644
--- a/db/command.c
+++ b/db/command.c
@@ -40,6 +40,7 @@
 #include "inode.h"
 #include "input.h"
 #include "io.h"
+#include "logformat.h"
 #include "metadump.h"
 #include "output.h"
 #include "print.h"
@@ -131,6 +132,7 @@ init_commands(void)
 	hash_init();
 	inode_init();
 	input_init();
+	logformat_init();
 	io_init();
 	metadump_init();
 	output_init();
diff --git a/db/logformat.c b/db/logformat.c
new file mode 100644
index 0000000..254f33d
--- /dev/null
+++ b/db/logformat.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015 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 "libxfs.h"
+#include "command.h"
+#include "init.h"
+#include "output.h"
+#include "libxlog.h"
+
+#define MAX_LSUNIT	256 * 1024	/* max log buf. size */
+
+static int
+logformat_f(int argc, char **argv)
+{
+	xfs_daddr_t	head_blk;
+	xfs_daddr_t	tail_blk;
+	int		logversion;
+	int		lsunit = -1;
+	int		cycle = -1;
+	int		error;
+	int		c;
+
+	logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1;
+
+	while ((c = getopt(argc, argv, "c:s:")) != EOF) {
+		switch (c) {
+		case 'c':
+			cycle = strtol(optarg, NULL, 0);
+			if (cycle == 0) {
+				dbprintf("invalid cycle\n");
+				return -1;
+			}
+			break;
+		case 's':
+			lsunit = strtol(optarg, NULL, 0);
+			/*
+			 * The log stripe unit must be block aligned and no
+			 * larger than 256k.
+			 */
+			if (lsunit > 1 &&
+			    (lsunit % mp->m_sb.sb_blocksize ||
+			    (logversion == 2 && lsunit > MAX_LSUNIT))) {
+				dbprintf("invalid log stripe unit\n");
+				return -1;
+			}
+			break;
+		default:
+			dbprintf("invalid option\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * Check whether the log is dirty. This also determines the current log
+	 * cycle if we have to use it by default below.
+	 */
+	memset(mp->m_log, 0, sizeof(struct xlog));
+	mp->m_log->l_mp = mp;
+	mp->m_log->l_dev = mp->m_logdev_targp;
+	mp->m_log->l_logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
+	mp->m_log->l_logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
+	mp->m_log->l_sectBBsize = BBSIZE;
+	if (xfs_sb_version_hassector(&mp->m_sb))
+		mp->m_log->l_sectBBsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT);
+	mp->m_log->l_sectBBsize = BTOBB(mp->m_log->l_sectBBsize);
+
+	error = xlog_find_tail(mp->m_log, &head_blk, &tail_blk);
+	if (error) {
+		dbprintf("could not find log head/tail\n");
+		return -1;
+	}
+	if (head_blk != tail_blk) {
+		dbprintf(_(
+			"The log is dirty. Please mount to replay the log.\n"));
+		return -1;
+	}
+
+	/*
+	 * Use the current cycle and/or log stripe unit if either is not
+	 * provided by the user.
+	 */
+	if (cycle < 0)
+		cycle = mp->m_log->l_curr_cycle;
+	if (lsunit < 0)
+		lsunit = mp->m_sb.sb_logsunit;
+
+	dbprintf("Formatting the log to cycle %d, stripe unit %d bytes.\n",
+		 cycle, lsunit);
+	error = libxfs_log_clear(mp->m_logdev_targp, NULL,
+				 mp->m_log->l_logBBstart,
+				 mp->m_log->l_logBBsize,
+				 &mp->m_sb.sb_uuid, logversion, lsunit,
+				 XLOG_FMT, cycle, false);
+	if (error) {
+		dbprintf("error formatting log - %d\n", error);
+		return error;
+	}
+
+	return 0;
+}
+
+static void
+logformat_help(void)
+{
+	dbprintf(_(
+"\n"
+" The 'logformat' command reformats (clears) the log to the specified log\n"
+" cycle and log stripe unit. If the log cycle is not specified, the log is\n"
+" reformatted to the current cycle. If the log stripe unit is not specified,\n"
+" the stripe unit from the filesystem superblock is used.\n"
+"\n"
+	));
+}
+
+static const struct cmdinfo logformat_cmd = {
+	.name =		"logformat",
+	.altname =	NULL,
+	.cfunc =	logformat_f,
+	.argmin =	0,
+	.argmax =	4,
+	.canpush =	0,
+	.args =		N_("[-c cycle] [-s sunit]"),
+	.oneline =	N_("reformat the log"),
+	.help =		logformat_help,
+};
+
+void
+logformat_init(void)
+{
+	if (!expert_mode)
+		return;
+
+	add_command(&logformat_cmd);
+}
diff --git a/db/logformat.h b/db/logformat.h
new file mode 100644
index 0000000..f9763ee
--- /dev/null
+++ b/db/logformat.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015 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
+ */
+
+void logformat_init(void);
-- 
2.1.0

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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-11-25 20:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-25 20:17 [PATCH 0/4] xfsprogs: log format fixes, db command Brian Foster
2015-11-25 20:17 ` [PATCH 1/4] logprint: use correct ext. header count for unaligned size Brian Foster
2015-11-25 20:17 ` [PATCH 2/4] libxfs: format the log with valid log record headers Brian Foster
2015-11-25 20:17 ` [PATCH 3/4] libxfs: conditionalize log format record size optimization Brian Foster
2015-11-25 20:17 ` [PATCH 4/4] db: add the logformat command Brian Foster

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.