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