18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * logfile.h - Defines for NTFS kernel journal ($LogFile) handling. Part of 48c2ecf20Sopenharmony_ci * the Linux-NTFS project. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (c) 2000-2005 Anton Altaparmakov 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef _LINUX_NTFS_LOGFILE_H 108c2ecf20Sopenharmony_ci#define _LINUX_NTFS_LOGFILE_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifdef NTFS_RW 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/fs.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "types.h" 178c2ecf20Sopenharmony_ci#include "endian.h" 188c2ecf20Sopenharmony_ci#include "layout.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * Journal ($LogFile) organization: 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Two restart areas present in the first two pages (restart pages, one restart 248c2ecf20Sopenharmony_ci * area in each page). When the volume is dismounted they should be identical, 258c2ecf20Sopenharmony_ci * except for the update sequence array which usually has a different update 268c2ecf20Sopenharmony_ci * sequence number. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * These are followed by log records organized in pages headed by a log record 298c2ecf20Sopenharmony_ci * header going up to log file size. Not all pages contain log records when a 308c2ecf20Sopenharmony_ci * volume is first formatted, but as the volume ages, all records will be used. 318c2ecf20Sopenharmony_ci * When the log file fills up, the records at the beginning are purged (by 328c2ecf20Sopenharmony_ci * modifying the oldest_lsn to a higher value presumably) and writing begins 338c2ecf20Sopenharmony_ci * at the beginning of the file. Effectively, the log file is viewed as a 348c2ecf20Sopenharmony_ci * circular entity. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept 378c2ecf20Sopenharmony_ci * versions <= 1.x, including 0.-1. (Yes, that is a minus one in there!) We 388c2ecf20Sopenharmony_ci * probably only want to support 1.1 as this seems to be the current version 398c2ecf20Sopenharmony_ci * and we don't know how that differs from the older versions. The only 408c2ecf20Sopenharmony_ci * exception is if the journal is clean as marked by the two restart pages 418c2ecf20Sopenharmony_ci * then it doesn't matter whether we are on an earlier version. We can just 428c2ecf20Sopenharmony_ci * reinitialize the logfile and start again with version 1.1. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Some $LogFile related constants. */ 468c2ecf20Sopenharmony_ci#define MaxLogFileSize 0x100000000ULL 478c2ecf20Sopenharmony_ci#define DefaultLogPageSize 4096 488c2ecf20Sopenharmony_ci#define MinLogRecordPages 48 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * Log file restart page header (begins the restart area). 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_citypedef struct { 548c2ecf20Sopenharmony_ci/*Ofs*/ 558c2ecf20Sopenharmony_ci/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 568c2ecf20Sopenharmony_ci/* 0*/ NTFS_RECORD_TYPE magic; /* The magic is "RSTR". */ 578c2ecf20Sopenharmony_ci/* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h. 588c2ecf20Sopenharmony_ci When creating, set this to be immediately 598c2ecf20Sopenharmony_ci after this header structure (without any 608c2ecf20Sopenharmony_ci alignment). */ 618c2ecf20Sopenharmony_ci/* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by 648c2ecf20Sopenharmony_ci chkdsk. Only used when the magic is changed 658c2ecf20Sopenharmony_ci to "CHKD". Otherwise this is zero. */ 668c2ecf20Sopenharmony_ci/* 16*/ le32 system_page_size; /* Byte size of system pages when the log file 678c2ecf20Sopenharmony_ci was created, has to be >= 512 and a power of 688c2ecf20Sopenharmony_ci 2. Use this to calculate the required size 698c2ecf20Sopenharmony_ci of the usa (usa_count) and add it to usa_ofs. 708c2ecf20Sopenharmony_ci Then verify that the result is less than the 718c2ecf20Sopenharmony_ci value of the restart_area_offset. */ 728c2ecf20Sopenharmony_ci/* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >= 738c2ecf20Sopenharmony_ci 512 and a power of 2. The default is 4096 748c2ecf20Sopenharmony_ci and is used when the system page size is 758c2ecf20Sopenharmony_ci between 4096 and 8192. Otherwise this is 768c2ecf20Sopenharmony_ci set to the system page size instead. */ 778c2ecf20Sopenharmony_ci/* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to 788c2ecf20Sopenharmony_ci the RESTART_AREA. Value has to be aligned 798c2ecf20Sopenharmony_ci to 8-byte boundary. When creating, set this 808c2ecf20Sopenharmony_ci to be after the usa. */ 818c2ecf20Sopenharmony_ci/* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major 828c2ecf20Sopenharmony_ci version is 1. */ 838c2ecf20Sopenharmony_ci/* 28*/ sle16 major_ver; /* Log file major version. We only support 848c2ecf20Sopenharmony_ci version 1.1. */ 858c2ecf20Sopenharmony_ci/* sizeof() = 30 (0x1e) bytes */ 868c2ecf20Sopenharmony_ci} __attribute__ ((__packed__)) RESTART_PAGE_HEADER; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* 898c2ecf20Sopenharmony_ci * Constant for the log client indices meaning that there are no client records 908c2ecf20Sopenharmony_ci * in this particular client array. Also inside the client records themselves, 918c2ecf20Sopenharmony_ci * this means that there are no client records preceding or following this one. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci#define LOGFILE_NO_CLIENT cpu_to_le16(0xffff) 948c2ecf20Sopenharmony_ci#define LOGFILE_NO_CLIENT_CPU 0xffff 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* 978c2ecf20Sopenharmony_ci * These are the so far known RESTART_AREA_* flags (16-bit) which contain 988c2ecf20Sopenharmony_ci * information about the log file in which they are present. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_cienum { 1018c2ecf20Sopenharmony_ci RESTART_VOLUME_IS_CLEAN = cpu_to_le16(0x0002), 1028c2ecf20Sopenharmony_ci RESTART_SPACE_FILLER = cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ 1038c2ecf20Sopenharmony_ci} __attribute__ ((__packed__)); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_citypedef le16 RESTART_AREA_FLAGS; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* 1088c2ecf20Sopenharmony_ci * Log file restart area record. The offset of this record is found by adding 1098c2ecf20Sopenharmony_ci * the offset of the RESTART_PAGE_HEADER to the restart_area_offset value found 1108c2ecf20Sopenharmony_ci * in it. See notes at restart_area_offset above. 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_citypedef struct { 1138c2ecf20Sopenharmony_ci/*Ofs*/ 1148c2ecf20Sopenharmony_ci/* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log 1158c2ecf20Sopenharmony_ci when the restart area was last written. 1168c2ecf20Sopenharmony_ci This happens often but what is the interval? 1178c2ecf20Sopenharmony_ci Is it just fixed time or is it every time a 1188c2ecf20Sopenharmony_ci check point is written or somethine else? 1198c2ecf20Sopenharmony_ci On create set to 0. */ 1208c2ecf20Sopenharmony_ci/* 8*/ le16 log_clients; /* Number of log client records in the array of 1218c2ecf20Sopenharmony_ci log client records which follows this 1228c2ecf20Sopenharmony_ci restart area. Must be 1. */ 1238c2ecf20Sopenharmony_ci/* 10*/ le16 client_free_list; /* The index of the first free log client record 1248c2ecf20Sopenharmony_ci in the array of log client records. 1258c2ecf20Sopenharmony_ci LOGFILE_NO_CLIENT means that there are no 1268c2ecf20Sopenharmony_ci free log client records in the array. 1278c2ecf20Sopenharmony_ci If != LOGFILE_NO_CLIENT, check that 1288c2ecf20Sopenharmony_ci log_clients > client_free_list. On Win2k 1298c2ecf20Sopenharmony_ci and presumably earlier, on a clean volume 1308c2ecf20Sopenharmony_ci this is != LOGFILE_NO_CLIENT, and it should 1318c2ecf20Sopenharmony_ci be 0, i.e. the first (and only) client 1328c2ecf20Sopenharmony_ci record is free and thus the logfile is 1338c2ecf20Sopenharmony_ci closed and hence clean. A dirty volume 1348c2ecf20Sopenharmony_ci would have left the logfile open and hence 1358c2ecf20Sopenharmony_ci this would be LOGFILE_NO_CLIENT. On WinXP 1368c2ecf20Sopenharmony_ci and presumably later, the logfile is always 1378c2ecf20Sopenharmony_ci open, even on clean shutdown so this should 1388c2ecf20Sopenharmony_ci always be LOGFILE_NO_CLIENT. */ 1398c2ecf20Sopenharmony_ci/* 12*/ le16 client_in_use_list;/* The index of the first in-use log client 1408c2ecf20Sopenharmony_ci record in the array of log client records. 1418c2ecf20Sopenharmony_ci LOGFILE_NO_CLIENT means that there are no 1428c2ecf20Sopenharmony_ci in-use log client records in the array. If 1438c2ecf20Sopenharmony_ci != LOGFILE_NO_CLIENT check that log_clients 1448c2ecf20Sopenharmony_ci > client_in_use_list. On Win2k and 1458c2ecf20Sopenharmony_ci presumably earlier, on a clean volume this 1468c2ecf20Sopenharmony_ci is LOGFILE_NO_CLIENT, i.e. there are no 1478c2ecf20Sopenharmony_ci client records in use and thus the logfile 1488c2ecf20Sopenharmony_ci is closed and hence clean. A dirty volume 1498c2ecf20Sopenharmony_ci would have left the logfile open and hence 1508c2ecf20Sopenharmony_ci this would be != LOGFILE_NO_CLIENT, and it 1518c2ecf20Sopenharmony_ci should be 0, i.e. the first (and only) 1528c2ecf20Sopenharmony_ci client record is in use. On WinXP and 1538c2ecf20Sopenharmony_ci presumably later, the logfile is always 1548c2ecf20Sopenharmony_ci open, even on clean shutdown so this should 1558c2ecf20Sopenharmony_ci always be 0. */ 1568c2ecf20Sopenharmony_ci/* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k 1578c2ecf20Sopenharmony_ci and presumably earlier this is always 0. On 1588c2ecf20Sopenharmony_ci WinXP and presumably later, if the logfile 1598c2ecf20Sopenharmony_ci was shutdown cleanly, the second bit, 1608c2ecf20Sopenharmony_ci RESTART_VOLUME_IS_CLEAN, is set. This bit 1618c2ecf20Sopenharmony_ci is cleared when the volume is mounted by 1628c2ecf20Sopenharmony_ci WinXP and set when the volume is dismounted, 1638c2ecf20Sopenharmony_ci thus if the logfile is dirty, this bit is 1648c2ecf20Sopenharmony_ci clear. Thus we don't need to check the 1658c2ecf20Sopenharmony_ci Windows version to determine if the logfile 1668c2ecf20Sopenharmony_ci is clean. Instead if the logfile is closed, 1678c2ecf20Sopenharmony_ci we know it must be clean. If it is open and 1688c2ecf20Sopenharmony_ci this bit is set, we also know it must be 1698c2ecf20Sopenharmony_ci clean. If on the other hand the logfile is 1708c2ecf20Sopenharmony_ci open and this bit is clear, we can be almost 1718c2ecf20Sopenharmony_ci certain that the logfile is dirty. */ 1728c2ecf20Sopenharmony_ci/* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence 1738c2ecf20Sopenharmony_ci number. This is calculated as 67 - the 1748c2ecf20Sopenharmony_ci number of bits required to store the logfile 1758c2ecf20Sopenharmony_ci size in bytes and this can be used in with 1768c2ecf20Sopenharmony_ci the specified file_size as a consistency 1778c2ecf20Sopenharmony_ci check. */ 1788c2ecf20Sopenharmony_ci/* 20*/ le16 restart_area_length;/* Length of the restart area including the 1798c2ecf20Sopenharmony_ci client array. Following checks required if 1808c2ecf20Sopenharmony_ci version matches. Otherwise, skip them. 1818c2ecf20Sopenharmony_ci restart_area_offset + restart_area_length 1828c2ecf20Sopenharmony_ci has to be <= system_page_size. Also, 1838c2ecf20Sopenharmony_ci restart_area_length has to be >= 1848c2ecf20Sopenharmony_ci client_array_offset + (log_clients * 1858c2ecf20Sopenharmony_ci sizeof(log client record)). */ 1868c2ecf20Sopenharmony_ci/* 22*/ le16 client_array_offset;/* Offset from the start of this record to 1878c2ecf20Sopenharmony_ci the first log client record if versions are 1888c2ecf20Sopenharmony_ci matched. When creating, set this to be 1898c2ecf20Sopenharmony_ci after this restart area structure, aligned 1908c2ecf20Sopenharmony_ci to 8-bytes boundary. If the versions do not 1918c2ecf20Sopenharmony_ci match, this is ignored and the offset is 1928c2ecf20Sopenharmony_ci assumed to be (sizeof(RESTART_AREA) + 7) & 1938c2ecf20Sopenharmony_ci ~7, i.e. rounded up to first 8-byte 1948c2ecf20Sopenharmony_ci boundary. Either way, client_array_offset 1958c2ecf20Sopenharmony_ci has to be aligned to an 8-byte boundary. 1968c2ecf20Sopenharmony_ci Also, restart_area_offset + 1978c2ecf20Sopenharmony_ci client_array_offset has to be <= 510. 1988c2ecf20Sopenharmony_ci Finally, client_array_offset + (log_clients 1998c2ecf20Sopenharmony_ci * sizeof(log client record)) has to be <= 2008c2ecf20Sopenharmony_ci system_page_size. On Win2k and presumably 2018c2ecf20Sopenharmony_ci earlier, this is 0x30, i.e. immediately 2028c2ecf20Sopenharmony_ci following this record. On WinXP and 2038c2ecf20Sopenharmony_ci presumably later, this is 0x40, i.e. there 2048c2ecf20Sopenharmony_ci are 16 extra bytes between this record and 2058c2ecf20Sopenharmony_ci the client array. This probably means that 2068c2ecf20Sopenharmony_ci the RESTART_AREA record is actually bigger 2078c2ecf20Sopenharmony_ci in WinXP and later. */ 2088c2ecf20Sopenharmony_ci/* 24*/ sle64 file_size; /* Usable byte size of the log file. If the 2098c2ecf20Sopenharmony_ci restart_area_offset + the offset of the 2108c2ecf20Sopenharmony_ci file_size are > 510 then corruption has 2118c2ecf20Sopenharmony_ci occurred. This is the very first check when 2128c2ecf20Sopenharmony_ci starting with the restart_area as if it 2138c2ecf20Sopenharmony_ci fails it means that some of the above values 2148c2ecf20Sopenharmony_ci will be corrupted by the multi sector 2158c2ecf20Sopenharmony_ci transfer protection. The file_size has to 2168c2ecf20Sopenharmony_ci be rounded down to be a multiple of the 2178c2ecf20Sopenharmony_ci log_page_size in the RESTART_PAGE_HEADER and 2188c2ecf20Sopenharmony_ci then it has to be at least big enough to 2198c2ecf20Sopenharmony_ci store the two restart pages and 48 (0x30) 2208c2ecf20Sopenharmony_ci log record pages. */ 2218c2ecf20Sopenharmony_ci/* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including 2228c2ecf20Sopenharmony_ci the log record header. On create set to 2238c2ecf20Sopenharmony_ci 0. */ 2248c2ecf20Sopenharmony_ci/* 36*/ le16 log_record_header_length;/* Byte size of the log record header. 2258c2ecf20Sopenharmony_ci If the version matches then check that the 2268c2ecf20Sopenharmony_ci value of log_record_header_length is a 2278c2ecf20Sopenharmony_ci multiple of 8, i.e. 2288c2ecf20Sopenharmony_ci (log_record_header_length + 7) & ~7 == 2298c2ecf20Sopenharmony_ci log_record_header_length. When creating set 2308c2ecf20Sopenharmony_ci it to sizeof(LOG_RECORD_HEADER), aligned to 2318c2ecf20Sopenharmony_ci 8 bytes. */ 2328c2ecf20Sopenharmony_ci/* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record 2338c2ecf20Sopenharmony_ci page. Must be a multiple of 8. On create 2348c2ecf20Sopenharmony_ci set it to immediately after the update 2358c2ecf20Sopenharmony_ci sequence array of the log record page. */ 2368c2ecf20Sopenharmony_ci/* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every 2378c2ecf20Sopenharmony_ci time the logfile is restarted which happens 2388c2ecf20Sopenharmony_ci at mount time when the logfile is opened. 2398c2ecf20Sopenharmony_ci When creating set to a random value. Win2k 2408c2ecf20Sopenharmony_ci sets it to the low 32 bits of the current 2418c2ecf20Sopenharmony_ci system time in NTFS format (see time.h). */ 2428c2ecf20Sopenharmony_ci/* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */ 2438c2ecf20Sopenharmony_ci/* sizeof() = 48 (0x30) bytes */ 2448c2ecf20Sopenharmony_ci} __attribute__ ((__packed__)) RESTART_AREA; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/* 2478c2ecf20Sopenharmony_ci * Log client record. The offset of this record is found by adding the offset 2488c2ecf20Sopenharmony_ci * of the RESTART_AREA to the client_array_offset value found in it. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_citypedef struct { 2518c2ecf20Sopenharmony_ci/*Ofs*/ 2528c2ecf20Sopenharmony_ci/* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create 2538c2ecf20Sopenharmony_ci set to 0. */ 2548c2ecf20Sopenharmony_ci/* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart 2558c2ecf20Sopenharmony_ci the volume, i.e. the current position within 2568c2ecf20Sopenharmony_ci the log file. At present, if clean this 2578c2ecf20Sopenharmony_ci should = current_lsn in restart area but it 2588c2ecf20Sopenharmony_ci probably also = current_lsn when dirty most 2598c2ecf20Sopenharmony_ci of the time. At create set to 0. */ 2608c2ecf20Sopenharmony_ci/* 16*/ le16 prev_client; /* The offset to the previous log client record 2618c2ecf20Sopenharmony_ci in the array of log client records. 2628c2ecf20Sopenharmony_ci LOGFILE_NO_CLIENT means there is no previous 2638c2ecf20Sopenharmony_ci client record, i.e. this is the first one. 2648c2ecf20Sopenharmony_ci This is always LOGFILE_NO_CLIENT. */ 2658c2ecf20Sopenharmony_ci/* 18*/ le16 next_client; /* The offset to the next log client record in 2668c2ecf20Sopenharmony_ci the array of log client records. 2678c2ecf20Sopenharmony_ci LOGFILE_NO_CLIENT means there are no next 2688c2ecf20Sopenharmony_ci client records, i.e. this is the last one. 2698c2ecf20Sopenharmony_ci This is always LOGFILE_NO_CLIENT. */ 2708c2ecf20Sopenharmony_ci/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set 2718c2ecf20Sopenharmony_ci to zero every time the logfile is restarted 2728c2ecf20Sopenharmony_ci and it is incremented when the logfile is 2738c2ecf20Sopenharmony_ci closed at dismount time. Thus it is 0 when 2748c2ecf20Sopenharmony_ci dirty and 1 when clean. On WinXP and 2758c2ecf20Sopenharmony_ci presumably later, this is always 0. */ 2768c2ecf20Sopenharmony_ci/* 22*/ u8 reserved[6]; /* Reserved/alignment. */ 2778c2ecf20Sopenharmony_ci/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should 2788c2ecf20Sopenharmony_ci always be 8. */ 2798c2ecf20Sopenharmony_ci/* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should 2808c2ecf20Sopenharmony_ci always be "NTFS" with the remaining bytes 2818c2ecf20Sopenharmony_ci set to 0. */ 2828c2ecf20Sopenharmony_ci/* sizeof() = 160 (0xa0) bytes */ 2838c2ecf20Sopenharmony_ci} __attribute__ ((__packed__)) LOG_CLIENT_RECORD; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ciextern bool ntfs_check_logfile(struct inode *log_vi, 2868c2ecf20Sopenharmony_ci RESTART_PAGE_HEADER **rp); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ciextern bool ntfs_is_logfile_clean(struct inode *log_vi, 2898c2ecf20Sopenharmony_ci const RESTART_PAGE_HEADER *rp); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ciextern bool ntfs_empty_logfile(struct inode *log_vi); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci#endif /* NTFS_RW */ 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci#endif /* _LINUX_NTFS_LOGFILE_H */ 296