11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * logfile.h - Defines for NTFS kernel journal ($LogFile) handling. Part of 31da177e4SLinus Torvalds * the Linux-NTFS project. 41da177e4SLinus Torvalds * 5*e7a1033bSAnton Altaparmakov * Copyright (c) 2000-2005 Anton Altaparmakov 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This program/include file is free software; you can redistribute it and/or 81da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License as published 91da177e4SLinus Torvalds * by the Free Software Foundation; either version 2 of the License, or 101da177e4SLinus Torvalds * (at your option) any later version. 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * This program/include file is distributed in the hope that it will be 131da177e4SLinus Torvalds * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 141da177e4SLinus Torvalds * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4SLinus Torvalds * GNU General Public License for more details. 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 181da177e4SLinus Torvalds * along with this program (in the main directory of the Linux-NTFS 191da177e4SLinus Torvalds * distribution in the file COPYING); if not, write to the Free Software 201da177e4SLinus Torvalds * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 211da177e4SLinus Torvalds */ 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds #ifndef _LINUX_NTFS_LOGFILE_H 241da177e4SLinus Torvalds #define _LINUX_NTFS_LOGFILE_H 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #ifdef NTFS_RW 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <linux/fs.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include "types.h" 311da177e4SLinus Torvalds #include "endian.h" 321da177e4SLinus Torvalds #include "layout.h" 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds /* 351da177e4SLinus Torvalds * Journal ($LogFile) organization: 361da177e4SLinus Torvalds * 371da177e4SLinus Torvalds * Two restart areas present in the first two pages (restart pages, one restart 381da177e4SLinus Torvalds * area in each page). When the volume is dismounted they should be identical, 391da177e4SLinus Torvalds * except for the update sequence array which usually has a different update 401da177e4SLinus Torvalds * sequence number. 411da177e4SLinus Torvalds * 421da177e4SLinus Torvalds * These are followed by log records organized in pages headed by a log record 431da177e4SLinus Torvalds * header going up to log file size. Not all pages contain log records when a 441da177e4SLinus Torvalds * volume is first formatted, but as the volume ages, all records will be used. 451da177e4SLinus Torvalds * When the log file fills up, the records at the beginning are purged (by 461da177e4SLinus Torvalds * modifying the oldest_lsn to a higher value presumably) and writing begins 471da177e4SLinus Torvalds * at the beginning of the file. Effectively, the log file is viewed as a 481da177e4SLinus Torvalds * circular entity. 491da177e4SLinus Torvalds * 501da177e4SLinus Torvalds * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept 511da177e4SLinus Torvalds * versions <= 1.x, including 0.-1. (Yes, that is a minus one in there!) We 521da177e4SLinus Torvalds * probably only want to support 1.1 as this seems to be the current version 531da177e4SLinus Torvalds * and we don't know how that differs from the older versions. The only 541da177e4SLinus Torvalds * exception is if the journal is clean as marked by the two restart pages 551da177e4SLinus Torvalds * then it doesn't matter whether we are on an earlier version. We can just 561da177e4SLinus Torvalds * reinitialize the logfile and start again with version 1.1. 571da177e4SLinus Torvalds */ 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds /* Some $LogFile related constants. */ 601da177e4SLinus Torvalds #define MaxLogFileSize 0x100000000ULL 611da177e4SLinus Torvalds #define DefaultLogPageSize 4096 621da177e4SLinus Torvalds #define MinLogRecordPages 48 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds /* 651da177e4SLinus Torvalds * Log file restart page header (begins the restart area). 661da177e4SLinus Torvalds */ 671da177e4SLinus Torvalds typedef struct { 681da177e4SLinus Torvalds /*Ofs*/ 691da177e4SLinus Torvalds /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 701da177e4SLinus Torvalds /* 0*/ NTFS_RECORD_TYPE magic; /* The magic is "RSTR". */ 711da177e4SLinus Torvalds /* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h. 721da177e4SLinus Torvalds When creating, set this to be immediately 731da177e4SLinus Torvalds after this header structure (without any 741da177e4SLinus Torvalds alignment). */ 751da177e4SLinus Torvalds /* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */ 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds /* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by 781da177e4SLinus Torvalds chkdsk. Only used when the magic is changed 791da177e4SLinus Torvalds to "CHKD". Otherwise this is zero. */ 801da177e4SLinus Torvalds /* 16*/ le32 system_page_size; /* Byte size of system pages when the log file 811da177e4SLinus Torvalds was created, has to be >= 512 and a power of 821da177e4SLinus Torvalds 2. Use this to calculate the required size 831da177e4SLinus Torvalds of the usa (usa_count) and add it to usa_ofs. 841da177e4SLinus Torvalds Then verify that the result is less than the 851da177e4SLinus Torvalds value of the restart_area_offset. */ 861da177e4SLinus Torvalds /* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >= 871da177e4SLinus Torvalds 512 and a power of 2. The default is 4096 881da177e4SLinus Torvalds and is used when the system page size is 891da177e4SLinus Torvalds between 4096 and 8192. Otherwise this is 901da177e4SLinus Torvalds set to the system page size instead. */ 911da177e4SLinus Torvalds /* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to 921da177e4SLinus Torvalds the RESTART_AREA. Value has to be aligned 931da177e4SLinus Torvalds to 8-byte boundary. When creating, set this 941da177e4SLinus Torvalds to be after the usa. */ 951da177e4SLinus Torvalds /* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major 961da177e4SLinus Torvalds version is 1. */ 971da177e4SLinus Torvalds /* 28*/ sle16 major_ver; /* Log file major version. We only support 981da177e4SLinus Torvalds version 1.1. */ 991da177e4SLinus Torvalds /* sizeof() = 30 (0x1e) bytes */ 1001da177e4SLinus Torvalds } __attribute__ ((__packed__)) RESTART_PAGE_HEADER; 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds /* 1031da177e4SLinus Torvalds * Constant for the log client indices meaning that there are no client records 1041da177e4SLinus Torvalds * in this particular client array. Also inside the client records themselves, 1051da177e4SLinus Torvalds * this means that there are no client records preceding or following this one. 1061da177e4SLinus Torvalds */ 1071da177e4SLinus Torvalds #define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff) 1081da177e4SLinus Torvalds #define LOGFILE_NO_CLIENT_CPU 0xffff 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds /* 1111da177e4SLinus Torvalds * These are the so far known RESTART_AREA_* flags (16-bit) which contain 1121da177e4SLinus Torvalds * information about the log file in which they are present. 1131da177e4SLinus Torvalds */ 1141da177e4SLinus Torvalds enum { 1151da177e4SLinus Torvalds RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), 1161da177e4SLinus Torvalds RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */ 1171da177e4SLinus Torvalds } __attribute__ ((__packed__)); 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds typedef le16 RESTART_AREA_FLAGS; 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds /* 1221da177e4SLinus Torvalds * Log file restart area record. The offset of this record is found by adding 1231da177e4SLinus Torvalds * the offset of the RESTART_PAGE_HEADER to the restart_area_offset value found 1241da177e4SLinus Torvalds * in it. See notes at restart_area_offset above. 1251da177e4SLinus Torvalds */ 1261da177e4SLinus Torvalds typedef struct { 1271da177e4SLinus Torvalds /*Ofs*/ 1281da177e4SLinus Torvalds /* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log 1291da177e4SLinus Torvalds when the restart area was last written. 1301da177e4SLinus Torvalds This happens often but what is the interval? 1311da177e4SLinus Torvalds Is it just fixed time or is it every time a 1321da177e4SLinus Torvalds check point is written or somethine else? 1331da177e4SLinus Torvalds On create set to 0. */ 1341da177e4SLinus Torvalds /* 8*/ le16 log_clients; /* Number of log client records in the array of 1351da177e4SLinus Torvalds log client records which follows this 1361da177e4SLinus Torvalds restart area. Must be 1. */ 1371da177e4SLinus Torvalds /* 10*/ le16 client_free_list; /* The index of the first free log client record 1381da177e4SLinus Torvalds in the array of log client records. 1391da177e4SLinus Torvalds LOGFILE_NO_CLIENT means that there are no 1401da177e4SLinus Torvalds free log client records in the array. 1411da177e4SLinus Torvalds If != LOGFILE_NO_CLIENT, check that 1421da177e4SLinus Torvalds log_clients > client_free_list. On Win2k 1431da177e4SLinus Torvalds and presumably earlier, on a clean volume 1441da177e4SLinus Torvalds this is != LOGFILE_NO_CLIENT, and it should 1451da177e4SLinus Torvalds be 0, i.e. the first (and only) client 1461da177e4SLinus Torvalds record is free and thus the logfile is 1471da177e4SLinus Torvalds closed and hence clean. A dirty volume 1481da177e4SLinus Torvalds would have left the logfile open and hence 1491da177e4SLinus Torvalds this would be LOGFILE_NO_CLIENT. On WinXP 1501da177e4SLinus Torvalds and presumably later, the logfile is always 1511da177e4SLinus Torvalds open, even on clean shutdown so this should 1521da177e4SLinus Torvalds always be LOGFILE_NO_CLIENT. */ 1531da177e4SLinus Torvalds /* 12*/ le16 client_in_use_list;/* The index of the first in-use log client 1541da177e4SLinus Torvalds record in the array of log client records. 1551da177e4SLinus Torvalds LOGFILE_NO_CLIENT means that there are no 1561da177e4SLinus Torvalds in-use log client records in the array. If 1571da177e4SLinus Torvalds != LOGFILE_NO_CLIENT check that log_clients 1581da177e4SLinus Torvalds > client_in_use_list. On Win2k and 1591da177e4SLinus Torvalds presumably earlier, on a clean volume this 1601da177e4SLinus Torvalds is LOGFILE_NO_CLIENT, i.e. there are no 1611da177e4SLinus Torvalds client records in use and thus the logfile 1621da177e4SLinus Torvalds is closed and hence clean. A dirty volume 1631da177e4SLinus Torvalds would have left the logfile open and hence 1641da177e4SLinus Torvalds this would be != LOGFILE_NO_CLIENT, and it 1651da177e4SLinus Torvalds should be 0, i.e. the first (and only) 1661da177e4SLinus Torvalds client record is in use. On WinXP and 1671da177e4SLinus Torvalds presumably later, the logfile is always 1681da177e4SLinus Torvalds open, even on clean shutdown so this should 1691da177e4SLinus Torvalds always be 0. */ 1701da177e4SLinus Torvalds /* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k 1711da177e4SLinus Torvalds and presumably earlier this is always 0. On 1721da177e4SLinus Torvalds WinXP and presumably later, if the logfile 1731da177e4SLinus Torvalds was shutdown cleanly, the second bit, 1741da177e4SLinus Torvalds RESTART_VOLUME_IS_CLEAN, is set. This bit 1751da177e4SLinus Torvalds is cleared when the volume is mounted by 1761da177e4SLinus Torvalds WinXP and set when the volume is dismounted, 1771da177e4SLinus Torvalds thus if the logfile is dirty, this bit is 1781da177e4SLinus Torvalds clear. Thus we don't need to check the 1791da177e4SLinus Torvalds Windows version to determine if the logfile 1801da177e4SLinus Torvalds is clean. Instead if the logfile is closed, 1811da177e4SLinus Torvalds we know it must be clean. If it is open and 1821da177e4SLinus Torvalds this bit is set, we also know it must be 1831da177e4SLinus Torvalds clean. If on the other hand the logfile is 1841da177e4SLinus Torvalds open and this bit is clear, we can be almost 1851da177e4SLinus Torvalds certain that the logfile is dirty. */ 1861da177e4SLinus Torvalds /* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence 1871da177e4SLinus Torvalds number. This is calculated as 67 - the 1881da177e4SLinus Torvalds number of bits required to store the logfile 1891da177e4SLinus Torvalds size in bytes and this can be used in with 1901da177e4SLinus Torvalds the specified file_size as a consistency 1911da177e4SLinus Torvalds check. */ 1921da177e4SLinus Torvalds /* 20*/ le16 restart_area_length;/* Length of the restart area including the 1931da177e4SLinus Torvalds client array. Following checks required if 1941da177e4SLinus Torvalds version matches. Otherwise, skip them. 1951da177e4SLinus Torvalds restart_area_offset + restart_area_length 1961da177e4SLinus Torvalds has to be <= system_page_size. Also, 1971da177e4SLinus Torvalds restart_area_length has to be >= 1981da177e4SLinus Torvalds client_array_offset + (log_clients * 1991da177e4SLinus Torvalds sizeof(log client record)). */ 2001da177e4SLinus Torvalds /* 22*/ le16 client_array_offset;/* Offset from the start of this record to 2011da177e4SLinus Torvalds the first log client record if versions are 2021da177e4SLinus Torvalds matched. When creating, set this to be 2031da177e4SLinus Torvalds after this restart area structure, aligned 2041da177e4SLinus Torvalds to 8-bytes boundary. If the versions do not 2051da177e4SLinus Torvalds match, this is ignored and the offset is 2061da177e4SLinus Torvalds assumed to be (sizeof(RESTART_AREA) + 7) & 2071da177e4SLinus Torvalds ~7, i.e. rounded up to first 8-byte 2081da177e4SLinus Torvalds boundary. Either way, client_array_offset 2091da177e4SLinus Torvalds has to be aligned to an 8-byte boundary. 2101da177e4SLinus Torvalds Also, restart_area_offset + 2111da177e4SLinus Torvalds client_array_offset has to be <= 510. 2121da177e4SLinus Torvalds Finally, client_array_offset + (log_clients 2131da177e4SLinus Torvalds * sizeof(log client record)) has to be <= 2141da177e4SLinus Torvalds system_page_size. On Win2k and presumably 2151da177e4SLinus Torvalds earlier, this is 0x30, i.e. immediately 2161da177e4SLinus Torvalds following this record. On WinXP and 2171da177e4SLinus Torvalds presumably later, this is 0x40, i.e. there 2181da177e4SLinus Torvalds are 16 extra bytes between this record and 2191da177e4SLinus Torvalds the client array. This probably means that 2201da177e4SLinus Torvalds the RESTART_AREA record is actually bigger 2211da177e4SLinus Torvalds in WinXP and later. */ 2221da177e4SLinus Torvalds /* 24*/ sle64 file_size; /* Usable byte size of the log file. If the 2231da177e4SLinus Torvalds restart_area_offset + the offset of the 2241da177e4SLinus Torvalds file_size are > 510 then corruption has 2251da177e4SLinus Torvalds occured. This is the very first check when 2261da177e4SLinus Torvalds starting with the restart_area as if it 2271da177e4SLinus Torvalds fails it means that some of the above values 2281da177e4SLinus Torvalds will be corrupted by the multi sector 2291da177e4SLinus Torvalds transfer protection. The file_size has to 2301da177e4SLinus Torvalds be rounded down to be a multiple of the 2311da177e4SLinus Torvalds log_page_size in the RESTART_PAGE_HEADER and 2321da177e4SLinus Torvalds then it has to be at least big enough to 2331da177e4SLinus Torvalds store the two restart pages and 48 (0x30) 2341da177e4SLinus Torvalds log record pages. */ 2351da177e4SLinus Torvalds /* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including 2361da177e4SLinus Torvalds the log record header. On create set to 2371da177e4SLinus Torvalds 0. */ 2381da177e4SLinus Torvalds /* 36*/ le16 log_record_header_length;/* Byte size of the log record header. 2391da177e4SLinus Torvalds If the version matches then check that the 2401da177e4SLinus Torvalds value of log_record_header_length is a 2411da177e4SLinus Torvalds multiple of 8, i.e. 2421da177e4SLinus Torvalds (log_record_header_length + 7) & ~7 == 2431da177e4SLinus Torvalds log_record_header_length. When creating set 2441da177e4SLinus Torvalds it to sizeof(LOG_RECORD_HEADER), aligned to 2451da177e4SLinus Torvalds 8 bytes. */ 2461da177e4SLinus Torvalds /* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record 2471da177e4SLinus Torvalds page. Must be a multiple of 8. On create 2481da177e4SLinus Torvalds set it to immediately after the update 2491da177e4SLinus Torvalds sequence array of the log record page. */ 2501da177e4SLinus Torvalds /* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every 2511da177e4SLinus Torvalds time the logfile is restarted which happens 2521da177e4SLinus Torvalds at mount time when the logfile is opened. 2531da177e4SLinus Torvalds When creating set to a random value. Win2k 2541da177e4SLinus Torvalds sets it to the low 32 bits of the current 2551da177e4SLinus Torvalds system time in NTFS format (see time.h). */ 2561da177e4SLinus Torvalds /* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */ 2571da177e4SLinus Torvalds /* sizeof() = 48 (0x30) bytes */ 2581da177e4SLinus Torvalds } __attribute__ ((__packed__)) RESTART_AREA; 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds /* 2611da177e4SLinus Torvalds * Log client record. The offset of this record is found by adding the offset 2621da177e4SLinus Torvalds * of the RESTART_AREA to the client_array_offset value found in it. 2631da177e4SLinus Torvalds */ 2641da177e4SLinus Torvalds typedef struct { 2651da177e4SLinus Torvalds /*Ofs*/ 2661da177e4SLinus Torvalds /* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create 2671da177e4SLinus Torvalds set to 0. */ 2681da177e4SLinus Torvalds /* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart 2691da177e4SLinus Torvalds the volume, i.e. the current position within 2701da177e4SLinus Torvalds the log file. At present, if clean this 2711da177e4SLinus Torvalds should = current_lsn in restart area but it 2721da177e4SLinus Torvalds probably also = current_lsn when dirty most 2731da177e4SLinus Torvalds of the time. At create set to 0. */ 2741da177e4SLinus Torvalds /* 16*/ le16 prev_client; /* The offset to the previous log client record 2751da177e4SLinus Torvalds in the array of log client records. 2761da177e4SLinus Torvalds LOGFILE_NO_CLIENT means there is no previous 2771da177e4SLinus Torvalds client record, i.e. this is the first one. 2781da177e4SLinus Torvalds This is always LOGFILE_NO_CLIENT. */ 2791da177e4SLinus Torvalds /* 18*/ le16 next_client; /* The offset to the next log client record in 2801da177e4SLinus Torvalds the array of log client records. 2811da177e4SLinus Torvalds LOGFILE_NO_CLIENT means there are no next 2821da177e4SLinus Torvalds client records, i.e. this is the last one. 2831da177e4SLinus Torvalds This is always LOGFILE_NO_CLIENT. */ 2841da177e4SLinus Torvalds /* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set 2851da177e4SLinus Torvalds to zero every time the logfile is restarted 2861da177e4SLinus Torvalds and it is incremented when the logfile is 2871da177e4SLinus Torvalds closed at dismount time. Thus it is 0 when 2881da177e4SLinus Torvalds dirty and 1 when clean. On WinXP and 2891da177e4SLinus Torvalds presumably later, this is always 0. */ 2901da177e4SLinus Torvalds /* 22*/ u8 reserved[6]; /* Reserved/alignment. */ 2911da177e4SLinus Torvalds /* 28*/ le32 client_name_length;/* Length of client name in bytes. Should 2921da177e4SLinus Torvalds always be 8. */ 2931da177e4SLinus Torvalds /* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should 2941da177e4SLinus Torvalds always be "NTFS" with the remaining bytes 2951da177e4SLinus Torvalds set to 0. */ 2961da177e4SLinus Torvalds /* sizeof() = 160 (0xa0) bytes */ 2971da177e4SLinus Torvalds } __attribute__ ((__packed__)) LOG_CLIENT_RECORD; 2981da177e4SLinus Torvalds 299*e7a1033bSAnton Altaparmakov extern BOOL ntfs_check_logfile(struct inode *log_vi, 300*e7a1033bSAnton Altaparmakov RESTART_PAGE_HEADER **rp); 3011da177e4SLinus Torvalds 302*e7a1033bSAnton Altaparmakov extern BOOL ntfs_is_logfile_clean(struct inode *log_vi, 303*e7a1033bSAnton Altaparmakov const RESTART_PAGE_HEADER *rp); 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds extern BOOL ntfs_empty_logfile(struct inode *log_vi); 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds #endif /* NTFS_RW */ 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds #endif /* _LINUX_NTFS_LOGFILE_H */ 310