162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * logfile.h - Defines for NTFS kernel journal ($LogFile) handling. Part of 462306a36Sopenharmony_ci * the Linux-NTFS project. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2000-2005 Anton Altaparmakov 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef _LINUX_NTFS_LOGFILE_H 1062306a36Sopenharmony_ci#define _LINUX_NTFS_LOGFILE_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifdef NTFS_RW 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/fs.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "types.h" 1762306a36Sopenharmony_ci#include "endian.h" 1862306a36Sopenharmony_ci#include "layout.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* 2162306a36Sopenharmony_ci * Journal ($LogFile) organization: 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Two restart areas present in the first two pages (restart pages, one restart 2462306a36Sopenharmony_ci * area in each page). When the volume is dismounted they should be identical, 2562306a36Sopenharmony_ci * except for the update sequence array which usually has a different update 2662306a36Sopenharmony_ci * sequence number. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * These are followed by log records organized in pages headed by a log record 2962306a36Sopenharmony_ci * header going up to log file size. Not all pages contain log records when a 3062306a36Sopenharmony_ci * volume is first formatted, but as the volume ages, all records will be used. 3162306a36Sopenharmony_ci * When the log file fills up, the records at the beginning are purged (by 3262306a36Sopenharmony_ci * modifying the oldest_lsn to a higher value presumably) and writing begins 3362306a36Sopenharmony_ci * at the beginning of the file. Effectively, the log file is viewed as a 3462306a36Sopenharmony_ci * circular entity. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept 3762306a36Sopenharmony_ci * versions <= 1.x, including 0.-1. (Yes, that is a minus one in there!) We 3862306a36Sopenharmony_ci * probably only want to support 1.1 as this seems to be the current version 3962306a36Sopenharmony_ci * and we don't know how that differs from the older versions. The only 4062306a36Sopenharmony_ci * exception is if the journal is clean as marked by the two restart pages 4162306a36Sopenharmony_ci * then it doesn't matter whether we are on an earlier version. We can just 4262306a36Sopenharmony_ci * reinitialize the logfile and start again with version 1.1. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* Some $LogFile related constants. */ 4662306a36Sopenharmony_ci#define MaxLogFileSize 0x100000000ULL 4762306a36Sopenharmony_ci#define DefaultLogPageSize 4096 4862306a36Sopenharmony_ci#define MinLogRecordPages 48 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* 5162306a36Sopenharmony_ci * Log file restart page header (begins the restart area). 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_citypedef struct { 5462306a36Sopenharmony_ci/*Ofs*/ 5562306a36Sopenharmony_ci/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 5662306a36Sopenharmony_ci/* 0*/ NTFS_RECORD_TYPE magic; /* The magic is "RSTR". */ 5762306a36Sopenharmony_ci/* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h. 5862306a36Sopenharmony_ci When creating, set this to be immediately 5962306a36Sopenharmony_ci after this header structure (without any 6062306a36Sopenharmony_ci alignment). */ 6162306a36Sopenharmony_ci/* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by 6462306a36Sopenharmony_ci chkdsk. Only used when the magic is changed 6562306a36Sopenharmony_ci to "CHKD". Otherwise this is zero. */ 6662306a36Sopenharmony_ci/* 16*/ le32 system_page_size; /* Byte size of system pages when the log file 6762306a36Sopenharmony_ci was created, has to be >= 512 and a power of 6862306a36Sopenharmony_ci 2. Use this to calculate the required size 6962306a36Sopenharmony_ci of the usa (usa_count) and add it to usa_ofs. 7062306a36Sopenharmony_ci Then verify that the result is less than the 7162306a36Sopenharmony_ci value of the restart_area_offset. */ 7262306a36Sopenharmony_ci/* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >= 7362306a36Sopenharmony_ci 512 and a power of 2. The default is 4096 7462306a36Sopenharmony_ci and is used when the system page size is 7562306a36Sopenharmony_ci between 4096 and 8192. Otherwise this is 7662306a36Sopenharmony_ci set to the system page size instead. */ 7762306a36Sopenharmony_ci/* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to 7862306a36Sopenharmony_ci the RESTART_AREA. Value has to be aligned 7962306a36Sopenharmony_ci to 8-byte boundary. When creating, set this 8062306a36Sopenharmony_ci to be after the usa. */ 8162306a36Sopenharmony_ci/* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major 8262306a36Sopenharmony_ci version is 1. */ 8362306a36Sopenharmony_ci/* 28*/ sle16 major_ver; /* Log file major version. We only support 8462306a36Sopenharmony_ci version 1.1. */ 8562306a36Sopenharmony_ci/* sizeof() = 30 (0x1e) bytes */ 8662306a36Sopenharmony_ci} __attribute__ ((__packed__)) RESTART_PAGE_HEADER; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* 8962306a36Sopenharmony_ci * Constant for the log client indices meaning that there are no client records 9062306a36Sopenharmony_ci * in this particular client array. Also inside the client records themselves, 9162306a36Sopenharmony_ci * this means that there are no client records preceding or following this one. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci#define LOGFILE_NO_CLIENT cpu_to_le16(0xffff) 9462306a36Sopenharmony_ci#define LOGFILE_NO_CLIENT_CPU 0xffff 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* 9762306a36Sopenharmony_ci * These are the so far known RESTART_AREA_* flags (16-bit) which contain 9862306a36Sopenharmony_ci * information about the log file in which they are present. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_cienum { 10162306a36Sopenharmony_ci RESTART_VOLUME_IS_CLEAN = cpu_to_le16(0x0002), 10262306a36Sopenharmony_ci RESTART_SPACE_FILLER = cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ 10362306a36Sopenharmony_ci} __attribute__ ((__packed__)); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_citypedef le16 RESTART_AREA_FLAGS; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/* 10862306a36Sopenharmony_ci * Log file restart area record. The offset of this record is found by adding 10962306a36Sopenharmony_ci * the offset of the RESTART_PAGE_HEADER to the restart_area_offset value found 11062306a36Sopenharmony_ci * in it. See notes at restart_area_offset above. 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_citypedef struct { 11362306a36Sopenharmony_ci/*Ofs*/ 11462306a36Sopenharmony_ci/* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log 11562306a36Sopenharmony_ci when the restart area was last written. 11662306a36Sopenharmony_ci This happens often but what is the interval? 11762306a36Sopenharmony_ci Is it just fixed time or is it every time a 11862306a36Sopenharmony_ci check point is written or somethine else? 11962306a36Sopenharmony_ci On create set to 0. */ 12062306a36Sopenharmony_ci/* 8*/ le16 log_clients; /* Number of log client records in the array of 12162306a36Sopenharmony_ci log client records which follows this 12262306a36Sopenharmony_ci restart area. Must be 1. */ 12362306a36Sopenharmony_ci/* 10*/ le16 client_free_list; /* The index of the first free log client record 12462306a36Sopenharmony_ci in the array of log client records. 12562306a36Sopenharmony_ci LOGFILE_NO_CLIENT means that there are no 12662306a36Sopenharmony_ci free log client records in the array. 12762306a36Sopenharmony_ci If != LOGFILE_NO_CLIENT, check that 12862306a36Sopenharmony_ci log_clients > client_free_list. On Win2k 12962306a36Sopenharmony_ci and presumably earlier, on a clean volume 13062306a36Sopenharmony_ci this is != LOGFILE_NO_CLIENT, and it should 13162306a36Sopenharmony_ci be 0, i.e. the first (and only) client 13262306a36Sopenharmony_ci record is free and thus the logfile is 13362306a36Sopenharmony_ci closed and hence clean. A dirty volume 13462306a36Sopenharmony_ci would have left the logfile open and hence 13562306a36Sopenharmony_ci this would be LOGFILE_NO_CLIENT. On WinXP 13662306a36Sopenharmony_ci and presumably later, the logfile is always 13762306a36Sopenharmony_ci open, even on clean shutdown so this should 13862306a36Sopenharmony_ci always be LOGFILE_NO_CLIENT. */ 13962306a36Sopenharmony_ci/* 12*/ le16 client_in_use_list;/* The index of the first in-use log client 14062306a36Sopenharmony_ci record in the array of log client records. 14162306a36Sopenharmony_ci LOGFILE_NO_CLIENT means that there are no 14262306a36Sopenharmony_ci in-use log client records in the array. If 14362306a36Sopenharmony_ci != LOGFILE_NO_CLIENT check that log_clients 14462306a36Sopenharmony_ci > client_in_use_list. On Win2k and 14562306a36Sopenharmony_ci presumably earlier, on a clean volume this 14662306a36Sopenharmony_ci is LOGFILE_NO_CLIENT, i.e. there are no 14762306a36Sopenharmony_ci client records in use and thus the logfile 14862306a36Sopenharmony_ci is closed and hence clean. A dirty volume 14962306a36Sopenharmony_ci would have left the logfile open and hence 15062306a36Sopenharmony_ci this would be != LOGFILE_NO_CLIENT, and it 15162306a36Sopenharmony_ci should be 0, i.e. the first (and only) 15262306a36Sopenharmony_ci client record is in use. On WinXP and 15362306a36Sopenharmony_ci presumably later, the logfile is always 15462306a36Sopenharmony_ci open, even on clean shutdown so this should 15562306a36Sopenharmony_ci always be 0. */ 15662306a36Sopenharmony_ci/* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k 15762306a36Sopenharmony_ci and presumably earlier this is always 0. On 15862306a36Sopenharmony_ci WinXP and presumably later, if the logfile 15962306a36Sopenharmony_ci was shutdown cleanly, the second bit, 16062306a36Sopenharmony_ci RESTART_VOLUME_IS_CLEAN, is set. This bit 16162306a36Sopenharmony_ci is cleared when the volume is mounted by 16262306a36Sopenharmony_ci WinXP and set when the volume is dismounted, 16362306a36Sopenharmony_ci thus if the logfile is dirty, this bit is 16462306a36Sopenharmony_ci clear. Thus we don't need to check the 16562306a36Sopenharmony_ci Windows version to determine if the logfile 16662306a36Sopenharmony_ci is clean. Instead if the logfile is closed, 16762306a36Sopenharmony_ci we know it must be clean. If it is open and 16862306a36Sopenharmony_ci this bit is set, we also know it must be 16962306a36Sopenharmony_ci clean. If on the other hand the logfile is 17062306a36Sopenharmony_ci open and this bit is clear, we can be almost 17162306a36Sopenharmony_ci certain that the logfile is dirty. */ 17262306a36Sopenharmony_ci/* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence 17362306a36Sopenharmony_ci number. This is calculated as 67 - the 17462306a36Sopenharmony_ci number of bits required to store the logfile 17562306a36Sopenharmony_ci size in bytes and this can be used in with 17662306a36Sopenharmony_ci the specified file_size as a consistency 17762306a36Sopenharmony_ci check. */ 17862306a36Sopenharmony_ci/* 20*/ le16 restart_area_length;/* Length of the restart area including the 17962306a36Sopenharmony_ci client array. Following checks required if 18062306a36Sopenharmony_ci version matches. Otherwise, skip them. 18162306a36Sopenharmony_ci restart_area_offset + restart_area_length 18262306a36Sopenharmony_ci has to be <= system_page_size. Also, 18362306a36Sopenharmony_ci restart_area_length has to be >= 18462306a36Sopenharmony_ci client_array_offset + (log_clients * 18562306a36Sopenharmony_ci sizeof(log client record)). */ 18662306a36Sopenharmony_ci/* 22*/ le16 client_array_offset;/* Offset from the start of this record to 18762306a36Sopenharmony_ci the first log client record if versions are 18862306a36Sopenharmony_ci matched. When creating, set this to be 18962306a36Sopenharmony_ci after this restart area structure, aligned 19062306a36Sopenharmony_ci to 8-bytes boundary. If the versions do not 19162306a36Sopenharmony_ci match, this is ignored and the offset is 19262306a36Sopenharmony_ci assumed to be (sizeof(RESTART_AREA) + 7) & 19362306a36Sopenharmony_ci ~7, i.e. rounded up to first 8-byte 19462306a36Sopenharmony_ci boundary. Either way, client_array_offset 19562306a36Sopenharmony_ci has to be aligned to an 8-byte boundary. 19662306a36Sopenharmony_ci Also, restart_area_offset + 19762306a36Sopenharmony_ci client_array_offset has to be <= 510. 19862306a36Sopenharmony_ci Finally, client_array_offset + (log_clients 19962306a36Sopenharmony_ci * sizeof(log client record)) has to be <= 20062306a36Sopenharmony_ci system_page_size. On Win2k and presumably 20162306a36Sopenharmony_ci earlier, this is 0x30, i.e. immediately 20262306a36Sopenharmony_ci following this record. On WinXP and 20362306a36Sopenharmony_ci presumably later, this is 0x40, i.e. there 20462306a36Sopenharmony_ci are 16 extra bytes between this record and 20562306a36Sopenharmony_ci the client array. This probably means that 20662306a36Sopenharmony_ci the RESTART_AREA record is actually bigger 20762306a36Sopenharmony_ci in WinXP and later. */ 20862306a36Sopenharmony_ci/* 24*/ sle64 file_size; /* Usable byte size of the log file. If the 20962306a36Sopenharmony_ci restart_area_offset + the offset of the 21062306a36Sopenharmony_ci file_size are > 510 then corruption has 21162306a36Sopenharmony_ci occurred. This is the very first check when 21262306a36Sopenharmony_ci starting with the restart_area as if it 21362306a36Sopenharmony_ci fails it means that some of the above values 21462306a36Sopenharmony_ci will be corrupted by the multi sector 21562306a36Sopenharmony_ci transfer protection. The file_size has to 21662306a36Sopenharmony_ci be rounded down to be a multiple of the 21762306a36Sopenharmony_ci log_page_size in the RESTART_PAGE_HEADER and 21862306a36Sopenharmony_ci then it has to be at least big enough to 21962306a36Sopenharmony_ci store the two restart pages and 48 (0x30) 22062306a36Sopenharmony_ci log record pages. */ 22162306a36Sopenharmony_ci/* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including 22262306a36Sopenharmony_ci the log record header. On create set to 22362306a36Sopenharmony_ci 0. */ 22462306a36Sopenharmony_ci/* 36*/ le16 log_record_header_length;/* Byte size of the log record header. 22562306a36Sopenharmony_ci If the version matches then check that the 22662306a36Sopenharmony_ci value of log_record_header_length is a 22762306a36Sopenharmony_ci multiple of 8, i.e. 22862306a36Sopenharmony_ci (log_record_header_length + 7) & ~7 == 22962306a36Sopenharmony_ci log_record_header_length. When creating set 23062306a36Sopenharmony_ci it to sizeof(LOG_RECORD_HEADER), aligned to 23162306a36Sopenharmony_ci 8 bytes. */ 23262306a36Sopenharmony_ci/* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record 23362306a36Sopenharmony_ci page. Must be a multiple of 8. On create 23462306a36Sopenharmony_ci set it to immediately after the update 23562306a36Sopenharmony_ci sequence array of the log record page. */ 23662306a36Sopenharmony_ci/* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every 23762306a36Sopenharmony_ci time the logfile is restarted which happens 23862306a36Sopenharmony_ci at mount time when the logfile is opened. 23962306a36Sopenharmony_ci When creating set to a random value. Win2k 24062306a36Sopenharmony_ci sets it to the low 32 bits of the current 24162306a36Sopenharmony_ci system time in NTFS format (see time.h). */ 24262306a36Sopenharmony_ci/* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */ 24362306a36Sopenharmony_ci/* sizeof() = 48 (0x30) bytes */ 24462306a36Sopenharmony_ci} __attribute__ ((__packed__)) RESTART_AREA; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* 24762306a36Sopenharmony_ci * Log client record. The offset of this record is found by adding the offset 24862306a36Sopenharmony_ci * of the RESTART_AREA to the client_array_offset value found in it. 24962306a36Sopenharmony_ci */ 25062306a36Sopenharmony_citypedef struct { 25162306a36Sopenharmony_ci/*Ofs*/ 25262306a36Sopenharmony_ci/* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create 25362306a36Sopenharmony_ci set to 0. */ 25462306a36Sopenharmony_ci/* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart 25562306a36Sopenharmony_ci the volume, i.e. the current position within 25662306a36Sopenharmony_ci the log file. At present, if clean this 25762306a36Sopenharmony_ci should = current_lsn in restart area but it 25862306a36Sopenharmony_ci probably also = current_lsn when dirty most 25962306a36Sopenharmony_ci of the time. At create set to 0. */ 26062306a36Sopenharmony_ci/* 16*/ le16 prev_client; /* The offset to the previous log client record 26162306a36Sopenharmony_ci in the array of log client records. 26262306a36Sopenharmony_ci LOGFILE_NO_CLIENT means there is no previous 26362306a36Sopenharmony_ci client record, i.e. this is the first one. 26462306a36Sopenharmony_ci This is always LOGFILE_NO_CLIENT. */ 26562306a36Sopenharmony_ci/* 18*/ le16 next_client; /* The offset to the next log client record in 26662306a36Sopenharmony_ci the array of log client records. 26762306a36Sopenharmony_ci LOGFILE_NO_CLIENT means there are no next 26862306a36Sopenharmony_ci client records, i.e. this is the last one. 26962306a36Sopenharmony_ci This is always LOGFILE_NO_CLIENT. */ 27062306a36Sopenharmony_ci/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set 27162306a36Sopenharmony_ci to zero every time the logfile is restarted 27262306a36Sopenharmony_ci and it is incremented when the logfile is 27362306a36Sopenharmony_ci closed at dismount time. Thus it is 0 when 27462306a36Sopenharmony_ci dirty and 1 when clean. On WinXP and 27562306a36Sopenharmony_ci presumably later, this is always 0. */ 27662306a36Sopenharmony_ci/* 22*/ u8 reserved[6]; /* Reserved/alignment. */ 27762306a36Sopenharmony_ci/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should 27862306a36Sopenharmony_ci always be 8. */ 27962306a36Sopenharmony_ci/* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should 28062306a36Sopenharmony_ci always be "NTFS" with the remaining bytes 28162306a36Sopenharmony_ci set to 0. */ 28262306a36Sopenharmony_ci/* sizeof() = 160 (0xa0) bytes */ 28362306a36Sopenharmony_ci} __attribute__ ((__packed__)) LOG_CLIENT_RECORD; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciextern bool ntfs_check_logfile(struct inode *log_vi, 28662306a36Sopenharmony_ci RESTART_PAGE_HEADER **rp); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciextern bool ntfs_is_logfile_clean(struct inode *log_vi, 28962306a36Sopenharmony_ci const RESTART_PAGE_HEADER *rp); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ciextern bool ntfs_empty_logfile(struct inode *log_vi); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci#endif /* NTFS_RW */ 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci#endif /* _LINUX_NTFS_LOGFILE_H */ 296