linux/fs/ntfs3/super.c

// SPDX-License-Identifier: GPL-2.0
/*
 *
 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
 *
 *
 *                 terminology
 *
 * cluster - allocation unit     - 512,1K,2K,4K,...,2M
 * vcn - virtual cluster number  - Offset inside the file in clusters.
 * vbo - virtual byte offset     - Offset inside the file in bytes.
 * lcn - logical cluster number  - 0 based cluster in clusters heap.
 * lbo - logical byte offset     - Absolute position inside volume.
 * run - maps VCN to LCN         - Stored in attributes in packed form.
 * attr - attribute segment      - std/name/data etc records inside MFT.
 * mi  - MFT inode               - One MFT record(usually 1024 bytes or 4K), consists of attributes.
 * ni  - NTFS inode              - Extends linux inode. consists of one or more mft inodes.
 * index - unit inside directory - 2K, 4K, <=page size, does not depend on cluster size.
 *
 * WSL - Windows Subsystem for Linux
 * https://docs.microsoft.com/en-us/windows/wsl/file-permissions
 * It stores uid/gid/mode/dev in xattr
 *
 * ntfs allows up to 2^64 clusters per volume.
 * It means you should use 64 bits lcn to operate with ntfs.
 * Implementation of ntfs.sys uses only 32 bits lcn.
 * Default ntfs3 uses 32 bits lcn too.
 * ntfs3 built with CONFIG_NTFS3_64BIT_CLUSTER (ntfs3_64) uses 64 bits per lcn.
 *
 *
 *     ntfs limits, cluster size is 4K (2^12)
 * -----------------------------------------------------------------------------
 * | Volume size   | Clusters | ntfs.sys | ntfs3  | ntfs3_64 | mkntfs | chkdsk |
 * -----------------------------------------------------------------------------
 * | < 16T, 2^44   |  < 2^32  |  yes     |  yes   |   yes    |  yes   |  yes   |
 * | > 16T, 2^44   |  > 2^32  |  no      |  no    |   yes    |  yes   |  yes   |
 * ----------------------------------------------------------|------------------
 *
 * To mount large volumes as ntfs one should use large cluster size (up to 2M)
 * The maximum volume size in this case is 2^32 * 2^21 = 2^53 = 8P
 *
 *     ntfs limits, cluster size is 2M (2^21)
 * -----------------------------------------------------------------------------
 * | < 8P, 2^53    |  < 2^32  |  yes     |  yes   |   yes    |  yes   |  yes   |
 * | > 8P, 2^53    |  > 2^32  |  no      |  no    |   yes    |  yes   |  yes   |
 * ----------------------------------------------------------|------------------
 *
 */

#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/exportfs.h>
#include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include <linux/log2.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/nls.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/statfs.h>

#include "debug.h"
#include "ntfs.h"
#include "ntfs_fs.h"
#ifdef CONFIG_NTFS3_LZX_XPRESS
#include "lib/lib.h"
#endif

#ifdef CONFIG_PRINTK
/*
 * ntfs_printk - Trace warnings/notices/errors.
 *
 * Thanks Joe Perches <[email protected]> for implementation
 */
void ntfs_printk(const struct super_block *sb, const char *fmt, ...)
{}

static char s_name_buf[512];
static atomic_t s_name_buf_cnt =; // 1 means 'free s_name_buf'.

/*
 * ntfs_inode_printk
 *
 * Print warnings/notices/errors about inode using name or inode number.
 */
void ntfs_inode_printk(struct inode *inode, const char *fmt, ...)
{}
#endif

/*
 * Shared memory struct.
 *
 * On-disk ntfs's upcase table is created by ntfs formatter.
 * 'upcase' table is 128K bytes of memory.
 * We should read it into memory when mounting.
 * Several ntfs volumes likely use the same 'upcase' table.
 * It is good idea to share in-memory 'upcase' table between different volumes.
 * Unfortunately winxp/vista/win7 use different upcase tables.
 */
static DEFINE_SPINLOCK(s_shared_lock);

static struct {} s_shared[8];

/*
 * ntfs_set_shared
 *
 * Return:
 * * @ptr - If pointer was saved in shared memory.
 * * NULL - If pointer was not shared.
 */
void *ntfs_set_shared(void *ptr, u32 bytes)
{}

/*
 * ntfs_put_shared
 *
 * Return:
 * * @ptr - If pointer is not shared anymore.
 * * NULL - If pointer is still shared.
 */
void *ntfs_put_shared(void *ptr)
{}

static inline void put_mount_options(struct ntfs_mount_options *options)
{}

enum Opt {};

// clang-format off
static const struct fs_parameter_spec ntfs_fs_parameters[] =;
// clang-format on

/*
 * Load nls table or if @nls is utf8 then return NULL.
 *
 * It is good idea to use here "const char *nls".
 * But load_nls accepts "char*".
 */
static struct nls_table *ntfs_load_nls(char *nls)
{}

static int ntfs_fs_parse_param(struct fs_context *fc,
			       struct fs_parameter *param)
{}

static int ntfs_fs_reconfigure(struct fs_context *fc)
{}

#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_info_root;

