linux/fs/ntfs3/fslog.c

// SPDX-License-Identifier: GPL-2.0
/*
 *
 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
 *
 */

#include <linux/blkdev.h>
#include <linux/fs.h>
#include <linux/random.h>
#include <linux/slab.h>

#include "debug.h"
#include "ntfs.h"
#include "ntfs_fs.h"

/*
 * LOG FILE structs
 */

// clang-format off

#define MaxLogFileSize
#define DefaultLogPageSize
#define MinLogRecordPages

struct RESTART_HDR {};

#define LFS_NO_CLIENT
#define LFS_NO_CLIENT_LE

struct CLIENT_REC {};

static_assert();

/* Two copies of these will exist at the beginning of the log file */
struct RESTART_AREA {};

struct LOG_REC_HDR {};

static_assert();

#define RESTART_ENTRY_ALLOCATED
#define RESTART_ENTRY_ALLOCATED_LE

struct RESTART_TABLE {};

static_assert();

struct ATTR_NAME_ENTRY {};

struct OPEN_ATTR_ENRTY {};

/* 32 bit version of 'struct OPEN_ATTR_ENRTY' */
struct OPEN_ATTR_ENRTY_32 {};

#define SIZEOF_OPENATTRIBUTEENTRY0
// static_assert( 0x2C == sizeof(struct OPEN_ATTR_ENRTY_32) );
static_assert();

/*
 * One entry exists in the Dirty Pages Table for each page which is dirty at
 * the time the Restart Area is written.
 */
struct DIR_PAGE_ENTRY {};

static_assert();

/* 32 bit version of 'struct DIR_PAGE_ENTRY' */
struct DIR_PAGE_ENTRY_32 {};

static_assert();
static_assert();

enum transact_state {};

struct TRANSACTION_ENTRY {};

static_assert();

struct NTFS_RESTART {};

static_assert();

struct NEW_ATTRIBUTE_SIZES {};

struct BITMAP_RANGE {};

struct LCN_RANGE {};

/* The following type defines the different log record types. */
#define LfsClientRecord
#define LfsClientRestart

/* This is used to uniquely identify a client for a particular log file. */
struct CLIENT_ID {};

/* This is the header that begins every Log Record in the log file. */
struct LFS_RECORD_HDR {};

#define LOG_RECORD_MULTI_PAGE

static_assert();

struct LFS_RECORD {};

static_assert();

struct RECORD_PAGE_HDR {};

// clang-format on

// Page contains the end of a log record.
#define LOG_PAGE_LOG_RECORD_END

static inline bool is_log_record_end(const struct RECORD_PAGE_HDR *hdr)
{}

static_assert();

/*
 * END of NTFS LOG structures
 */

/* Define some tuning parameters to keep the restart tables a reasonable size. */
#define INITIAL_NUMBER_TRANSACTIONS

enum NTFS_LOG_OPERATION {};

/*
 * Array for log records which require a target attribute.
 * A true indicates that the corresponding restart operation
 * requires a target attribute.
 */
static const u8 AttributeRequired[] =;

static inline bool is_target_required(u16 op)
{}

static inline bool can_skip_action(enum NTFS_LOG_OPERATION op)
{}

enum {};

/* Bytes per restart table. */
static inline u32 bytes_per_rt(const struct RESTART_TABLE *rt)
{}

/* Log record length. */
static inline u32 lrh_length(const struct LOG_REC_HDR *lr)
{}

struct lcb {};

static void lcb_put(struct lcb *lcb)
{}

/* Find the oldest lsn from active clients. */
static inline void oldest_client_lsn(const struct CLIENT_REC *ca,
				     __le16 next_client, u64 *oldest_lsn)
{}

static inline bool is_rst_page_hdr_valid(u32 file_off,
					 const struct RESTART_HDR *rhdr)
{}

static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr)
{}

static inline bool is_client_area_valid(const struct RESTART_HDR *rhdr,
					bool usa_error)
{}

/*
 * remove_client
 *
 * Remove a client record from a client record list an restart area.
 */
static inline void remove_client(struct CLIENT_REC *ca,
				 const struct CLIENT_REC *cr, __le16 *head)
{}

