Commit 40796051 authored by Namjae Jeon's avatar Namjae Jeon
Browse files

ntfs: update in-memory, on-disk structures and headers



Update the NTFS filesystem driver's in-memory and on-disk structures:

  - Introduce the  infrastructure and initial support for reparse
    points and EA attribute.
  - Refactor the core ntfs_inode and ntfs_volume structures to support
    new features such as iomap.
  - Remove the unnecessary types.h and endian.h headers.
  - Reorganize the comments in headers for better readability, including
    fixing warnings from checkpatch.pl.

Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
parent 1f662195
Loading
Loading
Loading
Loading

fs/ntfs/aops.h

deleted100644 → 0
+0 −88
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * aops.h - Defines for NTFS kernel address space operations and page cache
 *	    handling.  Part of the Linux-NTFS project.
 *
 * Copyright (c) 2001-2004 Anton Altaparmakov
 * Copyright (c) 2002 Richard Russon
 */

#ifndef _LINUX_NTFS_AOPS_H
#define _LINUX_NTFS_AOPS_H

#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/fs.h>

#include "inode.h"

/**
 * ntfs_unmap_page - release a page that was mapped using ntfs_map_page()
 * @page:	the page to release
 *
 * Unpin, unmap and release a page that was obtained from ntfs_map_page().
 */
static inline void ntfs_unmap_page(struct page *page)
{
	kunmap(page);
	put_page(page);
}

/**
 * ntfs_map_page - map a page into accessible memory, reading it if necessary
 * @mapping:	address space for which to obtain the page
 * @index:	index into the page cache for @mapping of the page to map
 *
 * Read a page from the page cache of the address space @mapping at position
 * @index, where @index is in units of PAGE_SIZE, and not in bytes.
 *
 * If the page is not in memory it is loaded from disk first using the
 * read_folio method defined in the address space operations of @mapping
 * and the page is added to the page cache of @mapping in the process.
 *
 * If the page belongs to an mst protected attribute and it is marked as such
 * in its ntfs inode (NInoMstProtected()) the mst fixups are applied but no
 * error checking is performed.  This means the caller has to verify whether
 * the ntfs record(s) contained in the page are valid or not using one of the
 * ntfs_is_XXXX_record{,p}() macros, where XXXX is the record type you are
 * expecting to see.  (For details of the macros, see fs/ntfs/layout.h.)
 *
 * If the page is in high memory it is mapped into memory directly addressible
 * by the kernel.
 *
 * Finally the page count is incremented, thus pinning the page into place.
 *
 * The above means that page_address(page) can be used on all pages obtained
 * with ntfs_map_page() to get the kernel virtual address of the page.
 *
 * When finished with the page, the caller has to call ntfs_unmap_page() to
 * unpin, unmap and release the page.
 *
 * Note this does not grant exclusive access. If such is desired, the caller
 * must provide it independently of the ntfs_{un}map_page() calls by using
 * a {rw_}semaphore or other means of serialization. A spin lock cannot be
 * used as ntfs_map_page() can block.
 *
 * The unlocked and uptodate page is returned on success or an encoded error
 * on failure. Caller has to test for error using the IS_ERR() macro on the
 * return value. If that evaluates to 'true', the negative error code can be
 * obtained using PTR_ERR() on the return value of ntfs_map_page().
 */
static inline struct page *ntfs_map_page(struct address_space *mapping,
		unsigned long index)
{
	struct page *page = read_mapping_page(mapping, index, NULL);

	if (!IS_ERR(page))
		kmap(page);
	return page;
}

#ifdef NTFS_RW

extern void mark_ntfs_record_dirty(struct page *page, const unsigned int ofs);

#endif /* NTFS_RW */

#endif /* _LINUX_NTFS_AOPS_H */
+128 −66
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * attrib.h - Defines for attribute handling in NTFS Linux kernel driver.
 *	      Part of the Linux-NTFS project.
 * Defines for attribute handling in NTFS Linux kernel driver.
 *
 * Copyright (c) 2001-2005 Anton Altaparmakov
 * Copyright (c) 2002 Richard Russon
 * Copyright (c) 2025 LG Electronics Co., Ltd.
 */

#ifndef _LINUX_NTFS_ATTRIB_H
#define _LINUX_NTFS_ATTRIB_H

#include "endian.h"
#include "types.h"
#include "layout.h"
#include "inode.h"
#include "runlist.h"
#include "volume.h"
#include "ntfs.h"
#include "dir.h"

