1N/A * logfile.h - Exports for $LogFile handling. Part of the Linux-NTFS project. 1N/A * Copyright (c) 2000-2005 Anton Altaparmakov 1N/A * Copyright (c) 2005-2007 Yura Pakhuchiy 1N/A * modify it under the terms of the GNU General Public License as published 1N/A * by the Free Software Foundation; either version 2 of the License, or 1N/A * (at your option) any later version. 1N/A * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1N/A * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1N/A * GNU General Public License for more details. 1N/A * You should have received a copy of the GNU General Public License 1N/A * along with this program (in the main directory of the Linux-NTFS 1N/A * distribution in the file COPYING); if not, write to the Free Software 1N/A * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1N/A * Journal ($LogFile) organization: 1N/A * Two restart areas present in the first two pages (restart pages, one restart 1N/A * area in each page). When the volume is dismounted they should be identical, 1N/A * except for the update sequence array which usually has a different update 1N/A * These are followed by log records organized in pages headed by a log record 1N/A * header going up to log file size. Not all pages contain log records when a 1N/A * volume is first formatted, but as the volume ages, all records will be used. 1N/A * When the log file fills up, the records at the beginning are purged (by 1N/A * modifying the oldest_lsn to a higher value presumably) and writing begins 1N/A * at the beginning of the file. Effectively, the log file is viewed as a 1N/A * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept 1N/A * versions <= 1.x, including 0.-1. (Yes, that is a minus one in there!) We 1N/A * probably only want to support 1.1 as this seems to be the current version 1N/A * and we don't know how that differs from the older versions. The only 1N/A * exception is if the journal is clean as marked by the two restart pages 1N/A * then it doesn't matter whether we are on an earlier version. We can just 1N/A * reinitialize the logfile and start again with version 1.1. 1N/A/* Some $LogFile related constants. */ 1N/A * struct RESTART_PAGE_HEADER - Log file restart page header. 1N/A * Begins the restart area. 1N/A/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 1N/A When creating, set this to be immediately 1N/A after this header structure (without any 1N/A chkdsk. Only used when the magic is changed 1N/A to "CHKD". Otherwise this is zero. */ 1N/A was created, has to be >= 512 and a power of 1N/A 2. Use this to calculate the required size 1N/A of the usa (usa_count) and add it to usa_ofs. 1N/A Then verify that the result is less than the 1N/A value of the restart_area_offset. */ 1N/A 512 and a power of 2. The default is 4096 1N/A and is used when the system page size is 1N/A between 4096 and 8192. Otherwise this is 1N/A set to the system page size instead. */ 1N/A the RESTART_AREA. Value has to be aligned 1N/A to 8-byte boundary. When creating, set this 1N/A to be after the usa. */ 1N/A/* sizeof() = 30 (0x1e) bytes */ 1N/A * Constant for the log client indices meaning that there are no client records 1N/A * in this particular client array. Also inside the client records themselves, 1N/A * this means that there are no client records preceding or following this one. 1N/A#
else /* not __sun */ 1N/A * These are the so far known RESTART_AREA_* flags (16-bit) which contain 1N/A * information about the log file in which they are present. 1N/A /* gcc: Force enum bit width to 16. */ 1N/A * struct RESTART_AREA - Log file restart area record. 1N/A * The offset of this record is found by adding the offset of the 1N/A * RESTART_PAGE_HEADER to the restart_area_offset value found in it. 1N/A * See notes at restart_area_offset above. 1N/A when the restart area was last written. 1N/A This happens often but what is the interval? 1N/A Is it just fixed time or is it every time a 1N/A check point is written or something else? 1N/A On create set to 0. */ 1N/A log client records which follows this 1N/A restart area. Must be 1. */ 1N/A in the array of log client records. 1N/A LOGFILE_NO_CLIENT means that there are no 1N/A free log client records in the array. 1N/A If != LOGFILE_NO_CLIENT, check that 1N/A log_clients > client_free_list. On Win2k 1N/A and presumably earlier, on a clean volume 1N/A this is != LOGFILE_NO_CLIENT, and it should 1N/A be 0, i.e. the first (and only) client 1N/A record is free and thus the logfile is 1N/A closed and hence clean. A dirty volume 1N/A would have left the logfile open and hence 1N/A this would be LOGFILE_NO_CLIENT. On WinXP 1N/A and presumably later, the logfile is always 1N/A open, even on clean shutdown so this should 1N/A always be LOGFILE_NO_CLIENT. */ 1N/A record in the array of log client records. 1N/A LOGFILE_NO_CLIENT means that there are no 1N/A in-use log client records in the array. If 1N/A != LOGFILE_NO_CLIENT check that log_clients 1N/A > client_in_use_list. On Win2k and 1N/A presumably earlier, on a clean volume this 1N/A is LOGFILE_NO_CLIENT, i.e. there are no 1N/A client records in use and thus the logfile 1N/A is closed and hence clean. A dirty volume 1N/A would have left the logfile open and hence 1N/A this would be != LOGFILE_NO_CLIENT, and it 1N/A should be 0, i.e. the first (and only) 1N/A client record is in use. On WinXP and 1N/A presumably later, the logfile is always 1N/A open, even on clean shutdown so this should 1N/A and presumably earlier this is always 0. On 1N/A WinXP and presumably later, if the logfile 1N/A was shutdown cleanly, the second bit, 1N/A RESTART_VOLUME_IS_CLEAN, is set. This bit 1N/A is cleared when the volume is mounted by 1N/A WinXP and set when the volume is dismounted, 1N/A thus if the logfile is dirty, this bit is 1N/A clear. Thus we don't need to check the 1N/A Windows version to determine if the logfile 1N/A is clean. Instead if the logfile is closed, 1N/A we know it must be clean. If it is open and 1N/A this bit is set, we also know it must be 1N/A clean. If on the other hand the logfile is 1N/A open and this bit is clear, we can be almost 1N/A certain that the logfile is dirty. */ 1N/A number. This is calculated as 67 - the 1N/A number of bits required to store the logfile 1N/A size in bytes and this can be used in with 1N/A the specified file_size as a consistency 1N/A client array. Following checks required if 1N/A version matches. Otherwise, skip them. 1N/A restart_area_offset + restart_area_length 1N/A has to be <= system_page_size. Also, 1N/A restart_area_length has to be >= 1N/A client_array_offset + (log_clients * 1N/A sizeof(log client record)). */ 1N/A the first log client record if versions are 1N/A matched. When creating, set this to be 1N/A after this restart area structure, aligned 1N/A to 8-bytes boundary. If the versions do not 1N/A match, this is ignored and the offset is 1N/A assumed to be (sizeof(RESTART_AREA) + 7) & 1N/A ~7, i.e. rounded up to first 8-byte 1N/A boundary. Either way, client_array_offset 1N/A has to be aligned to an 8-byte boundary. 1N/A Also, restart_area_offset + 1N/A client_array_offset has to be <= 510. 1N/A Finally, client_array_offset + (log_clients 1N/A * sizeof(log client record)) has to be <= 1N/A system_page_size. On Win2k and presumably 1N/A earlier, this is 0x30, i.e. immediately 1N/A following this record. On WinXP and 1N/A presumably later, this is 0x40, i.e. there 1N/A are 16 extra bytes between this record and 1N/A the client array. This probably means that 1N/A the RESTART_AREA record is actually bigger 1N/A in WinXP and later. */ 1N/A restart_area_offset + the offset of the 1N/A file_size are > 510 then corruption has 1N/A occurred. This is the very first check when 1N/A starting with the restart_area as if it 1N/A fails it means that some of the above values 1N/A will be corrupted by the multi sector 1N/A transfer protection. The file_size has to 1N/A be rounded down to be a multiple of the 1N/A log_page_size in the RESTART_PAGE_HEADER and 1N/A then it has to be at least big enough to 1N/A store the two restart pages and 48 (0x30) 1N/A log record pages. */ 1N/A the log record header. On create set to 1N/A If the version matches then check that the 1N/A value of log_record_header_length is a 1N/A (log_record_header_length + 7) & ~7 == 1N/A log_record_header_length. When creating set 1N/A it to sizeof(LOG_RECORD_HEADER), aligned to 1N/A page. Must be a multiple of 8. On create 1N/A set it to immediately after the update 1N/A sequence array of the log record page. */ 1N/A time the logfile is restarted which happens 1N/A at mount time when the logfile is opened. 1N/A When creating set to a random value. Win2k 1N/A sets it to the low 32 bits of the current 1N/A/* sizeof() = 48 (0x30) bytes */ 1N/A * struct LOG_CLIENT_RECORD - Log client record. 1N/A * The offset of this record is found by adding the offset of the 1N/A * RESTART_AREA to the client_array_offset value found in it. 1N/A the volume, i.e. the current position within 1N/A the log file. At present, if clean this 1N/A should = current_lsn in restart area but it 1N/A probably also = current_lsn when dirty most 1N/A of the time. At create set to 0. */ 1N/A in the array of log client records. 1N/A LOGFILE_NO_CLIENT means there is no previous 1N/A client record, i.e. this is the first one. 1N/A This is always LOGFILE_NO_CLIENT. */ 1N/A the array of log client records. 1N/A LOGFILE_NO_CLIENT means there are no next 1N/A client records, i.e. this is the last one. 1N/A This is always LOGFILE_NO_CLIENT. */ 1N/A to zero every time the logfile is restarted 1N/A and it is incremented when the logfile is 1N/A closed at dismount time. Thus it is 0 when 1N/A dirty and 1 when clean. On WinXP and 1N/A presumably later, this is always 0. */ 1N/A always be "NTFS" with the remaining bytes 1N/A/* sizeof() = 160 (0xa0) bytes */ 1N/A * struct RECORD_PAGE_HEADER - Log page record page header. 1N/A * Each log page begins with this header and is followed by several LOG_RECORD 1N/A * structures, starting at offset 0x40 (the size of this structure and the 1N/A * following update sequence array and then aligned to 8 byte boundary, but is 1N/A * this specified anywhere?). 1N/A/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 1N/A When creating, set this to be immediately 1N/A after this header structure (without any 1N/A * enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records. 1N/A * (Or is it log record pages?) 1N/A#
else /* not __sun */ 1N/A /* This has nothing to do with the log record. It is only so 1N/A gcc knows to make the flags 16-bit. */ 1N/A * struct LOG_CLIENT_ID - The log client id structure identifying a log client. 1N/A * struct LOG_RECORD - Log record header. 1N/A * Each log record seems to have a constant size of 0x70 bytes. 1N/A/* Now are at ofs 0x30 into struct. */ 1N/A following this entry. */ 1N/A/* Now at ofs 0x40. */ 1N/A/* Now at ofs 0x50. */ 1N/A struct {
/* Only present if lcns_to_follow 1N/A#
endif /* defined _NTFS_LOGFILE_H */