The Lustre Log Facility ~~~~~~~~~~~~~~~~~~~~~~~ [[llog]] The Lustre log (llog) file may contain a number of different types of data structures, including redo records for uncommitted distributed transactions such as unlink or ownership changes, configuration records for targets and clients, or ChangeLog records to track changes to the filesystem for external consumption, among others. Each llog file begins with an 'llog_log_hdr' that describes the llog file itself, followed by a series of log records that are appended sequentially to the file. Each record, including the header itself, begins with an 'llog_rec_hdr' and ends with an 'llog_rec_tail'. LLOG Log ID ^^^^^^^^^^^ [[struct-llog-logid]] ---- struct llog_logid { struct ost_id lgl_oi; __u32 lgl_ogen; }; ---- The 'llog_logid' structure is used to identify a single Lustre log file. It holds a <> in 'lgl_oi', which is typically a FID. LLog Information ^^^^^^^^^^^^^^^^ [[struct-llogd-body]] ---- struct llogd_body { struct llog_logid lgd_logid; __u32 lgd_ctxt_idx; __u32 lgd_llh_flags; __u32 lgd_index; __u32 lgd_saved_index; __u32 lgd_len; __u64 lgd_cur_offset; }; ---- The lgd_llh_flags are: ---- enum llog_flag { LLOG_F_ZAP_WHEN_EMPTY = 0x1, LLOG_F_IS_CAT = 0x2, LLOG_F_IS_PLAIN = 0x4, }; ---- LLog Record Header ^^^^^^^^^^^^^^^^^^ [[struct-llog-rec-hdr]] ---- struct llog_rec_hdr { __u32 lrh_len; __u32 lrh_index; __u32 lrh_type; __u32 lrh_id; }; ---- The 'llog_rec_hdr' is at the start of each llog record and describes the log record. 'lrh_len' holds the record size in bytes, including the header and tail. 'lrh_index' is the record index within the llog file and is sequentially increasing for each subsequent record. It can be used to determine the offset within the llog file when searching for an arbitrary record within the file. 'lrh_type' describes the type of data stored in this record. ---- enum llog_op_type { LLOG_PAD_MAGIC = LLOG_OP_MAGIC | 0x00000, OST_SZ_REC = LLOG_OP_MAGIC | 0x00f00, MDS_UNLINK64_REC = LLOG_OP_MAGIC | 0x90000 | (MDS_REINT << 8) | REINT_UNLINK, MDS_SETATTR64_REC = LLOG_OP_MAGIC | 0x90000 | (MDS_REINT << 8) | REINT_SETATTR, OBD_CFG_REC = LLOG_OP_MAGIC | 0x20000, LLOG_GEN_REC = LLOG_OP_MAGIC | 0x40000, CHANGELOG_REC = LLOG_OP_MAGIC | 0x60000, CHANGELOG_USER_REC = LLOG_OP_MAGIC | 0x70000, HSM_AGENT_REC = LLOG_OP_MAGIC | 0x80000, UPDATE_REC = LLOG_OP_MAGIC | 0xa0000, LLOG_HDR_MAGIC = LLOG_OP_MAGIC | 0x45539, LLOG_LOGID_MAGIC = LLOG_OP_MAGIC | 0x4553b, }; ---- LLog Record Tail ^^^^^^^^^^^^^^^^ [[struct-llog-rec-tail]] ---- struct llog_rec_tail { __u32 lrt_len; __u32 lrt_index; }; ---- The 'llog_rec_tail' is at the end of each llog record. The 'lrt_len' and 'lrt_index' fields must be the same as 'lrh_len' and 'lrh_index' in the header. They can be used to verify record integrity, as well as allowing processing the llog records in reverse order. LLog Log Header Information ^^^^^^^^^^^^^^^^^^^^^^^^^^^ [[struct-llog-log-hdr]] ---- struct llog_log_hdr { struct llog_rec_hdr llh_hdr; obd_time llh_timestamp; __u32 llh_count; __u32 llh_bitmap_offset; __u32 llh_size; __u32 llh_flags; __u32 llh_cat_idx; /* for a catalog the first plain slot is next to it */ struct obd_uuid llh_tgtuuid; __u32 llh_reserved[LLOG_HEADER_SIZE/sizeof(__u32) - 23]; __u32 llh_bitmap[LLOG_BITMAP_BYTES/sizeof(__u32)]; struct llog_rec_tail llh_tail; }; ---- The llog records start and end on a record size boundary, typically 8192 bytes, or as stored in 'llh_size', which allows some degree of random access within the llog file, even with variable record sizes. It is possible to interpolate the offset of an arbitrary record within the file by estimating the byte offset of a particular record index using 'llh_count' and the llog file size and aligning it to the chunk boundary 'llh_size'. The record index in the 'llog_rec_hdr' of the first record in that chunk can be used to further refine the estimate of the offset of the desired index down to a single chunk, and then sequential access can be used to find the actual record.