Andy, this is looking quite good (apart from what you've just fixed).
On 19 January 2018 at 23:09, git repository hosting <[email protected]> wrote: > 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 637bf11085b20726f48d66bb2d7302aca8548c7a > Author: Andrew Price <[email protected]> > 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 <[email protected]> > --- > configure.ac | 2 + > gfs2/libgfs2/Makefile.am | 2 + > gfs2/libgfs2/crc32c.c | 221 > ++++++++++++++++++++++++++++++++++++++++++++++ > gfs2/libgfs2/crc32c.h | 9 ++ > gfs2/libgfs2/libgfs2.h | 8 +- > gfs2/libgfs2/meta.c | 15 +++- > gfs2/libgfs2/ondisk.c | 66 +++++++++++++- > gfs2/libgfs2/recovery.c | 11 ++- > gfs2/libgfs2/structures.c | 66 ++++++++++++-- > gfs2/mkfs/main_jadd.c | 56 ++++++++++-- > 10 files changed, 431 insertions(+), 25 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/Makefile.am b/gfs2/libgfs2/Makefile.am > index 4321a67..749da85 100644 > --- a/gfs2/libgfs2/Makefile.am > +++ b/gfs2/libgfs2/Makefile.am > @@ -15,6 +15,7 @@ AM_YFLAGS = -d > > noinst_HEADERS = \ > libgfs2.h \ > + crc32c.h \ > lang.h \ > config.h \ > rgrp.h > @@ -24,6 +25,7 @@ noinst_LTLIBRARIES = libgfs2.la > noinst_PROGRAMS = gfs2l > > libgfs2_la_SOURCES = \ > + crc32c.c \ > block_list.c \ > fs_bits.c \ > gfs1.c \ > diff --git a/gfs2/libgfs2/crc32c.c b/gfs2/libgfs2/crc32c.c > new file mode 100644 > index 0000000..e04c611 > --- /dev/null > +++ b/gfs2/libgfs2/crc32c.c > @@ -0,0 +1,221 @@ > +/* > + * Copied from btrfs-progs, kernel-lib/crc32c.c, which was: > + * Copied from the kernel source code, lib/libcrc32c.c. > + * > + * 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; either version 2 of the License, or (at your option) > + * any later version. > + * > + */ > +#include <stdlib.h> > +#include <inttypes.h> > +#include "crc32c.h" > + > +static uint32_t __crc32c_le(uint32_t crc, unsigned char const *data, size_t > length); > +static uint32_t (*crc_function)(uint32_t crc, unsigned char const *data, > size_t length) = __crc32c_le; > + > +#ifdef __x86_64__ > + > +/* > + * Based on a posting to lkml by Austin Zhang <[email protected]> > + * > + * Using hardware provided CRC32 instruction to accelerate the CRC32 > disposal. > + * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE) > + * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at: > + * http://www.intel.com/products/processor/manuals/ > + * Intel(R) 64 and IA-32 Architectures Software Developer's Manual > + * Volume 2A: Instruction Set Reference, A-M > + */ > +#if __SIZEOF_LONG__ == 8 > +#define REX_PRE "0x48, " > +#define SCALE_F 8 > +#else > +#define REX_PRE > +#define SCALE_F 4 > +#endif > + > +static int crc32c_probed = 0; > +static int crc32c_intel_available = 0; > + > +static uint32_t crc32c_intel_le_hw_byte(uint32_t crc, unsigned char const > *data, > + unsigned long length) > +{ > + while (length--) { > + __asm__ __volatile__( > + ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1" > + :"=S"(crc) > + :"0"(crc), "c"(*data) > + ); > + data++; > + } > + > + return crc; > +} > + > +/* > + * Steps through buffer one byte at at time, calculates reflected > + * crc using table. > + */ > +static uint32_t crc32c_intel(uint32_t crc, unsigned char const *data, > unsigned long length) > +{ > + unsigned int iquotient = length / SCALE_F; > + unsigned int iremainder = length % SCALE_F; > + unsigned long *ptmp = (unsigned long *)data; > + > + while (iquotient--) { > + __asm__ __volatile__( > + ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;" > + :"=S"(crc) > + :"0"(crc), "c"(*ptmp) > + ); > + ptmp++; > + } > + > + if (iremainder) > + crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp, > + iremainder); > + > + return crc; > +} > + > +static void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, > + unsigned int *edx) > +{ > + int id = *eax; > + > + asm("movl %4, %%eax;" > + "cpuid;" > + "movl %%eax, %0;" > + "movl %%ebx, %1;" > + "movl %%ecx, %2;" > + "movl %%edx, %3;" > + : "=r" (*eax), "=r" (*ebx), "=r" (*ecx), "=r" (*edx) > + : "r" (id) > + : "eax", "ebx", "ecx", "edx"); > +} > + > +static void crc32c_intel_probe(void) > +{ > + if (!crc32c_probed) { > + unsigned int eax, ebx, ecx, edx; > + > + eax = 1; > + > + do_cpuid(&eax, &ebx, &ecx, &edx); > + crc32c_intel_available = (ecx & (1 << 20)) != 0; > + crc32c_probed = 1; > + } > +} > + > +void crc32c_optimization_init(void) > +{ > + crc32c_intel_probe(); > + if (crc32c_intel_available) > + crc_function = crc32c_intel; > +} > +#else > + > +void crc32c_optimization_init(void) > +{ > +} > + > +#endif /* __x86_64__ */ > + > +/* > + * This is the CRC-32C table > + * Generated with: > + * width = 32 bits > + * poly = 0x1EDC6F41 > + * reflect input bytes = true > + * reflect output bytes = true > + */ > + > +static const uint32_t crc32c_table[256] = { > + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, > + 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, > + 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, > + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, > + 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, > + 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, > + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, > + 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, > + 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, > + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, > + 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, > + 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, > + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, > + 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, > + 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, > + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, > + 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, > + 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, > + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, > + 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, > + 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, > + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, > + 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, > + 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, > + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, > + 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, > + 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, > + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, > + 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, > + 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, > + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, > + 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, > + 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, > + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, > + 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, > + 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, > + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, > + 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, > + 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, > + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, > + 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, > + 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, > + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, > + 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, > + 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, > + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, > + 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, > + 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, > + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, > + 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, > + 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, > + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, > + 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, > + 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, > + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, > + 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, > + 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, > + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, > + 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, > + 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, > + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, > + 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, > + 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, > + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L > +}; > + > +/* > + * Steps through buffer one byte at at time, calculates reflected > + * crc using table. > + */ > + > +static uint32_t __crc32c_le(uint32_t crc, unsigned char const *data, size_t > length) > +{ > + while (length--) > + crc = > + crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8); > + return crc; > +} > + > +uint32_t crc32c(uint32_t crc, unsigned char const *data, size_t length) > +{ > + /* Use by-byte access for unaligned buffers */ > + if ((unsigned long)data % sizeof(unsigned long)) > + return __crc32c_le(crc, data, length); > + > + return crc_function(crc, data, length); > +} > diff --git a/gfs2/libgfs2/crc32c.h b/gfs2/libgfs2/crc32c.h > new file mode 100644 > index 0000000..ad06df4 > --- /dev/null > +++ b/gfs2/libgfs2/crc32c.h > @@ -0,0 +1,9 @@ > +#ifndef CRC32C_H > +#define CRC32C_H > +#include <stdlib.h> > +#include <inttypes.h> > + > +uint32_t crc32c(uint32_t seed, unsigned char const *data, size_t length); > +void crc32c_optimization_init(void); > + > +#endif > 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..be79428 100644 > --- a/gfs2/libgfs2/meta.c > +++ b/gfs2/libgfs2/meta.c > @@ -118,7 +118,6 @@ const unsigned int lgfs2_ld1_type_size = > ARRAY_SIZE(lgfs2_ld1_types); > > #define INR(f,...) RF(f.no_formal_ino) \ > RFP(f.no_addr, __VA_ARGS__) > - > #define ANY_COMMON_BLOCK (1 << LGFS2_MT_DIR_LEAF) | \ > (1 << LGFS2_MT_JRNL_DATA) | \ > (1 << LGFS2_MT_EA_ATTR) | \ > @@ -363,6 +362,20 @@ 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) > +RF(__pad) > +#endif > }; > > #undef STRUCT > diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c > index dfb99d1..83c5dad 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,28 @@ 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); > + CPIN_32(lh, str, __pad); > +#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 +601,34 @@ 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); > + CPOUT_32(lh, str, __pad); > +#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 +638,23 @@ 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); > + pv(lh, __pad, "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..8cb55d2 100644 > --- a/gfs2/libgfs2/structures.c > +++ b/gfs2/libgfs2/structures.c > @@ -15,6 +15,7 @@ > > #include "libgfs2.h" > #include "config.h" > +#include "crc32c.h" > > #ifdef GFS2_HAS_UUID > #include <uuid.h> > @@ -102,6 +103,28 @@ 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; > + const unsigned char *lb = (const unsigned char *)buf; > + > + return crc32c(~0, lb + v1_end + sizeof(((struct > gfs2_log_header*)0)->lh_crc), > + bsize - v1_end - sizeof(((struct > gfs2_log_header*)0)->lh_crc)); You could as well just have put in 4 instead of sizeof(((struct gfs2_log_header*)0)->lh_crc) above, crc32c is fundamentally 4 bytes long. > +#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 +135,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; > @@ -129,12 +166,19 @@ int lgfs2_write_journal_data(struct gfs2_inode *ip) > if (bh == NULL) > return -1; > > + crc32c_optimization_init(); > 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 +212,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) > @@ -176,6 +223,7 @@ int write_journal(struct gfs2_inode *jnl, unsigned bsize, > unsigned int blocks) > bmodified(bh); > brelse(bh); > } > + crc32c_optimization_init(); > for (x = 0; x < blocks; x++) { > struct gfs2_buffer_head *bh = get_file_buf(jnl, x, FALSE); > if (!bh) > @@ -185,9 +233,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..764019a 100644 > --- a/gfs2/mkfs/main_jadd.c > +++ b/gfs2/mkfs/main_jadd.c > @@ -21,6 +21,8 @@ > #define _(String) gettext(String) > > #include <linux/types.h> > +#include <linux/fiemap.h> > +#include <linux/fs.h> > #include "libgfs2.h" > #include "gfs2_mkfs.h" > #include "metafs.h" > @@ -238,7 +240,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 +261,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 +277,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 +307,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 +337,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]; > @@ -419,13 +427,35 @@ close: > opts->orig_journals = existing_journals; > } > > +static uint64_t find_block_address(int fd, off_t offset, unsigned bsize) > +{ > + struct { > + struct fiemap fm; > + struct fiemap_extent fe; > + } fme; > + int ret; > + > + fme.fm.fm_start = offset; > + fme.fm.fm_length = 1; > + fme.fm.fm_flags = FIEMAP_FLAG_SYNC; > + fme.fm.fm_extent_count = 1; > + > + ret = ioctl(fd, FS_IOC_FIEMAP, &fme.fm); > + if (ret != 0 || fme.fm.fm_mapped_extents != 1) { > + fprintf(stderr, "Failed to find log header block address\n"); > + return 0; > + } > + return fme.fe.fe_physical / bsize; > +} > + > 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]; > @@ -434,6 +464,7 @@ static void add_j(struct gfs2_sbd *sdp, struct jadd_opts > *opts) > unsigned int x; > struct gfs2_log_header lh; > uint64_t seq = RANDOM(blocks); > + off_t off = 0; > > set_flags(fd, JA_FL_CLEAR, FS_JOURNAL_DATA_FL); > memset(buf, 0, sdp->bsize); > @@ -451,16 +482,24 @@ 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_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 > + ((struct gfs2_log_header *)buf)->lh_addr = > cpu_to_be64( > + find_block_address(fd, > off, sdp->bsize)); > + 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); > @@ -468,6 +507,7 @@ static void add_j(struct gfs2_sbd *sdp, struct jadd_opts > *opts) > > if (++seq == blocks) > seq = 0; > + off += sdp->bsize; > } > > error = fsync(fd); Thanks, Andreas