/*
 * ntfs3_volinfo:
 *
 * The content of /proc/fs/ntfs3/<dev>/volinfo
 *
 * ntfs3.1
 * cluster size
 * number of clusters
 * total number of mft records
 * number of used mft records ~= number of files + folders
 * real state of ntfs "dirty"/"clean"
 * current state of ntfs "dirty"/"clean"
*/
static int ntfs3_volinfo(struct seq_file *m, void *o)
{}

static int ntfs3_volinfo_open(struct inode *inode, struct file *file)
{}

/* read /proc/fs/ntfs3/<dev>/label */
static int ntfs3_label_show(struct seq_file *m, void *o)
{}

/* write /proc/fs/ntfs3/<dev>/label */
static ssize_t ntfs3_label_write(struct file *file, const char __user *buffer,
				 size_t count, loff_t *ppos)
{}

static int ntfs3_label_open(struct inode *inode, struct file *file)
{}

static const struct proc_ops ntfs3_volinfo_fops =;

static const struct proc_ops ntfs3_label_fops =;

#endif

static struct kmem_cache *ntfs_inode_cachep;

static struct inode *ntfs_alloc_inode(struct super_block *sb)
{}

static void ntfs_free_inode(struct inode *inode)
{}

static void init_once(void *foo)
{}

/*
 * Noinline to reduce binary size.
 */
static noinline void ntfs3_put_sbi(struct ntfs_sb_info *sbi)
{}

static void ntfs3_free_sbi(struct ntfs_sb_info *sbi)
{}

static void ntfs_put_super(struct super_block *sb)
{}

static int ntfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{}

static int ntfs_show_options(struct seq_file *m, struct dentry *root)
{}

/*
 * ntfs_shutdown - super_operations::shutdown
 */
static void ntfs_shutdown(struct super_block *sb)
{}

/*
 * ntfs_sync_fs - super_operations::sync_fs
 */
static int ntfs_sync_fs(struct super_block *sb, int wait)
{}

static const struct super_operations ntfs_sops =;

static struct inode *ntfs_export_get_inode(struct super_block *sb, u64 ino,
					   u32 generation)
{}

static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
					int fh_len, int fh_type)
{}

static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid,
					int fh_len, int fh_type)
{}

/* TODO: == ntfs_sync_inode */
static int ntfs_nfs_commit_metadata(struct inode *inode)
{}

static const struct export_operations ntfs_export_ops =;

/*
 * format_size_gb - Return Gb,Mb to print with "%u.%02u Gb".
 */
static u32 format_size_gb(const u64 bytes, u32 *mb)
{}

static u32 true_sectors_per_clst(const struct NTFS_BOOT *boot)
{}

/*
 * ntfs_init_from_boot - Init internal info from on-disk boot sector.
 *
 * NTFS mount begins from boot - special formatted 512 bytes.
 * There are two boots: the first and the last 512 bytes of volume.
 * The content of boot is not changed during ntfs life.
 *
 * NOTE: ntfs.sys checks only first (primary) boot.
 * chkdsk checks both boots.
 */
static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
			       u64 dev_size, struct NTFS_BOOT **boot2)
{}

/*
 * ntfs_fill_super - Try to mount.
 */
static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
{}

void ntfs_unmap_meta(struct super_block *sb, CLST lcn, CLST len)
{}

/*
 * ntfs_discard - Issue a discard request (trim for SSD).
 */
int ntfs_discard(struct ntfs_sb_info *sbi, CLST lcn, CLST len)
{}

static int ntfs_fs_get_tree(struct fs_context *fc)
{}

/*
 * ntfs_fs_free - Free fs_context.
 *
 * Note that this will be called after fill_super and reconfigure
 * even when they pass. So they have to take pointers if they pass.
 */
static void ntfs_fs_free(struct fs_context *fc)
{}

// clang-format off
static const struct fs_context_operations ntfs_context_ops =;
// clang-format on

/*
 * ntfs_init_fs_context - Initialize sbi and opts
 *
 * This will called when mount/remount. We will first initialize
 * options so that if remount we can use just that.
 */
static int __ntfs_init_fs_context(struct fs_context *fc)
{}

static int ntfs_init_fs_context(struct fs_context *fc)
{}

static void ntfs3_kill_sb(struct super_block *sb)
{}

// clang-format off
static struct file_system_type ntfs_fs_type =;

#if IS_ENABLED(CONFIG_NTFS_FS)
static int ntfs_legacy_init_fs_context(struct fs_context *fc)
{}

static struct file_system_type ntfs_legacy_fs_type =;
MODULE_ALIAS_FS();

static inline void register_as_ntfs_legacy(void)
{}

static inline void unregister_as_ntfs_legacy(void)
{}
bool is_legacy_ntfs(struct super_block *sb)
{}
#else
static inline void register_as_ntfs_legacy(void) {}
static inline void unregister_as_ntfs_legacy(void) {}
#endif

// clang-format on

static int __init init_ntfs_fs(void)
{}

static void __exit exit_ntfs_fs(void)
{}

MODULE_LICENSE();
MODULE_DESCRIPTION();
#ifdef CONFIG_NTFS3_FS_POSIX_ACL
MODULE_INFO();
#endif
#ifdef CONFIG_NTFS3_64BIT_CLUSTER
MODULE_INFO();
#endif
#ifdef CONFIG_NTFS3_LZX_XPRESS
MODULE_INFO();
#endif

MODULE_AUTHOR();
MODULE_ALIAS_FS();

module_init();
module_exit(exit_ntfs_fs);