/**
extern __le16 AT_UNNAMED[];

/*
 * ntfs_attr_search_ctx - used in attribute search functions
 * @mrec: buffer containing mft record to search
 * @mapped_mrec: true if @mrec was mapped by the search functions
 * @attr: attribute record in @mrec where to begin/continue search
 * @is_first: if true ntfs_attr_lookup() begins search with @attr, else after
 * @ntfs_ino: Inode owning this attribute search
 * @al_entry: Current attribute list entry
 * @base_ntfs_ino: Base inode
 * @mapped_base_mrec: true if @base_mrec was mapped by the search
 * @base_attr: Base attribute record pointer
 *
 * Structure must be initialized to zero before the first call to one of the
 * attribute search functions. Initialize @mrec to point to the mft record to
@@ -35,68 +39,126 @@
 * any modification of the search context, to automagically get the next
 * matching attribute.
 */
typedef struct {
	MFT_RECORD *mrec;
	ATTR_RECORD *attr;
struct ntfs_attr_search_ctx {
	struct mft_record *mrec;
	bool mapped_mrec;
	struct attr_record *attr;
	bool is_first;
	ntfs_inode *ntfs_ino;
	ATTR_LIST_ENTRY *al_entry;
	ntfs_inode *base_ntfs_ino;
	MFT_RECORD *base_mrec;
	ATTR_RECORD *base_attr;
} ntfs_attr_search_ctx;

extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn,
		ntfs_attr_search_ctx *ctx);
extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);

extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
	struct ntfs_inode *ntfs_ino;
	struct attr_list_entry *al_entry;
	struct ntfs_inode *base_ntfs_ino;
	struct mft_record *base_mrec;
	bool mapped_base_mrec;
	struct attr_record *base_attr;
};

enum {                  /* ways of processing holes when expanding */
	HOLES_NO,
	HOLES_OK,
};

int ntfs_map_runlist_nolock(struct ntfs_inode *ni, s64 vcn,
		struct ntfs_attr_search_ctx *ctx);
int ntfs_map_runlist(struct ntfs_inode *ni, s64 vcn);
s64 ntfs_attr_vcn_to_lcn_nolock(struct ntfs_inode *ni, const s64 vcn,
		const bool write_locked);

extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni,
		const VCN vcn, ntfs_attr_search_ctx *ctx);

int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
		const u32 name_len, const IGNORE_CASE_BOOL ic,
		const VCN lowest_vcn, const u8 *val, const u32 val_len,
		ntfs_attr_search_ctx *ctx);

extern int load_attribute_list(ntfs_volume *vol, runlist *rl, u8 *al_start,
		const s64 size, const s64 initialized_size);

static inline s64 ntfs_attr_size(const ATTR_RECORD *a)
struct runlist_element *ntfs_attr_find_vcn_nolock(struct ntfs_inode *ni,
		const s64 vcn, struct ntfs_attr_search_ctx *ctx);
struct runlist_element *__ntfs_attr_find_vcn_nolock(struct runlist *runlist,
		const s64 vcn);
int ntfs_attr_map_whole_runlist(struct ntfs_inode *ni);
int ntfs_attr_lookup(const __le32 type, const __le16 *name,
		const u32 name_len, const u32 ic,
		const s64 lowest_vcn, const u8 *val, const u32 val_len,
		struct ntfs_attr_search_ctx *ctx);
int load_attribute_list(struct ntfs_inode *base_ni,
			       u8 *al_start, const s64 size);

static inline s64 ntfs_attr_size(const struct attr_record *a)
{
	if (!a->non_resident)
		return (s64)le32_to_cpu(a->data.resident.value_length);
	return sle64_to_cpu(a->data.non_resident.data_size);
	return le64_to_cpu(a->data.non_resident.data_size);
}

extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx);
extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
		MFT_RECORD *mrec);
extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);

#ifdef NTFS_RW

extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol,
		const ATTR_TYPE type, const s64 size);
extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol,
		const ATTR_TYPE type);
extern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
		const ATTR_TYPE type);

extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
void ntfs_attr_reinit_search_ctx(struct ntfs_attr_search_ctx *ctx);
struct ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(struct ntfs_inode *ni,
		struct mft_record *mrec);
void ntfs_attr_put_search_ctx(struct ntfs_attr_search_ctx *ctx);
int ntfs_attr_size_bounds_check(const struct ntfs_volume *vol,
		const __le32 type, const s64 size);