/*
 * add_client - Add a client record to the start of a list.
 */
static inline void add_client(struct CLIENT_REC *ca, u16 index, __le16 *head)
{}

static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c)
{}

/*
 * find_dp - Search for a @vcn in Dirty Page Table.
 */
static inline struct DIR_PAGE_ENTRY *find_dp(struct RESTART_TABLE *dptbl,
					     u32 target_attr, u64 vcn)
{}

static inline u32 norm_file_page(u32 page_size, u32 *l_size, bool use_default)
{}

static bool check_log_rec(const struct LOG_REC_HDR *lr, u32 bytes, u32 tr,
			  u32 bytes_per_attr_entry)
{}

static bool check_rstbl(const struct RESTART_TABLE *rt, size_t bytes)
{}

/*
 * free_rsttbl_idx - Free a previously allocated index a Restart Table.
 */
static inline void free_rsttbl_idx(struct RESTART_TABLE *rt, u32 off)
{}

static inline struct RESTART_TABLE *init_rsttbl(u16 esize, u16 used)
{}

static inline struct RESTART_TABLE *extend_rsttbl(struct RESTART_TABLE *tbl,
						  u32 add, u32 free_goal)
{}

/*
 * alloc_rsttbl_idx
 *
 * Allocate an index from within a previously initialized Restart Table.
 */
static inline void *alloc_rsttbl_idx(struct RESTART_TABLE **tbl)
{}

/*
 * alloc_rsttbl_from_idx
 *
 * Allocate a specific index from within a previously initialized Restart Table.
 */
static inline void *alloc_rsttbl_from_idx(struct RESTART_TABLE **tbl, u32 vbo)
{}

struct restart_info {};

#define RESTART_SINGLE_PAGE_IO

#define NTFSLOG_WRAPPED
#define NTFSLOG_MULTIPLE_PAGE_IO
#define NTFSLOG_NO_LAST_LSN
#define NTFSLOG_REUSE_TAIL
#define NTFSLOG_NO_OLDEST_LSN

/* Helper struct to work with NTFS $LogFile. */
struct ntfs_log {};

static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn)
{}

/* Compute the offset in the log file of the next log page. */
static inline u32 next_page_off(struct ntfs_log *log, u32 off)
{}

static inline u32 lsn_to_page_off(struct ntfs_log *log, u64 lsn)
{}

static inline u64 vbo_to_lsn(struct ntfs_log *log, u32 off, u64 Seq)
{}

static inline bool is_lsn_in_file(struct ntfs_log *log, u64 lsn)
{}

static inline u32 hdr_file_off(struct ntfs_log *log,
			       struct RECORD_PAGE_HDR *hdr)
{}

static inline u64 base_lsn(struct ntfs_log *log,
			   const struct RECORD_PAGE_HDR *hdr, u64 lsn)
{}

static inline bool verify_client_lsn(struct ntfs_log *log,
				     const struct CLIENT_REC *client, u64 lsn)
{}

static int read_log_page(struct ntfs_log *log, u32 vbo,
			 struct RECORD_PAGE_HDR **buffer, bool *usa_error)
{}

/*
 * log_read_rst
 *
 * It walks through 512 blocks of the file looking for a valid
 * restart page header. It will stop the first time we find a
 * valid page header.
 */
static int log_read_rst(struct ntfs_log *log, bool first,
			struct restart_info *info)
{}

/*
 * Ilog_init_pg_hdr - Init @log from restart page header.
 */
static void log_init_pg_hdr(struct ntfs_log *log, u16 major_ver, u16 minor_ver)
{}

/*
 * log_create - Init @log in cases when we don't have a restart area to use.
 */
static void log_create(struct ntfs_log *log, const u64 last_lsn,
		       u32 open_log_count, bool wrapped, bool use_multi_page)
{}

/*
 * log_create_ra - Fill a restart area from the values stored in @log.
 */
static struct RESTART_AREA *log_create_ra(struct ntfs_log *log)
{}

static u32 final_log_off(struct ntfs_log *log, u64 lsn, u32 data_len)
{}

static int next_log_lsn(struct ntfs_log *log, const struct LFS_RECORD_HDR *rh,
			u64 *lsn)
{}

