This is an automated email from the git hooks/post-receive script.
andyp pushed a commit to branch andyp-lhv2
in repository gfs2-utils.
commit 741fad296ebf93b3d519f5f2f16fee26c3384f38
Author: Andrew Price <anprice(a)redhat.com>
Date: Fri Jan 19 14:21:23 2018 +0000
Add basic support for v2 log headers
mkfs.gfs2 now writes v2 log headers, fsck.gfs2 checks the crc as well as
the hash, gfs2_edit includes the new fields when printing log blocks and
gfs2_jadd now writes v2 log headers.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
configure.ac | 2 ++
gfs2/libgfs2/libgfs2.h | 8 ++++--
gfs2/libgfs2/meta.c | 13 ++++++++++
gfs2/libgfs2/ondisk.c | 63 ++++++++++++++++++++++++++++++++++++++++++++---
gfs2/libgfs2/recovery.c | 11 ++++++---
gfs2/libgfs2/structures.c | 62 ++++++++++++++++++++++++++++++++++++++++------
gfs2/mkfs/main_jadd.c | 30 ++++++++++++++++------
7 files changed, 165 insertions(+), 24 deletions(-)
diff --git a/configure.ac b/configure.ac
index 4e8518c..2fb5e0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -141,6 +141,8 @@ AC_CHECK_MEMBER([struct gfs2_rgrp.rg_skip],[AC_DEFINE([GFS2_HAS_RG_SKIP],[],[Nex
[], [[#include <linux/gfs2_ondisk.h>]])
AC_CHECK_MEMBER([struct gfs2_rgrp.rg_data0],[AC_DEFINE([GFS2_HAS_RG_RI_FIELDS],[],[Resource group fields duplicated from the rindex])],
[], [[#include <linux/gfs2_ondisk.h>]])
+AC_CHECK_MEMBER([struct gfs2_log_header.lh_crc],[AC_DEFINE([GFS2_HAS_LH_V2],[],[v2 log header format])],
+ [], [[#include <linux/gfs2_ondisk.h>]])
# libuuid is only required if struct gfs2_sb.sb_uuid exists
if test "$sb_has_uuid" = "yes" -a "$have_uuid" = "no"; then
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 2221af8..85ac74c 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -469,6 +469,8 @@ extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
extern int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned blocks);
extern int lgfs2_write_journal_data(struct gfs2_inode *ip);
extern int lgfs2_write_filemeta(struct gfs2_inode *ip);
+extern uint32_t lgfs2_log_header_hash(char *buf);
+extern uint32_t lgfs2_log_header_crc(char *buf, unsigned bsize);
/* gfs1.c - GFS1 backward compatibility structures and functions */
@@ -743,8 +745,9 @@ extern void gfs2_dirent_out(struct gfs2_dirent *de, char *buf);
extern void gfs2_leaf_in(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh);
extern void gfs2_leaf_out(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh);
extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, char *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header *lh,
- struct gfs2_buffer_head *bh);
+extern void gfs2_log_header_v1_in(struct gfs2_log_header *lh, struct gfs2_buffer_head *bh);
+extern void gfs2_log_header_in(struct gfs2_log_header *lh, struct gfs2_buffer_head *bh);
+extern void gfs2_log_header_v1_out(struct gfs2_log_header *lh, char *buf);
extern void gfs2_log_header_out(struct gfs2_log_header *lh, char *buf);
extern void gfs2_log_header_out_bh(struct gfs2_log_header *lh, struct gfs2_buffer_head *bh);
extern void gfs2_log_descriptor_in(struct gfs2_log_descriptor *ld,
@@ -769,6 +772,7 @@ extern void gfs2_quota_print(const struct gfs2_quota *qu);
extern void gfs2_dinode_print(const struct gfs2_dinode *di);
extern void gfs2_leaf_print(const struct gfs2_leaf *lf);
extern void gfs2_ea_header_print(const struct gfs2_ea_header *ea, char *name);
+extern void gfs2_log_header_v1_print(const struct gfs2_log_header *lh);
extern void gfs2_log_header_print(const struct gfs2_log_header *lh);
extern void gfs2_log_descriptor_print(const struct gfs2_log_descriptor *ld);
extern void gfs2_statfs_change_print(const struct gfs2_statfs_change *sc);
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
index 82c8c6b..e7a2226 100644
--- a/gfs2/libgfs2/meta.c
+++ b/gfs2/libgfs2/meta.c
@@ -363,6 +363,19 @@ F(lh_flags)
F(lh_tail)
F(lh_blkno)
F(lh_hash, .flags = LGFS2_MFF_CHECK)
+#ifdef GFS2_HAS_LH_V2
+F(lh_crc, .flags = LGFS2_MFF_CHECK)
+F(lh_nsec, .flags = LGFS2_MFF_NSECS)
+F(lh_sec, .flags = LGFS2_MFF_SECS)
+FP(lh_addr, .points_to = (1 << LGFS2_MT_GFS2_LOG_BLOCK))
+FP(lh_jinode, .points_to = (1 << LGFS2_MT_GFS2_DINODE))
+FP(lh_statfs_addr, .points_to = (1 << LGFS2_MT_GFS2_DINODE))
+FP(lh_quota_addr, .points_to = (1 << LGFS2_MT_GFS2_DINODE))
+F(lh_local_total, .flags = LGFS2_MFF_FSBLOCKS)
+F(lh_local_free, .flags = LGFS2_MFF_FSBLOCKS)
+F(lh_local_dinodes, .flags = LGFS2_MFF_FSBLOCKS)
+F(lh_log_origin)
+#endif
};
#undef STRUCT
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
index dfb99d1..000decf 100644
--- a/gfs2/libgfs2/ondisk.c
+++ b/gfs2/libgfs2/ondisk.c
@@ -556,8 +556,7 @@ void gfs2_ea_header_print(const struct gfs2_ea_header *ea, char *name)
print_it(" name", "%s", NULL, buf);
}
-void gfs2_log_header_in(struct gfs2_log_header *lh,
- struct gfs2_buffer_head *bh)
+void gfs2_log_header_v1_in(struct gfs2_log_header *lh, struct gfs2_buffer_head *bh)
{
struct gfs2_log_header *str = (struct gfs2_log_header *)bh->b_data;
@@ -569,7 +568,27 @@ void gfs2_log_header_in(struct gfs2_log_header *lh,
CPIN_32(lh, str, lh_hash);
}
-void gfs2_log_header_out(struct gfs2_log_header *lh, char *buf)
+void gfs2_log_header_in(struct gfs2_log_header *lh, struct gfs2_buffer_head *bh)
+{
+ struct gfs2_log_header *str = (struct gfs2_log_header *)bh->b_data;
+
+ gfs2_log_header_v1_in(lh, bh);
+#ifdef GFS2_HAS_LH_V2
+ CPIN_32(lh, str, lh_crc);
+ CPIN_32(lh, str, lh_nsec);
+ CPIN_64(lh, str, lh_sec);
+ CPIN_64(lh, str, lh_addr);
+ CPIN_64(lh, str, lh_jinode);
+ CPIN_64(lh, str, lh_statfs_addr);
+ CPIN_64(lh, str, lh_quota_addr);
+ CPIN_64(lh, str, lh_local_total);
+ CPIN_64(lh, str, lh_local_free);
+ CPIN_64(lh, str, lh_local_dinodes);
+ CPIN_32(lh, str, lh_log_origin);
+#endif
+}
+
+void gfs2_log_header_v1_out(struct gfs2_log_header *lh, char *buf)
{
struct gfs2_log_header *str = (struct gfs2_log_header *)buf;
@@ -581,13 +600,33 @@ void gfs2_log_header_out(struct gfs2_log_header *lh, char *buf)
CPOUT_32(lh, str, lh_hash);
}
+void gfs2_log_header_out(struct gfs2_log_header *lh, char *buf)
+{
+ struct gfs2_log_header *str = (struct gfs2_log_header *)buf;
+
+ gfs2_log_header_v1_out(lh, buf);
+#ifdef GFS2_HAS_LH_V2
+ CPOUT_32(lh, str, lh_crc);
+ CPOUT_32(lh, str, lh_nsec);
+ CPOUT_64(lh, str, lh_sec);
+ CPOUT_64(lh, str, lh_addr);
+ CPOUT_64(lh, str, lh_jinode);
+ CPOUT_64(lh, str, lh_statfs_addr);
+ CPOUT_64(lh, str, lh_quota_addr);
+ CPOUT_64(lh, str, lh_local_total);
+ CPOUT_64(lh, str, lh_local_free);
+ CPOUT_64(lh, str, lh_local_dinodes);
+ CPOUT_32(lh, str, lh_log_origin);
+#endif
+}
+
void gfs2_log_header_out_bh(struct gfs2_log_header *lh, struct gfs2_buffer_head *bh)
{
gfs2_log_header_out(lh, bh->iov.iov_base);
bmodified(bh);
}
-void gfs2_log_header_print(const struct gfs2_log_header *lh)
+void gfs2_log_header_v1_print(const struct gfs2_log_header *lh)
{
gfs2_meta_header_print(&lh->lh_header);
pv(lh, lh_sequence, "%llu", "0x%llx");
@@ -597,6 +636,22 @@ void gfs2_log_header_print(const struct gfs2_log_header *lh)
pv(lh, lh_hash, "0x%.8X", NULL);
}
+void gfs2_log_header_print(const struct gfs2_log_header *lh)
+{
+ gfs2_log_header_v1_print(lh);
+ pv(lh, lh_crc, "0x%.8X", NULL);
+ pv(lh, lh_nsec, "%u", "0x%x");
+ pv(lh, lh_sec, "%llu", "0x%llx");
+ pv(lh, lh_addr, "%llu", "0x%llx");
+ pv(lh, lh_jinode, "%llu", "0x%llx");
+ pv(lh, lh_statfs_addr, "%llu", "0x%llx");
+ pv(lh, lh_quota_addr, "%llu", "0x%llx");
+ pv(lh, lh_local_total, "%llu", "0x%llx");
+ pv(lh, lh_local_free, "%llu", "0x%llx");
+ pv(lh, lh_local_dinodes, "%llu", "0x%llx");
+ pv(lh, lh_log_origin, "0x%.8X", NULL);
+}
+
void gfs2_log_descriptor_in(struct gfs2_log_descriptor *ld,
struct gfs2_buffer_head *bh)
{
diff --git a/gfs2/libgfs2/recovery.c b/gfs2/libgfs2/recovery.c
index cad723f..51d210e 100644
--- a/gfs2/libgfs2/recovery.c
+++ b/gfs2/libgfs2/recovery.c
@@ -57,6 +57,8 @@ int get_log_header(struct gfs2_inode *ip, unsigned int blk,
struct gfs2_buffer_head *bh;
struct gfs2_log_header lh, *tmp;
uint32_t hash, saved_hash;
+ uint32_t lh_crc = 0;
+ uint32_t crc;
int error;
error = gfs2_replay_read_block(ip, blk, &bh);
@@ -66,12 +68,15 @@ int get_log_header(struct gfs2_inode *ip, unsigned int blk,
tmp = (struct gfs2_log_header *)bh->b_data;
saved_hash = tmp->lh_hash;
tmp->lh_hash = 0;
- hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
+ hash = lgfs2_log_header_hash(bh->b_data);
tmp->lh_hash = saved_hash;
+ crc = lgfs2_log_header_crc(bh->b_data, ip->i_sbd->bsize);
gfs2_log_header_in(&lh, bh);
brelse(bh);
-
- if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
+#ifdef GFS2_HAS_LH_V2
+ lh_crc = lh.lh_crc;
+#endif
+ if (error || lh.lh_blkno != blk || lh.lh_hash != hash || lh_crc != crc)
return 1;
*head = lh;
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index 2d97dab..99765bf 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -102,6 +102,27 @@ out_buf:
return err;
}
+uint32_t lgfs2_log_header_hash(char *buf)
+{
+ /* lh_hash only CRCs the fields in the old lh, which ends where lh_crc is now */
+ const off_t v1_end = offsetof(struct gfs2_log_header, lh_hash) + 4;
+
+ return gfs2_disk_hash(buf, v1_end);
+}
+
+uint32_t lgfs2_log_header_crc(char *buf, unsigned bsize)
+{
+#ifdef GFS2_HAS_LH_V2
+ /* lh_crc CRCs the rest of the block starting after lh_crc */
+ const off_t v1_end = offsetof(struct gfs2_log_header, lh_hash) + 4;
+
+ return gfs2_disk_hash(buf + v1_end + sizeof(((struct gfs2_log_header*)0)->lh_crc),
+ bsize - v1_end - sizeof(((struct gfs2_log_header*)0)->lh_crc));
+#else
+ return 0;
+#endif
+}
+
/**
* Intialise and write the data blocks for a new journal as a contiguous
* extent. The indirect blocks pointing to these data blocks should have been
@@ -112,12 +133,26 @@ out_buf:
*/
int lgfs2_write_journal_data(struct gfs2_inode *ip)
{
- uint32_t hash;
struct gfs2_log_header lh = {
.lh_header.mh_magic = GFS2_MAGIC,
.lh_header.mh_type = GFS2_METATYPE_LH,
.lh_header.mh_format = GFS2_FORMAT_LH,
.lh_flags = GFS2_LOG_HEAD_UNMOUNT,
+ .lh_tail = 0,
+ .lh_blkno = 0,
+ .lh_hash = 0,
+#ifdef GFS2_HAS_LH_V2
+ .lh_crc = 0,
+ .lh_nsec = 0,
+ .lh_sec = 0,
+ .lh_jinode = ip->i_di.di_num.no_addr,
+ .lh_statfs_addr = 0,
+ .lh_quota_addr = 0,
+ .lh_local_total = 0,
+ .lh_local_free = 0,
+ .lh_local_dinodes = 0,
+ .lh_log_origin = GFS2_LOG_HEAD_USERSPACE
+#endif
};
struct gfs2_buffer_head *bh;
struct gfs2_sbd *sdp = ip->i_sbd;
@@ -130,11 +165,17 @@ int lgfs2_write_journal_data(struct gfs2_inode *ip)
return -1;
do {
+ struct gfs2_log_header *buflh = (struct gfs2_log_header *)bh->b_data;
+
lh.lh_sequence = seq;
lh.lh_blkno = bh->b_blocknr - jext0;
- gfs2_log_header_out_bh(&lh, bh);
- hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
- ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash);
+ gfs2_log_header_out(&lh, bh->b_data);
+
+ buflh->lh_hash = cpu_to_be32(lgfs2_log_header_hash(bh->b_data));
+#ifdef GFS2_HAS_LH_V2
+ buflh->lh_addr = cpu_to_be32(bh->b_blocknr);
+ buflh->lh_crc = cpu_to_be32(lgfs2_log_header_crc(bh->b_data, sdp->bsize));
+#endif
if (bwrite(bh)) {
free(bh);
@@ -168,7 +209,10 @@ int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned int blocks)
lh.lh_header.mh_type = GFS2_METATYPE_LH;
lh.lh_header.mh_format = GFS2_FORMAT_LH;
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
-
+#ifdef GFS2_HAS_LH_V2
+ lh.lh_jinode = jnl->i_di.di_num.no_addr;
+ lh.lh_log_origin = GFS2_LOG_HEAD_USERSPACE;
+#endif
for (x = 0; x < blocks; x++) {
struct gfs2_buffer_head *bh = get_file_buf(jnl, x, TRUE);
if (!bh)
@@ -185,9 +229,13 @@ int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned int blocks)
lh.lh_sequence = seq;
lh.lh_blkno = x;
gfs2_log_header_out_bh(&lh, bh);
- hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
+ hash = lgfs2_log_header_hash(bh->b_data);
((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash);
-
+#ifdef GFS2_HAS_LH_V2
+ ((struct gfs2_log_header *)bh->b_data)->lh_addr = cpu_to_be32(bh->b_blocknr);
+ hash = lgfs2_log_header_crc(bh->b_data, bsize);
+ ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash);
+#endif
bmodified(bh);
brelse(bh);
diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c
index 3681b90..a77d97c 100644
--- a/gfs2/mkfs/main_jadd.c
+++ b/gfs2/mkfs/main_jadd.c
@@ -238,7 +238,7 @@ static void print_results(struct jadd_opts *opts)
printf( _("New journals: %u\n"), opts->journals);
}
-static int create_new_inode(struct jadd_opts *opts)
+static int create_new_inode(struct jadd_opts *opts, uint64_t *addr)
{
char *name = opts->new_inode;
int fd;
@@ -259,6 +259,12 @@ static int create_new_inode(struct jadd_opts *opts)
exit(EXIT_FAILURE);
}
}
+ if (addr != NULL) {
+ struct stat st;
+
+ fstat(fd, &st);
+ *addr = st.st_ino;
+ }
return fd;
}
@@ -269,7 +275,7 @@ static void add_ir(struct jadd_opts *opts)
char new_name[256];
int error;
- fd = create_new_inode(opts);
+ fd = create_new_inode(opts, NULL);
{
struct gfs2_inum_range ir;
@@ -299,7 +305,7 @@ static void add_sc(struct jadd_opts *opts)
char new_name[256];
int error;
- fd = create_new_inode(opts);
+ fd = create_new_inode(opts, NULL);
{
struct gfs2_statfs_change sc;
@@ -329,7 +335,7 @@ static void add_qc(struct gfs2_sbd *sdp, struct jadd_opts *opts)
char new_name[256];
int error;
- fd = create_new_inode(opts);
+ fd = create_new_inode(opts, NULL);
{
char buf[sdp->bsize];
@@ -424,8 +430,9 @@ static void add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts)
int fd;
char new_name[256];
int error;
+ uint64_t addr;
- fd = create_new_inode(opts);
+ fd = create_new_inode(opts, &addr);
{
char buf[sdp->bsize];
@@ -451,16 +458,23 @@ static void add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts)
lh.lh_header.mh_type = GFS2_METATYPE_LH;
lh.lh_header.mh_format = GFS2_FORMAT_LH;
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
-
+#ifdef GFS2_HAS_LH_V2
+ lh.lh_addr = 0; /* Don't know this value here, should be ok to leave it 0 */
+ lh.lh_jinode = addr;
+ lh.lh_log_origin = GFS2_LOG_HEAD_USERSPACE;
+#endif
for (x=0; x<blocks; x++) {
uint32_t hash;
lh.lh_sequence = seq;
lh.lh_blkno = x;
gfs2_log_header_out(&lh, buf);
- hash = gfs2_disk_hash(buf, sizeof(struct gfs2_log_header));
+ hash = lgfs2_log_header_hash(buf);
((struct gfs2_log_header *)buf)->lh_hash = cpu_to_be32(hash);
-
+#ifdef GFS2_HAS_LH_V2
+ hash = lgfs2_log_header_crc(buf, sdp->bsize);
+ ((struct gfs2_log_header *)buf)->lh_crc = cpu_to_be32(hash);
+#endif
if (write(fd, buf, sdp->bsize) != sdp->bsize) {
perror("add_j");
exit(EXIT_FAILURE);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.