int ntfs_attr_can_be_resident(const struct ntfs_volume *vol,
		const __le32 type);
int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
		s64 *lcn_count, s64 max_clu_count, bool *balloc, bool update_mp, bool skip_holes);
int ntfs_attr_record_resize(struct mft_record *m, struct attr_record *a, u32 new_size);
int ntfs_resident_attr_value_resize(struct mft_record *m, struct attr_record *a,
		const u32 new_size);

extern int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size);

extern s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size,
		const s64 new_data_size, const s64 data_start);

extern int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt,
int ntfs_attr_make_non_resident(struct ntfs_inode *ni, const u32 data_size);
int ntfs_attr_set(struct ntfs_inode *ni, const s64 ofs, const s64 cnt,
		const u8 val);
int ntfs_attr_set_initialized_size(struct ntfs_inode *ni, loff_t new_size);
int ntfs_attr_open(struct ntfs_inode *ni, const __le32 type,
		__le16 *name, u32 name_len);
void ntfs_attr_close(struct ntfs_inode *n);
int ntfs_attr_fallocate(struct ntfs_inode *ni, loff_t start, loff_t byte_len, bool keep_size);
int ntfs_non_resident_attr_insert_range(struct ntfs_inode *ni, s64 start_vcn, s64 len);
int ntfs_non_resident_attr_collapse_range(struct ntfs_inode *ni, s64 start_vcn, s64 len);
int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64 len);
int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,
		const s64 i_size);
int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloc_size);
int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned int holes);
int ntfs_attr_truncate(struct ntfs_inode *ni, const s64 newsize);
int ntfs_attr_rm(struct ntfs_inode *ni);
int ntfs_attr_exist(struct ntfs_inode *ni, const __le32 type, __le16 *name,
		u32 name_len);
int ntfs_attr_remove(struct ntfs_inode *ni, const __le32 type, __le16 *name,
		u32 name_len);
int ntfs_attr_record_rm(struct ntfs_attr_search_ctx *ctx);
int ntfs_attr_record_move_to(struct ntfs_attr_search_ctx *ctx, struct ntfs_inode *ni);
int ntfs_attr_add(struct ntfs_inode *ni, __le32 type,
		__le16 *name, u8 name_len, u8 *val, s64 size);
int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra);
char *ntfs_attr_name_get(const struct ntfs_volume *vol, const __le16 *uname,
		const int uname_len);
void ntfs_attr_name_free(unsigned char **name);
void *ntfs_attr_readall(struct ntfs_inode *ni, const __le32 type,
		__le16 *name, u32 name_len, s64 *data_size);
int ntfs_resident_attr_record_add(struct ntfs_inode *ni, __le32 type,
		__le16 *name, u8 name_len, u8 *val, u32 size,
		__le16 flags);
int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn);
struct runlist_element *ntfs_attr_vcn_to_rl(struct ntfs_inode *ni, s64 vcn, s64 *lcn);

#endif /* NTFS_RW */

/*
 * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
 * @ctx:	initialised attribute search context
 *
 * Syntactic sugar for walking attributes in an inode.
 *
 * Return 0 on success and -1 on error with errno set to the error code from
 * ntfs_attr_lookup().
 *
 * Example: When you want to enumerate all attributes in an open ntfs inode
 *	    @ni, you can simply do:
 *
 *	int err;
 *	struct ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL);
 *	if (!ctx)
 *		// Error code is in errno. Handle this case.
 *	while (!(err = ntfs_attrs_walk(ctx))) {
 *		struct attr_record *attr = ctx->attr;
 *		// attr now contains the next attribute. Do whatever you want
 *		// with it and then just continue with the while loop.
 *	}
 *	if (err && errno != ENOENT)
 *		// Ooops. An error occurred! You should handle this case.
 *	// Now finished with all attributes in the inode.
 */
static inline int ntfs_attrs_walk(struct ntfs_attr_search_ctx *ctx)
{
	return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
			NULL, 0, ctx);
}
#endif /* _LINUX_NTFS_ATTRIB_H */

fs/ntfs/attrlist.h

0 → 100644
+20 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Exports for attribute list attribute handling.
 *
 * Copyright (c) 2004 Anton Altaparmakov
 * Copyright (c) 2004 Yura Pakhuchiy
 * Copyright (c) 2025 LG Electronics Co., Ltd.
 */

#ifndef _NTFS_ATTRLIST_H
#define _NTFS_ATTRLIST_H

#include "attrib.h"