/*
 * current_log_avail - Calculate the number of bytes available for log records.
 */
static u32 current_log_avail(struct ntfs_log *log)
{}

static bool check_subseq_log_page(struct ntfs_log *log,
				  const struct RECORD_PAGE_HDR *rp, u32 vbo,
				  u64 seq)
{}

/*
 * last_log_lsn
 *
 * Walks through the log pages for a file, searching for the
 * last log page written to the file.
 */
static int last_log_lsn(struct ntfs_log *log)
{}

/*
 * read_log_rec_buf - Copy a log record from the file to a buffer.
 *
 * The log record may span several log pages and may even wrap the file.
 */
static int read_log_rec_buf(struct ntfs_log *log,
			    const struct LFS_RECORD_HDR *rh, void *buffer)
{}

static int read_rst_area(struct ntfs_log *log, struct NTFS_RESTART **rst_,
			 u64 *lsn)
{}

static int find_log_rec(struct ntfs_log *log, u64 lsn, struct lcb *lcb)
{}

/*
 * read_log_rec_lcb - Init the query operation.
 */
static int read_log_rec_lcb(struct ntfs_log *log, u64 lsn, u32 ctx_mode,
			    struct lcb **lcb_)
{}

/*
 * find_client_next_lsn
 *
 * Attempt to find the next lsn to return to a client based on the context mode.
 */
static int find_client_next_lsn(struct ntfs_log *log, struct lcb *lcb, u64 *lsn)
{}

static int read_next_log_rec(struct ntfs_log *log, struct lcb *lcb, u64 *lsn)
{}

bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes)
{}

static inline bool check_index_buffer(const struct INDEX_BUFFER *ib, u32 bytes)
{}

static inline bool check_index_root(const struct ATTRIB *attr,
				    struct ntfs_sb_info *sbi)
{}

static inline bool check_attr(const struct MFT_REC *rec,
			      const struct ATTRIB *attr,
			      struct ntfs_sb_info *sbi)
{}

static inline bool check_file_record(const struct MFT_REC *rec,
				     const struct MFT_REC *rec2,
				     struct ntfs_sb_info *sbi)
{}

static inline int check_lsn(const struct NTFS_RECORD_HEADER *hdr,
			    const u64 *rlsn)
{}

static inline bool check_if_attr(const struct MFT_REC *rec,
				 const struct LOG_REC_HDR *lrh)
{}

static inline bool check_if_index_root(const struct MFT_REC *rec,
				       const struct LOG_REC_HDR *lrh)
{}

static inline bool check_if_root_index(const struct ATTRIB *attr,
				       const struct INDEX_HDR *hdr,
				       const struct LOG_REC_HDR *lrh)
{}

static inline bool check_if_alloc_index(const struct INDEX_HDR *hdr,
					u32 attr_off)
{}

static inline void change_attr_size(struct MFT_REC *rec, struct ATTRIB *attr,
				    u32 nsize)
{}

struct OpenAttr {};

/*
 * cmp_type_and_name
 *
 * Return: 0 if 'attr' has the same type and name.
 */
static inline int cmp_type_and_name(const struct ATTRIB *a1,
				    const struct ATTRIB *a2)
{}

static struct OpenAttr *find_loaded_attr(struct ntfs_log *log,
					 const struct ATTRIB *attr, CLST rno)
{}

static struct ATTRIB *attr_create_nonres_log(struct ntfs_sb_info *sbi,
					     enum ATTR_TYPE type, u64 size,
					     const u16 *name, size_t name_len,
					     __le16 flags)
{}

/*
 * do_action - Common routine for the Redo and Undo Passes.
 * @rlsn: If it is NULL then undo.
 */
static int do_action(struct ntfs_log *log, struct OPEN_ATTR_ENRTY *oe,
		     const struct LOG_REC_HDR *lrh, u32 op, void *data,
		     u32 dlen, u32 rec_len, const u64 *rlsn)
{}

/*
 * log_replay - Replays log and empties it.
 *
 * This function is called during mount operation.
 * It replays log and empties it.
 * Initialized is set false if logfile contains '-1'.
 */
int log_replay(struct ntfs_inode *ni, bool *initialized)
{}