int ntfs_attrlist_need(struct ntfs_inode *ni);
int ntfs_attrlist_entry_add(struct ntfs_inode *ni, struct attr_record *attr);
int ntfs_attrlist_entry_rm(struct ntfs_attr_search_ctx *ctx);
int ntfs_attrlist_update(struct ntfs_inode *base_ni);

#endif /* defined _NTFS_ATTRLIST_H */
+9 −13
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * bitmap.h - Defines for NTFS kernel bitmap handling.  Part of the Linux-NTFS
 *	      project.
 * Defines for NTFS kernel bitmap handling.
 *
 * Copyright (c) 2004 Anton Altaparmakov
 */
@@ -9,16 +8,15 @@
#ifndef _LINUX_NTFS_BITMAP_H
#define _LINUX_NTFS_BITMAP_H

#ifdef NTFS_RW

#include <linux/fs.h>

#include "types.h"
#include "volume.h"

extern int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
int ntfs_trim_fs(struct ntfs_volume *vol, struct fstrim_range *range);
int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
		const s64 count, const u8 value, const bool is_rollback);

/**
/*
 * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
 * @vi:			vfs inode describing the bitmap
 * @start_bit:		first bit to set
@@ -37,7 +35,7 @@ static inline int ntfs_bitmap_set_bits_in_run(struct inode *vi,
			false);
}

/**
/*
 * ntfs_bitmap_set_run - set a run of bits in a bitmap
 * @vi:		vfs inode describing the bitmap
 * @start_bit:	first bit to set
@@ -54,7 +52,7 @@ static inline int ntfs_bitmap_set_run(struct inode *vi, const s64 start_bit,
	return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 1);
}

/**
/*
 * ntfs_bitmap_clear_run - clear a run of bits in a bitmap
 * @vi:		vfs inode describing the bitmap
 * @start_bit:	first bit to clear
@@ -71,7 +69,7 @@ static inline int ntfs_bitmap_clear_run(struct inode *vi, const s64 start_bit,
	return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 0);
}

/**
/*
 * ntfs_bitmap_set_bit - set a bit in a bitmap
 * @vi:		vfs inode describing the bitmap
 * @bit:	bit to set
@@ -85,7 +83,7 @@ static inline int ntfs_bitmap_set_bit(struct inode *vi, const s64 bit)
	return ntfs_bitmap_set_run(vi, bit, 1);
}

/**
/*
 * ntfs_bitmap_clear_bit - clear a bit in a bitmap
 * @vi:		vfs inode describing the bitmap
 * @bit:	bit to clear
@@ -99,6 +97,4 @@ static inline int ntfs_bitmap_clear_bit(struct inode *vi, const s64 bit)
	return ntfs_bitmap_clear_run(vi, bit, 1);
}

#endif /* NTFS_RW */

#endif /* defined _LINUX_NTFS_BITMAP_H */
+13 −13
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * collate.h - Defines for NTFS kernel collation handling.  Part of the
 *	       Linux-NTFS project.
 * Defines for NTFS kernel collation handling.
 *
 * Copyright (c) 2004 Anton Altaparmakov
 *
 * Part of this file is based on code from the NTFS-3G.
 * and is copyrighted by the respective authors below:
 * Copyright (c) 2004 Anton Altaparmakov
 * Copyright (c) 2005 Yura Pakhuchiy
 */

#ifndef _LINUX_NTFS_COLLATE_H
#define _LINUX_NTFS_COLLATE_H

#include "types.h"
#include "volume.h"

static inline bool ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
static inline bool ntfs_is_collation_rule_supported(__le32 cr)
{
	int i;

	/*
	 * FIXME:  At the moment we only support COLLATION_BINARY and
	 * COLLATION_NTOFS_ULONG, so we return false for everything else for
	 * now.
	 */
	if (unlikely(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG))
	if (unlikely(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG &&
		     cr != COLLATION_FILE_NAME) && cr != COLLATION_NTOFS_ULONGS)
		return false;
	i = le32_to_cpu(cr);
	if (likely(((i >= 0) && (i <= 0x02)) ||
@@ -29,8 +29,8 @@ static inline bool ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
	return false;
}

extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
		const void *data1, const int data1_len,
		const void *data2, const int data2_len);
int ntfs_collate(struct ntfs_volume *vol, __le32 cr,
		const void *data1, const u32 data1_len,
		const void *data2, const u32 data2_len);

#endif /* _LINUX_NTFS_COLLATE_H */
Loading