162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2001-2012 Anton Altaparmakov and Tuxera Inc. 662306a36Sopenharmony_ci * Copyright (c) 2001,2002 Richard Russon 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/stddef.h> 1162306a36Sopenharmony_ci#include <linux/init.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/string.h> 1462306a36Sopenharmony_ci#include <linux/spinlock.h> 1562306a36Sopenharmony_ci#include <linux/blkdev.h> /* For bdev_logical_block_size(). */ 1662306a36Sopenharmony_ci#include <linux/backing-dev.h> 1762306a36Sopenharmony_ci#include <linux/buffer_head.h> 1862306a36Sopenharmony_ci#include <linux/vfs.h> 1962306a36Sopenharmony_ci#include <linux/moduleparam.h> 2062306a36Sopenharmony_ci#include <linux/bitmap.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "sysctl.h" 2362306a36Sopenharmony_ci#include "logfile.h" 2462306a36Sopenharmony_ci#include "quota.h" 2562306a36Sopenharmony_ci#include "usnjrnl.h" 2662306a36Sopenharmony_ci#include "dir.h" 2762306a36Sopenharmony_ci#include "debug.h" 2862306a36Sopenharmony_ci#include "index.h" 2962306a36Sopenharmony_ci#include "inode.h" 3062306a36Sopenharmony_ci#include "aops.h" 3162306a36Sopenharmony_ci#include "layout.h" 3262306a36Sopenharmony_ci#include "malloc.h" 3362306a36Sopenharmony_ci#include "ntfs.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* Number of mounted filesystems which have compression enabled. */ 3662306a36Sopenharmony_cistatic unsigned long ntfs_nr_compression_users; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* A global default upcase table and a corresponding reference count. */ 3962306a36Sopenharmony_cistatic ntfschar *default_upcase; 4062306a36Sopenharmony_cistatic unsigned long ntfs_nr_upcase_users; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* Error constants/strings used in inode.c::ntfs_show_options(). */ 4362306a36Sopenharmony_citypedef enum { 4462306a36Sopenharmony_ci /* One of these must be present, default is ON_ERRORS_CONTINUE. */ 4562306a36Sopenharmony_ci ON_ERRORS_PANIC = 0x01, 4662306a36Sopenharmony_ci ON_ERRORS_REMOUNT_RO = 0x02, 4762306a36Sopenharmony_ci ON_ERRORS_CONTINUE = 0x04, 4862306a36Sopenharmony_ci /* Optional, can be combined with any of the above. */ 4962306a36Sopenharmony_ci ON_ERRORS_RECOVER = 0x10, 5062306a36Sopenharmony_ci} ON_ERRORS_ACTIONS; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciconst option_t on_errors_arr[] = { 5362306a36Sopenharmony_ci { ON_ERRORS_PANIC, "panic" }, 5462306a36Sopenharmony_ci { ON_ERRORS_REMOUNT_RO, "remount-ro", }, 5562306a36Sopenharmony_ci { ON_ERRORS_CONTINUE, "continue", }, 5662306a36Sopenharmony_ci { ON_ERRORS_RECOVER, "recover" }, 5762306a36Sopenharmony_ci { 0, NULL } 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/** 6162306a36Sopenharmony_ci * simple_getbool - convert input string to a boolean value 6262306a36Sopenharmony_ci * @s: input string to convert 6362306a36Sopenharmony_ci * @setval: where to store the output boolean value 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * Copied from old ntfs driver (which copied from vfat driver). 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * "1", "yes", "true", or an empty string are converted to %true. 6862306a36Sopenharmony_ci * "0", "no", and "false" are converted to %false. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Return: %1 if the string is converted or was empty and *setval contains it; 7162306a36Sopenharmony_ci * %0 if the string was not valid. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_cistatic int simple_getbool(char *s, bool *setval) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci if (s) { 7662306a36Sopenharmony_ci if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true")) 7762306a36Sopenharmony_ci *setval = true; 7862306a36Sopenharmony_ci else if (!strcmp(s, "0") || !strcmp(s, "no") || 7962306a36Sopenharmony_ci !strcmp(s, "false")) 8062306a36Sopenharmony_ci *setval = false; 8162306a36Sopenharmony_ci else 8262306a36Sopenharmony_ci return 0; 8362306a36Sopenharmony_ci } else 8462306a36Sopenharmony_ci *setval = true; 8562306a36Sopenharmony_ci return 1; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/** 8962306a36Sopenharmony_ci * parse_options - parse the (re)mount options 9062306a36Sopenharmony_ci * @vol: ntfs volume 9162306a36Sopenharmony_ci * @opt: string containing the (re)mount options 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * Parse the recognized options in @opt for the ntfs volume described by @vol. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_cistatic bool parse_options(ntfs_volume *vol, char *opt) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci char *p, *v, *ov; 9862306a36Sopenharmony_ci static char *utf8 = "utf8"; 9962306a36Sopenharmony_ci int errors = 0, sloppy = 0; 10062306a36Sopenharmony_ci kuid_t uid = INVALID_UID; 10162306a36Sopenharmony_ci kgid_t gid = INVALID_GID; 10262306a36Sopenharmony_ci umode_t fmask = (umode_t)-1, dmask = (umode_t)-1; 10362306a36Sopenharmony_ci int mft_zone_multiplier = -1, on_errors = -1; 10462306a36Sopenharmony_ci int show_sys_files = -1, case_sensitive = -1, disable_sparse = -1; 10562306a36Sopenharmony_ci struct nls_table *nls_map = NULL, *old_nls; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* I am lazy... (-8 */ 10862306a36Sopenharmony_ci#define NTFS_GETOPT_WITH_DEFAULT(option, variable, default_value) \ 10962306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 11062306a36Sopenharmony_ci if (!v || !*v) \ 11162306a36Sopenharmony_ci variable = default_value; \ 11262306a36Sopenharmony_ci else { \ 11362306a36Sopenharmony_ci variable = simple_strtoul(ov = v, &v, 0); \ 11462306a36Sopenharmony_ci if (*v) \ 11562306a36Sopenharmony_ci goto needs_val; \ 11662306a36Sopenharmony_ci } \ 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci#define NTFS_GETOPT(option, variable) \ 11962306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 12062306a36Sopenharmony_ci if (!v || !*v) \ 12162306a36Sopenharmony_ci goto needs_arg; \ 12262306a36Sopenharmony_ci variable = simple_strtoul(ov = v, &v, 0); \ 12362306a36Sopenharmony_ci if (*v) \ 12462306a36Sopenharmony_ci goto needs_val; \ 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci#define NTFS_GETOPT_UID(option, variable) \ 12762306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 12862306a36Sopenharmony_ci uid_t uid_value; \ 12962306a36Sopenharmony_ci if (!v || !*v) \ 13062306a36Sopenharmony_ci goto needs_arg; \ 13162306a36Sopenharmony_ci uid_value = simple_strtoul(ov = v, &v, 0); \ 13262306a36Sopenharmony_ci if (*v) \ 13362306a36Sopenharmony_ci goto needs_val; \ 13462306a36Sopenharmony_ci variable = make_kuid(current_user_ns(), uid_value); \ 13562306a36Sopenharmony_ci if (!uid_valid(variable)) \ 13662306a36Sopenharmony_ci goto needs_val; \ 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci#define NTFS_GETOPT_GID(option, variable) \ 13962306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 14062306a36Sopenharmony_ci gid_t gid_value; \ 14162306a36Sopenharmony_ci if (!v || !*v) \ 14262306a36Sopenharmony_ci goto needs_arg; \ 14362306a36Sopenharmony_ci gid_value = simple_strtoul(ov = v, &v, 0); \ 14462306a36Sopenharmony_ci if (*v) \ 14562306a36Sopenharmony_ci goto needs_val; \ 14662306a36Sopenharmony_ci variable = make_kgid(current_user_ns(), gid_value); \ 14762306a36Sopenharmony_ci if (!gid_valid(variable)) \ 14862306a36Sopenharmony_ci goto needs_val; \ 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci#define NTFS_GETOPT_OCTAL(option, variable) \ 15162306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 15262306a36Sopenharmony_ci if (!v || !*v) \ 15362306a36Sopenharmony_ci goto needs_arg; \ 15462306a36Sopenharmony_ci variable = simple_strtoul(ov = v, &v, 8); \ 15562306a36Sopenharmony_ci if (*v) \ 15662306a36Sopenharmony_ci goto needs_val; \ 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci#define NTFS_GETOPT_BOOL(option, variable) \ 15962306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 16062306a36Sopenharmony_ci bool val; \ 16162306a36Sopenharmony_ci if (!simple_getbool(v, &val)) \ 16262306a36Sopenharmony_ci goto needs_bool; \ 16362306a36Sopenharmony_ci variable = val; \ 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci#define NTFS_GETOPT_OPTIONS_ARRAY(option, variable, opt_array) \ 16662306a36Sopenharmony_ci if (!strcmp(p, option)) { \ 16762306a36Sopenharmony_ci int _i; \ 16862306a36Sopenharmony_ci if (!v || !*v) \ 16962306a36Sopenharmony_ci goto needs_arg; \ 17062306a36Sopenharmony_ci ov = v; \ 17162306a36Sopenharmony_ci if (variable == -1) \ 17262306a36Sopenharmony_ci variable = 0; \ 17362306a36Sopenharmony_ci for (_i = 0; opt_array[_i].str && *opt_array[_i].str; _i++) \ 17462306a36Sopenharmony_ci if (!strcmp(opt_array[_i].str, v)) { \ 17562306a36Sopenharmony_ci variable |= opt_array[_i].val; \ 17662306a36Sopenharmony_ci break; \ 17762306a36Sopenharmony_ci } \ 17862306a36Sopenharmony_ci if (!opt_array[_i].str || !*opt_array[_i].str) \ 17962306a36Sopenharmony_ci goto needs_val; \ 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci if (!opt || !*opt) 18262306a36Sopenharmony_ci goto no_mount_options; 18362306a36Sopenharmony_ci ntfs_debug("Entering with mount options string: %s", opt); 18462306a36Sopenharmony_ci while ((p = strsep(&opt, ","))) { 18562306a36Sopenharmony_ci if ((v = strchr(p, '='))) 18662306a36Sopenharmony_ci *v++ = 0; 18762306a36Sopenharmony_ci NTFS_GETOPT_UID("uid", uid) 18862306a36Sopenharmony_ci else NTFS_GETOPT_GID("gid", gid) 18962306a36Sopenharmony_ci else NTFS_GETOPT_OCTAL("umask", fmask = dmask) 19062306a36Sopenharmony_ci else NTFS_GETOPT_OCTAL("fmask", fmask) 19162306a36Sopenharmony_ci else NTFS_GETOPT_OCTAL("dmask", dmask) 19262306a36Sopenharmony_ci else NTFS_GETOPT("mft_zone_multiplier", mft_zone_multiplier) 19362306a36Sopenharmony_ci else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, true) 19462306a36Sopenharmony_ci else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files) 19562306a36Sopenharmony_ci else NTFS_GETOPT_BOOL("case_sensitive", case_sensitive) 19662306a36Sopenharmony_ci else NTFS_GETOPT_BOOL("disable_sparse", disable_sparse) 19762306a36Sopenharmony_ci else NTFS_GETOPT_OPTIONS_ARRAY("errors", on_errors, 19862306a36Sopenharmony_ci on_errors_arr) 19962306a36Sopenharmony_ci else if (!strcmp(p, "posix") || !strcmp(p, "show_inodes")) 20062306a36Sopenharmony_ci ntfs_warning(vol->sb, "Ignoring obsolete option %s.", 20162306a36Sopenharmony_ci p); 20262306a36Sopenharmony_ci else if (!strcmp(p, "nls") || !strcmp(p, "iocharset")) { 20362306a36Sopenharmony_ci if (!strcmp(p, "iocharset")) 20462306a36Sopenharmony_ci ntfs_warning(vol->sb, "Option iocharset is " 20562306a36Sopenharmony_ci "deprecated. Please use " 20662306a36Sopenharmony_ci "option nls=<charsetname> in " 20762306a36Sopenharmony_ci "the future."); 20862306a36Sopenharmony_ci if (!v || !*v) 20962306a36Sopenharmony_ci goto needs_arg; 21062306a36Sopenharmony_ciuse_utf8: 21162306a36Sopenharmony_ci old_nls = nls_map; 21262306a36Sopenharmony_ci nls_map = load_nls(v); 21362306a36Sopenharmony_ci if (!nls_map) { 21462306a36Sopenharmony_ci if (!old_nls) { 21562306a36Sopenharmony_ci ntfs_error(vol->sb, "NLS character set " 21662306a36Sopenharmony_ci "%s not found.", v); 21762306a36Sopenharmony_ci return false; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci ntfs_error(vol->sb, "NLS character set %s not " 22062306a36Sopenharmony_ci "found. Using previous one %s.", 22162306a36Sopenharmony_ci v, old_nls->charset); 22262306a36Sopenharmony_ci nls_map = old_nls; 22362306a36Sopenharmony_ci } else /* nls_map */ { 22462306a36Sopenharmony_ci unload_nls(old_nls); 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci } else if (!strcmp(p, "utf8")) { 22762306a36Sopenharmony_ci bool val = false; 22862306a36Sopenharmony_ci ntfs_warning(vol->sb, "Option utf8 is no longer " 22962306a36Sopenharmony_ci "supported, using option nls=utf8. Please " 23062306a36Sopenharmony_ci "use option nls=utf8 in the future and " 23162306a36Sopenharmony_ci "make sure utf8 is compiled either as a " 23262306a36Sopenharmony_ci "module or into the kernel."); 23362306a36Sopenharmony_ci if (!v || !*v) 23462306a36Sopenharmony_ci val = true; 23562306a36Sopenharmony_ci else if (!simple_getbool(v, &val)) 23662306a36Sopenharmony_ci goto needs_bool; 23762306a36Sopenharmony_ci if (val) { 23862306a36Sopenharmony_ci v = utf8; 23962306a36Sopenharmony_ci goto use_utf8; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci } else { 24262306a36Sopenharmony_ci ntfs_error(vol->sb, "Unrecognized mount option %s.", p); 24362306a36Sopenharmony_ci if (errors < INT_MAX) 24462306a36Sopenharmony_ci errors++; 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci#undef NTFS_GETOPT_OPTIONS_ARRAY 24762306a36Sopenharmony_ci#undef NTFS_GETOPT_BOOL 24862306a36Sopenharmony_ci#undef NTFS_GETOPT 24962306a36Sopenharmony_ci#undef NTFS_GETOPT_WITH_DEFAULT 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_cino_mount_options: 25262306a36Sopenharmony_ci if (errors && !sloppy) 25362306a36Sopenharmony_ci return false; 25462306a36Sopenharmony_ci if (sloppy) 25562306a36Sopenharmony_ci ntfs_warning(vol->sb, "Sloppy option given. Ignoring " 25662306a36Sopenharmony_ci "unrecognized mount option(s) and continuing."); 25762306a36Sopenharmony_ci /* Keep this first! */ 25862306a36Sopenharmony_ci if (on_errors != -1) { 25962306a36Sopenharmony_ci if (!on_errors) { 26062306a36Sopenharmony_ci ntfs_error(vol->sb, "Invalid errors option argument " 26162306a36Sopenharmony_ci "or bug in options parser."); 26262306a36Sopenharmony_ci return false; 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci if (nls_map) { 26662306a36Sopenharmony_ci if (vol->nls_map && vol->nls_map != nls_map) { 26762306a36Sopenharmony_ci ntfs_error(vol->sb, "Cannot change NLS character set " 26862306a36Sopenharmony_ci "on remount."); 26962306a36Sopenharmony_ci return false; 27062306a36Sopenharmony_ci } /* else (!vol->nls_map) */ 27162306a36Sopenharmony_ci ntfs_debug("Using NLS character set %s.", nls_map->charset); 27262306a36Sopenharmony_ci vol->nls_map = nls_map; 27362306a36Sopenharmony_ci } else /* (!nls_map) */ { 27462306a36Sopenharmony_ci if (!vol->nls_map) { 27562306a36Sopenharmony_ci vol->nls_map = load_nls_default(); 27662306a36Sopenharmony_ci if (!vol->nls_map) { 27762306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load default " 27862306a36Sopenharmony_ci "NLS character set."); 27962306a36Sopenharmony_ci return false; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci ntfs_debug("Using default NLS character set (%s).", 28262306a36Sopenharmony_ci vol->nls_map->charset); 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci if (mft_zone_multiplier != -1) { 28662306a36Sopenharmony_ci if (vol->mft_zone_multiplier && vol->mft_zone_multiplier != 28762306a36Sopenharmony_ci mft_zone_multiplier) { 28862306a36Sopenharmony_ci ntfs_error(vol->sb, "Cannot change mft_zone_multiplier " 28962306a36Sopenharmony_ci "on remount."); 29062306a36Sopenharmony_ci return false; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci if (mft_zone_multiplier < 1 || mft_zone_multiplier > 4) { 29362306a36Sopenharmony_ci ntfs_error(vol->sb, "Invalid mft_zone_multiplier. " 29462306a36Sopenharmony_ci "Using default value, i.e. 1."); 29562306a36Sopenharmony_ci mft_zone_multiplier = 1; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci vol->mft_zone_multiplier = mft_zone_multiplier; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci if (!vol->mft_zone_multiplier) 30062306a36Sopenharmony_ci vol->mft_zone_multiplier = 1; 30162306a36Sopenharmony_ci if (on_errors != -1) 30262306a36Sopenharmony_ci vol->on_errors = on_errors; 30362306a36Sopenharmony_ci if (!vol->on_errors || vol->on_errors == ON_ERRORS_RECOVER) 30462306a36Sopenharmony_ci vol->on_errors |= ON_ERRORS_CONTINUE; 30562306a36Sopenharmony_ci if (uid_valid(uid)) 30662306a36Sopenharmony_ci vol->uid = uid; 30762306a36Sopenharmony_ci if (gid_valid(gid)) 30862306a36Sopenharmony_ci vol->gid = gid; 30962306a36Sopenharmony_ci if (fmask != (umode_t)-1) 31062306a36Sopenharmony_ci vol->fmask = fmask; 31162306a36Sopenharmony_ci if (dmask != (umode_t)-1) 31262306a36Sopenharmony_ci vol->dmask = dmask; 31362306a36Sopenharmony_ci if (show_sys_files != -1) { 31462306a36Sopenharmony_ci if (show_sys_files) 31562306a36Sopenharmony_ci NVolSetShowSystemFiles(vol); 31662306a36Sopenharmony_ci else 31762306a36Sopenharmony_ci NVolClearShowSystemFiles(vol); 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci if (case_sensitive != -1) { 32062306a36Sopenharmony_ci if (case_sensitive) 32162306a36Sopenharmony_ci NVolSetCaseSensitive(vol); 32262306a36Sopenharmony_ci else 32362306a36Sopenharmony_ci NVolClearCaseSensitive(vol); 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci if (disable_sparse != -1) { 32662306a36Sopenharmony_ci if (disable_sparse) 32762306a36Sopenharmony_ci NVolClearSparseEnabled(vol); 32862306a36Sopenharmony_ci else { 32962306a36Sopenharmony_ci if (!NVolSparseEnabled(vol) && 33062306a36Sopenharmony_ci vol->major_ver && vol->major_ver < 3) 33162306a36Sopenharmony_ci ntfs_warning(vol->sb, "Not enabling sparse " 33262306a36Sopenharmony_ci "support due to NTFS volume " 33362306a36Sopenharmony_ci "version %i.%i (need at least " 33462306a36Sopenharmony_ci "version 3.0).", vol->major_ver, 33562306a36Sopenharmony_ci vol->minor_ver); 33662306a36Sopenharmony_ci else 33762306a36Sopenharmony_ci NVolSetSparseEnabled(vol); 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci return true; 34162306a36Sopenharmony_cineeds_arg: 34262306a36Sopenharmony_ci ntfs_error(vol->sb, "The %s option requires an argument.", p); 34362306a36Sopenharmony_ci return false; 34462306a36Sopenharmony_cineeds_bool: 34562306a36Sopenharmony_ci ntfs_error(vol->sb, "The %s option requires a boolean argument.", p); 34662306a36Sopenharmony_ci return false; 34762306a36Sopenharmony_cineeds_val: 34862306a36Sopenharmony_ci ntfs_error(vol->sb, "Invalid %s option argument: %s", p, ov); 34962306a36Sopenharmony_ci return false; 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci#ifdef NTFS_RW 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci/** 35562306a36Sopenharmony_ci * ntfs_write_volume_flags - write new flags to the volume information flags 35662306a36Sopenharmony_ci * @vol: ntfs volume on which to modify the flags 35762306a36Sopenharmony_ci * @flags: new flags value for the volume information flags 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci * Internal function. You probably want to use ntfs_{set,clear}_volume_flags() 36062306a36Sopenharmony_ci * instead (see below). 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * Replace the volume information flags on the volume @vol with the value 36362306a36Sopenharmony_ci * supplied in @flags. Note, this overwrites the volume information flags, so 36462306a36Sopenharmony_ci * make sure to combine the flags you want to modify with the old flags and use 36562306a36Sopenharmony_ci * the result when calling ntfs_write_volume_flags(). 36662306a36Sopenharmony_ci * 36762306a36Sopenharmony_ci * Return 0 on success and -errno on error. 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_cistatic int ntfs_write_volume_flags(ntfs_volume *vol, const VOLUME_FLAGS flags) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci ntfs_inode *ni = NTFS_I(vol->vol_ino); 37262306a36Sopenharmony_ci MFT_RECORD *m; 37362306a36Sopenharmony_ci VOLUME_INFORMATION *vi; 37462306a36Sopenharmony_ci ntfs_attr_search_ctx *ctx; 37562306a36Sopenharmony_ci int err; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci ntfs_debug("Entering, old flags = 0x%x, new flags = 0x%x.", 37862306a36Sopenharmony_ci le16_to_cpu(vol->vol_flags), le16_to_cpu(flags)); 37962306a36Sopenharmony_ci if (vol->vol_flags == flags) 38062306a36Sopenharmony_ci goto done; 38162306a36Sopenharmony_ci BUG_ON(!ni); 38262306a36Sopenharmony_ci m = map_mft_record(ni); 38362306a36Sopenharmony_ci if (IS_ERR(m)) { 38462306a36Sopenharmony_ci err = PTR_ERR(m); 38562306a36Sopenharmony_ci goto err_out; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(ni, m); 38862306a36Sopenharmony_ci if (!ctx) { 38962306a36Sopenharmony_ci err = -ENOMEM; 39062306a36Sopenharmony_ci goto put_unm_err_out; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci err = ntfs_attr_lookup(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0, 39362306a36Sopenharmony_ci ctx); 39462306a36Sopenharmony_ci if (err) 39562306a36Sopenharmony_ci goto put_unm_err_out; 39662306a36Sopenharmony_ci vi = (VOLUME_INFORMATION*)((u8*)ctx->attr + 39762306a36Sopenharmony_ci le16_to_cpu(ctx->attr->data.resident.value_offset)); 39862306a36Sopenharmony_ci vol->vol_flags = vi->flags = flags; 39962306a36Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 40062306a36Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 40162306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 40262306a36Sopenharmony_ci unmap_mft_record(ni); 40362306a36Sopenharmony_cidone: 40462306a36Sopenharmony_ci ntfs_debug("Done."); 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ciput_unm_err_out: 40762306a36Sopenharmony_ci if (ctx) 40862306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 40962306a36Sopenharmony_ci unmap_mft_record(ni); 41062306a36Sopenharmony_cierr_out: 41162306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed with error code %i.", -err); 41262306a36Sopenharmony_ci return err; 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/** 41662306a36Sopenharmony_ci * ntfs_set_volume_flags - set bits in the volume information flags 41762306a36Sopenharmony_ci * @vol: ntfs volume on which to modify the flags 41862306a36Sopenharmony_ci * @flags: flags to set on the volume 41962306a36Sopenharmony_ci * 42062306a36Sopenharmony_ci * Set the bits in @flags in the volume information flags on the volume @vol. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * Return 0 on success and -errno on error. 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_cistatic inline int ntfs_set_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci flags &= VOLUME_FLAGS_MASK; 42762306a36Sopenharmony_ci return ntfs_write_volume_flags(vol, vol->vol_flags | flags); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci/** 43162306a36Sopenharmony_ci * ntfs_clear_volume_flags - clear bits in the volume information flags 43262306a36Sopenharmony_ci * @vol: ntfs volume on which to modify the flags 43362306a36Sopenharmony_ci * @flags: flags to clear on the volume 43462306a36Sopenharmony_ci * 43562306a36Sopenharmony_ci * Clear the bits in @flags in the volume information flags on the volume @vol. 43662306a36Sopenharmony_ci * 43762306a36Sopenharmony_ci * Return 0 on success and -errno on error. 43862306a36Sopenharmony_ci */ 43962306a36Sopenharmony_cistatic inline int ntfs_clear_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci flags &= VOLUME_FLAGS_MASK; 44262306a36Sopenharmony_ci flags = vol->vol_flags & cpu_to_le16(~le16_to_cpu(flags)); 44362306a36Sopenharmony_ci return ntfs_write_volume_flags(vol, flags); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci#endif /* NTFS_RW */ 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci/** 44962306a36Sopenharmony_ci * ntfs_remount - change the mount options of a mounted ntfs filesystem 45062306a36Sopenharmony_ci * @sb: superblock of mounted ntfs filesystem 45162306a36Sopenharmony_ci * @flags: remount flags 45262306a36Sopenharmony_ci * @opt: remount options string 45362306a36Sopenharmony_ci * 45462306a36Sopenharmony_ci * Change the mount options of an already mounted ntfs filesystem. 45562306a36Sopenharmony_ci * 45662306a36Sopenharmony_ci * NOTE: The VFS sets the @sb->s_flags remount flags to @flags after 45762306a36Sopenharmony_ci * ntfs_remount() returns successfully (i.e. returns 0). Otherwise, 45862306a36Sopenharmony_ci * @sb->s_flags are not changed. 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_cistatic int ntfs_remount(struct super_block *sb, int *flags, char *opt) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci ntfs_volume *vol = NTFS_SB(sb); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci ntfs_debug("Entering with remount options string: %s", opt); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci sync_filesystem(sb); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci#ifndef NTFS_RW 46962306a36Sopenharmony_ci /* For read-only compiled driver, enforce read-only flag. */ 47062306a36Sopenharmony_ci *flags |= SB_RDONLY; 47162306a36Sopenharmony_ci#else /* NTFS_RW */ 47262306a36Sopenharmony_ci /* 47362306a36Sopenharmony_ci * For the read-write compiled driver, if we are remounting read-write, 47462306a36Sopenharmony_ci * make sure there are no volume errors and that no unsupported volume 47562306a36Sopenharmony_ci * flags are set. Also, empty the logfile journal as it would become 47662306a36Sopenharmony_ci * stale as soon as something is written to the volume and mark the 47762306a36Sopenharmony_ci * volume dirty so that chkdsk is run if the volume is not umounted 47862306a36Sopenharmony_ci * cleanly. Finally, mark the quotas out of date so Windows rescans 47962306a36Sopenharmony_ci * the volume on boot and updates them. 48062306a36Sopenharmony_ci * 48162306a36Sopenharmony_ci * When remounting read-only, mark the volume clean if no volume errors 48262306a36Sopenharmony_ci * have occurred. 48362306a36Sopenharmony_ci */ 48462306a36Sopenharmony_ci if (sb_rdonly(sb) && !(*flags & SB_RDONLY)) { 48562306a36Sopenharmony_ci static const char *es = ". Cannot remount read-write."; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* Remounting read-write. */ 48862306a36Sopenharmony_ci if (NVolErrors(vol)) { 48962306a36Sopenharmony_ci ntfs_error(sb, "Volume has errors and is read-only%s", 49062306a36Sopenharmony_ci es); 49162306a36Sopenharmony_ci return -EROFS; 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci if (vol->vol_flags & VOLUME_IS_DIRTY) { 49462306a36Sopenharmony_ci ntfs_error(sb, "Volume is dirty and read-only%s", es); 49562306a36Sopenharmony_ci return -EROFS; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci if (vol->vol_flags & VOLUME_MODIFIED_BY_CHKDSK) { 49862306a36Sopenharmony_ci ntfs_error(sb, "Volume has been modified by chkdsk " 49962306a36Sopenharmony_ci "and is read-only%s", es); 50062306a36Sopenharmony_ci return -EROFS; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) { 50362306a36Sopenharmony_ci ntfs_error(sb, "Volume has unsupported flags set " 50462306a36Sopenharmony_ci "(0x%x) and is read-only%s", 50562306a36Sopenharmony_ci (unsigned)le16_to_cpu(vol->vol_flags), 50662306a36Sopenharmony_ci es); 50762306a36Sopenharmony_ci return -EROFS; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci if (ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) { 51062306a36Sopenharmony_ci ntfs_error(sb, "Failed to set dirty bit in volume " 51162306a36Sopenharmony_ci "information flags%s", es); 51262306a36Sopenharmony_ci return -EROFS; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci#if 0 51562306a36Sopenharmony_ci // TODO: Enable this code once we start modifying anything that 51662306a36Sopenharmony_ci // is different between NTFS 1.2 and 3.x... 51762306a36Sopenharmony_ci /* Set NT4 compatibility flag on newer NTFS version volumes. */ 51862306a36Sopenharmony_ci if ((vol->major_ver > 1)) { 51962306a36Sopenharmony_ci if (ntfs_set_volume_flags(vol, VOLUME_MOUNTED_ON_NT4)) { 52062306a36Sopenharmony_ci ntfs_error(sb, "Failed to set NT4 " 52162306a36Sopenharmony_ci "compatibility flag%s", es); 52262306a36Sopenharmony_ci NVolSetErrors(vol); 52362306a36Sopenharmony_ci return -EROFS; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci#endif 52762306a36Sopenharmony_ci if (!ntfs_empty_logfile(vol->logfile_ino)) { 52862306a36Sopenharmony_ci ntfs_error(sb, "Failed to empty journal $LogFile%s", 52962306a36Sopenharmony_ci es); 53062306a36Sopenharmony_ci NVolSetErrors(vol); 53162306a36Sopenharmony_ci return -EROFS; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci if (!ntfs_mark_quotas_out_of_date(vol)) { 53462306a36Sopenharmony_ci ntfs_error(sb, "Failed to mark quotas out of date%s", 53562306a36Sopenharmony_ci es); 53662306a36Sopenharmony_ci NVolSetErrors(vol); 53762306a36Sopenharmony_ci return -EROFS; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci if (!ntfs_stamp_usnjrnl(vol)) { 54062306a36Sopenharmony_ci ntfs_error(sb, "Failed to stamp transaction log " 54162306a36Sopenharmony_ci "($UsnJrnl)%s", es); 54262306a36Sopenharmony_ci NVolSetErrors(vol); 54362306a36Sopenharmony_ci return -EROFS; 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci } else if (!sb_rdonly(sb) && (*flags & SB_RDONLY)) { 54662306a36Sopenharmony_ci /* Remounting read-only. */ 54762306a36Sopenharmony_ci if (!NVolErrors(vol)) { 54862306a36Sopenharmony_ci if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) 54962306a36Sopenharmony_ci ntfs_warning(sb, "Failed to clear dirty bit " 55062306a36Sopenharmony_ci "in volume information " 55162306a36Sopenharmony_ci "flags. Run chkdsk."); 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci#endif /* NTFS_RW */ 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci // TODO: Deal with *flags. 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci if (!parse_options(vol, opt)) 55962306a36Sopenharmony_ci return -EINVAL; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci ntfs_debug("Done."); 56262306a36Sopenharmony_ci return 0; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/** 56662306a36Sopenharmony_ci * is_boot_sector_ntfs - check whether a boot sector is a valid NTFS boot sector 56762306a36Sopenharmony_ci * @sb: Super block of the device to which @b belongs. 56862306a36Sopenharmony_ci * @b: Boot sector of device @sb to check. 56962306a36Sopenharmony_ci * @silent: If 'true', all output will be silenced. 57062306a36Sopenharmony_ci * 57162306a36Sopenharmony_ci * is_boot_sector_ntfs() checks whether the boot sector @b is a valid NTFS boot 57262306a36Sopenharmony_ci * sector. Returns 'true' if it is valid and 'false' if not. 57362306a36Sopenharmony_ci * 57462306a36Sopenharmony_ci * @sb is only needed for warning/error output, i.e. it can be NULL when silent 57562306a36Sopenharmony_ci * is 'true'. 57662306a36Sopenharmony_ci */ 57762306a36Sopenharmony_cistatic bool is_boot_sector_ntfs(const struct super_block *sb, 57862306a36Sopenharmony_ci const NTFS_BOOT_SECTOR *b, const bool silent) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci /* 58162306a36Sopenharmony_ci * Check that checksum == sum of u32 values from b to the checksum 58262306a36Sopenharmony_ci * field. If checksum is zero, no checking is done. We will work when 58362306a36Sopenharmony_ci * the checksum test fails, since some utilities update the boot sector 58462306a36Sopenharmony_ci * ignoring the checksum which leaves the checksum out-of-date. We 58562306a36Sopenharmony_ci * report a warning if this is the case. 58662306a36Sopenharmony_ci */ 58762306a36Sopenharmony_ci if ((void*)b < (void*)&b->checksum && b->checksum && !silent) { 58862306a36Sopenharmony_ci le32 *u; 58962306a36Sopenharmony_ci u32 i; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci for (i = 0, u = (le32*)b; u < (le32*)(&b->checksum); ++u) 59262306a36Sopenharmony_ci i += le32_to_cpup(u); 59362306a36Sopenharmony_ci if (le32_to_cpu(b->checksum) != i) 59462306a36Sopenharmony_ci ntfs_warning(sb, "Invalid boot sector checksum."); 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci /* Check OEMidentifier is "NTFS " */ 59762306a36Sopenharmony_ci if (b->oem_id != magicNTFS) 59862306a36Sopenharmony_ci goto not_ntfs; 59962306a36Sopenharmony_ci /* Check bytes per sector value is between 256 and 4096. */ 60062306a36Sopenharmony_ci if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 || 60162306a36Sopenharmony_ci le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000) 60262306a36Sopenharmony_ci goto not_ntfs; 60362306a36Sopenharmony_ci /* Check sectors per cluster value is valid. */ 60462306a36Sopenharmony_ci switch (b->bpb.sectors_per_cluster) { 60562306a36Sopenharmony_ci case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: 60662306a36Sopenharmony_ci break; 60762306a36Sopenharmony_ci default: 60862306a36Sopenharmony_ci goto not_ntfs; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci /* Check the cluster size is not above the maximum (64kiB). */ 61162306a36Sopenharmony_ci if ((u32)le16_to_cpu(b->bpb.bytes_per_sector) * 61262306a36Sopenharmony_ci b->bpb.sectors_per_cluster > NTFS_MAX_CLUSTER_SIZE) 61362306a36Sopenharmony_ci goto not_ntfs; 61462306a36Sopenharmony_ci /* Check reserved/unused fields are really zero. */ 61562306a36Sopenharmony_ci if (le16_to_cpu(b->bpb.reserved_sectors) || 61662306a36Sopenharmony_ci le16_to_cpu(b->bpb.root_entries) || 61762306a36Sopenharmony_ci le16_to_cpu(b->bpb.sectors) || 61862306a36Sopenharmony_ci le16_to_cpu(b->bpb.sectors_per_fat) || 61962306a36Sopenharmony_ci le32_to_cpu(b->bpb.large_sectors) || b->bpb.fats) 62062306a36Sopenharmony_ci goto not_ntfs; 62162306a36Sopenharmony_ci /* Check clusters per file mft record value is valid. */ 62262306a36Sopenharmony_ci if ((u8)b->clusters_per_mft_record < 0xe1 || 62362306a36Sopenharmony_ci (u8)b->clusters_per_mft_record > 0xf7) 62462306a36Sopenharmony_ci switch (b->clusters_per_mft_record) { 62562306a36Sopenharmony_ci case 1: case 2: case 4: case 8: case 16: case 32: case 64: 62662306a36Sopenharmony_ci break; 62762306a36Sopenharmony_ci default: 62862306a36Sopenharmony_ci goto not_ntfs; 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci /* Check clusters per index block value is valid. */ 63162306a36Sopenharmony_ci if ((u8)b->clusters_per_index_record < 0xe1 || 63262306a36Sopenharmony_ci (u8)b->clusters_per_index_record > 0xf7) 63362306a36Sopenharmony_ci switch (b->clusters_per_index_record) { 63462306a36Sopenharmony_ci case 1: case 2: case 4: case 8: case 16: case 32: case 64: 63562306a36Sopenharmony_ci break; 63662306a36Sopenharmony_ci default: 63762306a36Sopenharmony_ci goto not_ntfs; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci /* 64062306a36Sopenharmony_ci * Check for valid end of sector marker. We will work without it, but 64162306a36Sopenharmony_ci * many BIOSes will refuse to boot from a bootsector if the magic is 64262306a36Sopenharmony_ci * incorrect, so we emit a warning. 64362306a36Sopenharmony_ci */ 64462306a36Sopenharmony_ci if (!silent && b->end_of_sector_marker != cpu_to_le16(0xaa55)) 64562306a36Sopenharmony_ci ntfs_warning(sb, "Invalid end of sector marker."); 64662306a36Sopenharmony_ci return true; 64762306a36Sopenharmony_cinot_ntfs: 64862306a36Sopenharmony_ci return false; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci/** 65262306a36Sopenharmony_ci * read_ntfs_boot_sector - read the NTFS boot sector of a device 65362306a36Sopenharmony_ci * @sb: super block of device to read the boot sector from 65462306a36Sopenharmony_ci * @silent: if true, suppress all output 65562306a36Sopenharmony_ci * 65662306a36Sopenharmony_ci * Reads the boot sector from the device and validates it. If that fails, tries 65762306a36Sopenharmony_ci * to read the backup boot sector, first from the end of the device a-la NT4 and 65862306a36Sopenharmony_ci * later and then from the middle of the device a-la NT3.51 and before. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * If a valid boot sector is found but it is not the primary boot sector, we 66162306a36Sopenharmony_ci * repair the primary boot sector silently (unless the device is read-only or 66262306a36Sopenharmony_ci * the primary boot sector is not accessible). 66362306a36Sopenharmony_ci * 66462306a36Sopenharmony_ci * NOTE: To call this function, @sb must have the fields s_dev, the ntfs super 66562306a36Sopenharmony_ci * block (u.ntfs_sb), nr_blocks and the device flags (s_flags) initialized 66662306a36Sopenharmony_ci * to their respective values. 66762306a36Sopenharmony_ci * 66862306a36Sopenharmony_ci * Return the unlocked buffer head containing the boot sector or NULL on error. 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_cistatic struct buffer_head *read_ntfs_boot_sector(struct super_block *sb, 67162306a36Sopenharmony_ci const int silent) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci const char *read_err_str = "Unable to read %s boot sector."; 67462306a36Sopenharmony_ci struct buffer_head *bh_primary, *bh_backup; 67562306a36Sopenharmony_ci sector_t nr_blocks = NTFS_SB(sb)->nr_blocks; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* Try to read primary boot sector. */ 67862306a36Sopenharmony_ci if ((bh_primary = sb_bread(sb, 0))) { 67962306a36Sopenharmony_ci if (is_boot_sector_ntfs(sb, (NTFS_BOOT_SECTOR*) 68062306a36Sopenharmony_ci bh_primary->b_data, silent)) 68162306a36Sopenharmony_ci return bh_primary; 68262306a36Sopenharmony_ci if (!silent) 68362306a36Sopenharmony_ci ntfs_error(sb, "Primary boot sector is invalid."); 68462306a36Sopenharmony_ci } else if (!silent) 68562306a36Sopenharmony_ci ntfs_error(sb, read_err_str, "primary"); 68662306a36Sopenharmony_ci if (!(NTFS_SB(sb)->on_errors & ON_ERRORS_RECOVER)) { 68762306a36Sopenharmony_ci if (bh_primary) 68862306a36Sopenharmony_ci brelse(bh_primary); 68962306a36Sopenharmony_ci if (!silent) 69062306a36Sopenharmony_ci ntfs_error(sb, "Mount option errors=recover not used. " 69162306a36Sopenharmony_ci "Aborting without trying to recover."); 69262306a36Sopenharmony_ci return NULL; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci /* Try to read NT4+ backup boot sector. */ 69562306a36Sopenharmony_ci if ((bh_backup = sb_bread(sb, nr_blocks - 1))) { 69662306a36Sopenharmony_ci if (is_boot_sector_ntfs(sb, (NTFS_BOOT_SECTOR*) 69762306a36Sopenharmony_ci bh_backup->b_data, silent)) 69862306a36Sopenharmony_ci goto hotfix_primary_boot_sector; 69962306a36Sopenharmony_ci brelse(bh_backup); 70062306a36Sopenharmony_ci } else if (!silent) 70162306a36Sopenharmony_ci ntfs_error(sb, read_err_str, "backup"); 70262306a36Sopenharmony_ci /* Try to read NT3.51- backup boot sector. */ 70362306a36Sopenharmony_ci if ((bh_backup = sb_bread(sb, nr_blocks >> 1))) { 70462306a36Sopenharmony_ci if (is_boot_sector_ntfs(sb, (NTFS_BOOT_SECTOR*) 70562306a36Sopenharmony_ci bh_backup->b_data, silent)) 70662306a36Sopenharmony_ci goto hotfix_primary_boot_sector; 70762306a36Sopenharmony_ci if (!silent) 70862306a36Sopenharmony_ci ntfs_error(sb, "Could not find a valid backup boot " 70962306a36Sopenharmony_ci "sector."); 71062306a36Sopenharmony_ci brelse(bh_backup); 71162306a36Sopenharmony_ci } else if (!silent) 71262306a36Sopenharmony_ci ntfs_error(sb, read_err_str, "backup"); 71362306a36Sopenharmony_ci /* We failed. Cleanup and return. */ 71462306a36Sopenharmony_ci if (bh_primary) 71562306a36Sopenharmony_ci brelse(bh_primary); 71662306a36Sopenharmony_ci return NULL; 71762306a36Sopenharmony_cihotfix_primary_boot_sector: 71862306a36Sopenharmony_ci if (bh_primary) { 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * If we managed to read sector zero and the volume is not 72162306a36Sopenharmony_ci * read-only, copy the found, valid backup boot sector to the 72262306a36Sopenharmony_ci * primary boot sector. Note we only copy the actual boot 72362306a36Sopenharmony_ci * sector structure, not the actual whole device sector as that 72462306a36Sopenharmony_ci * may be bigger and would potentially damage the $Boot system 72562306a36Sopenharmony_ci * file (FIXME: Would be nice to know if the backup boot sector 72662306a36Sopenharmony_ci * on a large sector device contains the whole boot loader or 72762306a36Sopenharmony_ci * just the first 512 bytes). 72862306a36Sopenharmony_ci */ 72962306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 73062306a36Sopenharmony_ci ntfs_warning(sb, "Hot-fix: Recovering invalid primary " 73162306a36Sopenharmony_ci "boot sector from backup copy."); 73262306a36Sopenharmony_ci memcpy(bh_primary->b_data, bh_backup->b_data, 73362306a36Sopenharmony_ci NTFS_BLOCK_SIZE); 73462306a36Sopenharmony_ci mark_buffer_dirty(bh_primary); 73562306a36Sopenharmony_ci sync_dirty_buffer(bh_primary); 73662306a36Sopenharmony_ci if (buffer_uptodate(bh_primary)) { 73762306a36Sopenharmony_ci brelse(bh_backup); 73862306a36Sopenharmony_ci return bh_primary; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci ntfs_error(sb, "Hot-fix: Device write error while " 74162306a36Sopenharmony_ci "recovering primary boot sector."); 74262306a36Sopenharmony_ci } else { 74362306a36Sopenharmony_ci ntfs_warning(sb, "Hot-fix: Recovery of primary boot " 74462306a36Sopenharmony_ci "sector failed: Read-only mount."); 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci brelse(bh_primary); 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci ntfs_warning(sb, "Using backup boot sector."); 74962306a36Sopenharmony_ci return bh_backup; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci/** 75362306a36Sopenharmony_ci * parse_ntfs_boot_sector - parse the boot sector and store the data in @vol 75462306a36Sopenharmony_ci * @vol: volume structure to initialise with data from boot sector 75562306a36Sopenharmony_ci * @b: boot sector to parse 75662306a36Sopenharmony_ci * 75762306a36Sopenharmony_ci * Parse the ntfs boot sector @b and store all imporant information therein in 75862306a36Sopenharmony_ci * the ntfs super block @vol. Return 'true' on success and 'false' on error. 75962306a36Sopenharmony_ci */ 76062306a36Sopenharmony_cistatic bool parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci unsigned int sectors_per_cluster_bits, nr_hidden_sects; 76362306a36Sopenharmony_ci int clusters_per_mft_record, clusters_per_index_record; 76462306a36Sopenharmony_ci s64 ll; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci vol->sector_size = le16_to_cpu(b->bpb.bytes_per_sector); 76762306a36Sopenharmony_ci vol->sector_size_bits = ffs(vol->sector_size) - 1; 76862306a36Sopenharmony_ci ntfs_debug("vol->sector_size = %i (0x%x)", vol->sector_size, 76962306a36Sopenharmony_ci vol->sector_size); 77062306a36Sopenharmony_ci ntfs_debug("vol->sector_size_bits = %i (0x%x)", vol->sector_size_bits, 77162306a36Sopenharmony_ci vol->sector_size_bits); 77262306a36Sopenharmony_ci if (vol->sector_size < vol->sb->s_blocksize) { 77362306a36Sopenharmony_ci ntfs_error(vol->sb, "Sector size (%i) is smaller than the " 77462306a36Sopenharmony_ci "device block size (%lu). This is not " 77562306a36Sopenharmony_ci "supported. Sorry.", vol->sector_size, 77662306a36Sopenharmony_ci vol->sb->s_blocksize); 77762306a36Sopenharmony_ci return false; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster); 78062306a36Sopenharmony_ci sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1; 78162306a36Sopenharmony_ci ntfs_debug("sectors_per_cluster_bits = 0x%x", 78262306a36Sopenharmony_ci sectors_per_cluster_bits); 78362306a36Sopenharmony_ci nr_hidden_sects = le32_to_cpu(b->bpb.hidden_sectors); 78462306a36Sopenharmony_ci ntfs_debug("number of hidden sectors = 0x%x", nr_hidden_sects); 78562306a36Sopenharmony_ci vol->cluster_size = vol->sector_size << sectors_per_cluster_bits; 78662306a36Sopenharmony_ci vol->cluster_size_mask = vol->cluster_size - 1; 78762306a36Sopenharmony_ci vol->cluster_size_bits = ffs(vol->cluster_size) - 1; 78862306a36Sopenharmony_ci ntfs_debug("vol->cluster_size = %i (0x%x)", vol->cluster_size, 78962306a36Sopenharmony_ci vol->cluster_size); 79062306a36Sopenharmony_ci ntfs_debug("vol->cluster_size_mask = 0x%x", vol->cluster_size_mask); 79162306a36Sopenharmony_ci ntfs_debug("vol->cluster_size_bits = %i", vol->cluster_size_bits); 79262306a36Sopenharmony_ci if (vol->cluster_size < vol->sector_size) { 79362306a36Sopenharmony_ci ntfs_error(vol->sb, "Cluster size (%i) is smaller than the " 79462306a36Sopenharmony_ci "sector size (%i). This is not supported. " 79562306a36Sopenharmony_ci "Sorry.", vol->cluster_size, vol->sector_size); 79662306a36Sopenharmony_ci return false; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci clusters_per_mft_record = b->clusters_per_mft_record; 79962306a36Sopenharmony_ci ntfs_debug("clusters_per_mft_record = %i (0x%x)", 80062306a36Sopenharmony_ci clusters_per_mft_record, clusters_per_mft_record); 80162306a36Sopenharmony_ci if (clusters_per_mft_record > 0) 80262306a36Sopenharmony_ci vol->mft_record_size = vol->cluster_size << 80362306a36Sopenharmony_ci (ffs(clusters_per_mft_record) - 1); 80462306a36Sopenharmony_ci else 80562306a36Sopenharmony_ci /* 80662306a36Sopenharmony_ci * When mft_record_size < cluster_size, clusters_per_mft_record 80762306a36Sopenharmony_ci * = -log2(mft_record_size) bytes. mft_record_size normaly is 80862306a36Sopenharmony_ci * 1024 bytes, which is encoded as 0xF6 (-10 in decimal). 80962306a36Sopenharmony_ci */ 81062306a36Sopenharmony_ci vol->mft_record_size = 1 << -clusters_per_mft_record; 81162306a36Sopenharmony_ci vol->mft_record_size_mask = vol->mft_record_size - 1; 81262306a36Sopenharmony_ci vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; 81362306a36Sopenharmony_ci ntfs_debug("vol->mft_record_size = %i (0x%x)", vol->mft_record_size, 81462306a36Sopenharmony_ci vol->mft_record_size); 81562306a36Sopenharmony_ci ntfs_debug("vol->mft_record_size_mask = 0x%x", 81662306a36Sopenharmony_ci vol->mft_record_size_mask); 81762306a36Sopenharmony_ci ntfs_debug("vol->mft_record_size_bits = %i (0x%x)", 81862306a36Sopenharmony_ci vol->mft_record_size_bits, vol->mft_record_size_bits); 81962306a36Sopenharmony_ci /* 82062306a36Sopenharmony_ci * We cannot support mft record sizes above the PAGE_SIZE since 82162306a36Sopenharmony_ci * we store $MFT/$DATA, the table of mft records in the page cache. 82262306a36Sopenharmony_ci */ 82362306a36Sopenharmony_ci if (vol->mft_record_size > PAGE_SIZE) { 82462306a36Sopenharmony_ci ntfs_error(vol->sb, "Mft record size (%i) exceeds the " 82562306a36Sopenharmony_ci "PAGE_SIZE on your system (%lu). " 82662306a36Sopenharmony_ci "This is not supported. Sorry.", 82762306a36Sopenharmony_ci vol->mft_record_size, PAGE_SIZE); 82862306a36Sopenharmony_ci return false; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci /* We cannot support mft record sizes below the sector size. */ 83162306a36Sopenharmony_ci if (vol->mft_record_size < vol->sector_size) { 83262306a36Sopenharmony_ci ntfs_error(vol->sb, "Mft record size (%i) is smaller than the " 83362306a36Sopenharmony_ci "sector size (%i). This is not supported. " 83462306a36Sopenharmony_ci "Sorry.", vol->mft_record_size, 83562306a36Sopenharmony_ci vol->sector_size); 83662306a36Sopenharmony_ci return false; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci clusters_per_index_record = b->clusters_per_index_record; 83962306a36Sopenharmony_ci ntfs_debug("clusters_per_index_record = %i (0x%x)", 84062306a36Sopenharmony_ci clusters_per_index_record, clusters_per_index_record); 84162306a36Sopenharmony_ci if (clusters_per_index_record > 0) 84262306a36Sopenharmony_ci vol->index_record_size = vol->cluster_size << 84362306a36Sopenharmony_ci (ffs(clusters_per_index_record) - 1); 84462306a36Sopenharmony_ci else 84562306a36Sopenharmony_ci /* 84662306a36Sopenharmony_ci * When index_record_size < cluster_size, 84762306a36Sopenharmony_ci * clusters_per_index_record = -log2(index_record_size) bytes. 84862306a36Sopenharmony_ci * index_record_size normaly equals 4096 bytes, which is 84962306a36Sopenharmony_ci * encoded as 0xF4 (-12 in decimal). 85062306a36Sopenharmony_ci */ 85162306a36Sopenharmony_ci vol->index_record_size = 1 << -clusters_per_index_record; 85262306a36Sopenharmony_ci vol->index_record_size_mask = vol->index_record_size - 1; 85362306a36Sopenharmony_ci vol->index_record_size_bits = ffs(vol->index_record_size) - 1; 85462306a36Sopenharmony_ci ntfs_debug("vol->index_record_size = %i (0x%x)", 85562306a36Sopenharmony_ci vol->index_record_size, vol->index_record_size); 85662306a36Sopenharmony_ci ntfs_debug("vol->index_record_size_mask = 0x%x", 85762306a36Sopenharmony_ci vol->index_record_size_mask); 85862306a36Sopenharmony_ci ntfs_debug("vol->index_record_size_bits = %i (0x%x)", 85962306a36Sopenharmony_ci vol->index_record_size_bits, 86062306a36Sopenharmony_ci vol->index_record_size_bits); 86162306a36Sopenharmony_ci /* We cannot support index record sizes below the sector size. */ 86262306a36Sopenharmony_ci if (vol->index_record_size < vol->sector_size) { 86362306a36Sopenharmony_ci ntfs_error(vol->sb, "Index record size (%i) is smaller than " 86462306a36Sopenharmony_ci "the sector size (%i). This is not " 86562306a36Sopenharmony_ci "supported. Sorry.", vol->index_record_size, 86662306a36Sopenharmony_ci vol->sector_size); 86762306a36Sopenharmony_ci return false; 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci /* 87062306a36Sopenharmony_ci * Get the size of the volume in clusters and check for 64-bit-ness. 87162306a36Sopenharmony_ci * Windows currently only uses 32 bits to save the clusters so we do 87262306a36Sopenharmony_ci * the same as it is much faster on 32-bit CPUs. 87362306a36Sopenharmony_ci */ 87462306a36Sopenharmony_ci ll = sle64_to_cpu(b->number_of_sectors) >> sectors_per_cluster_bits; 87562306a36Sopenharmony_ci if ((u64)ll >= 1ULL << 32) { 87662306a36Sopenharmony_ci ntfs_error(vol->sb, "Cannot handle 64-bit clusters. Sorry."); 87762306a36Sopenharmony_ci return false; 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci vol->nr_clusters = ll; 88062306a36Sopenharmony_ci ntfs_debug("vol->nr_clusters = 0x%llx", (long long)vol->nr_clusters); 88162306a36Sopenharmony_ci /* 88262306a36Sopenharmony_ci * On an architecture where unsigned long is 32-bits, we restrict the 88362306a36Sopenharmony_ci * volume size to 2TiB (2^41). On a 64-bit architecture, the compiler 88462306a36Sopenharmony_ci * will hopefully optimize the whole check away. 88562306a36Sopenharmony_ci */ 88662306a36Sopenharmony_ci if (sizeof(unsigned long) < 8) { 88762306a36Sopenharmony_ci if ((ll << vol->cluster_size_bits) >= (1ULL << 41)) { 88862306a36Sopenharmony_ci ntfs_error(vol->sb, "Volume size (%lluTiB) is too " 88962306a36Sopenharmony_ci "large for this architecture. " 89062306a36Sopenharmony_ci "Maximum supported is 2TiB. Sorry.", 89162306a36Sopenharmony_ci (unsigned long long)ll >> (40 - 89262306a36Sopenharmony_ci vol->cluster_size_bits)); 89362306a36Sopenharmony_ci return false; 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci ll = sle64_to_cpu(b->mft_lcn); 89762306a36Sopenharmony_ci if (ll >= vol->nr_clusters) { 89862306a36Sopenharmony_ci ntfs_error(vol->sb, "MFT LCN (%lli, 0x%llx) is beyond end of " 89962306a36Sopenharmony_ci "volume. Weird.", (unsigned long long)ll, 90062306a36Sopenharmony_ci (unsigned long long)ll); 90162306a36Sopenharmony_ci return false; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci vol->mft_lcn = ll; 90462306a36Sopenharmony_ci ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn); 90562306a36Sopenharmony_ci ll = sle64_to_cpu(b->mftmirr_lcn); 90662306a36Sopenharmony_ci if (ll >= vol->nr_clusters) { 90762306a36Sopenharmony_ci ntfs_error(vol->sb, "MFTMirr LCN (%lli, 0x%llx) is beyond end " 90862306a36Sopenharmony_ci "of volume. Weird.", (unsigned long long)ll, 90962306a36Sopenharmony_ci (unsigned long long)ll); 91062306a36Sopenharmony_ci return false; 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci vol->mftmirr_lcn = ll; 91362306a36Sopenharmony_ci ntfs_debug("vol->mftmirr_lcn = 0x%llx", (long long)vol->mftmirr_lcn); 91462306a36Sopenharmony_ci#ifdef NTFS_RW 91562306a36Sopenharmony_ci /* 91662306a36Sopenharmony_ci * Work out the size of the mft mirror in number of mft records. If the 91762306a36Sopenharmony_ci * cluster size is less than or equal to the size taken by four mft 91862306a36Sopenharmony_ci * records, the mft mirror stores the first four mft records. If the 91962306a36Sopenharmony_ci * cluster size is bigger than the size taken by four mft records, the 92062306a36Sopenharmony_ci * mft mirror contains as many mft records as will fit into one 92162306a36Sopenharmony_ci * cluster. 92262306a36Sopenharmony_ci */ 92362306a36Sopenharmony_ci if (vol->cluster_size <= (4 << vol->mft_record_size_bits)) 92462306a36Sopenharmony_ci vol->mftmirr_size = 4; 92562306a36Sopenharmony_ci else 92662306a36Sopenharmony_ci vol->mftmirr_size = vol->cluster_size >> 92762306a36Sopenharmony_ci vol->mft_record_size_bits; 92862306a36Sopenharmony_ci ntfs_debug("vol->mftmirr_size = %i", vol->mftmirr_size); 92962306a36Sopenharmony_ci#endif /* NTFS_RW */ 93062306a36Sopenharmony_ci vol->serial_no = le64_to_cpu(b->volume_serial_number); 93162306a36Sopenharmony_ci ntfs_debug("vol->serial_no = 0x%llx", 93262306a36Sopenharmony_ci (unsigned long long)vol->serial_no); 93362306a36Sopenharmony_ci return true; 93462306a36Sopenharmony_ci} 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci/** 93762306a36Sopenharmony_ci * ntfs_setup_allocators - initialize the cluster and mft allocators 93862306a36Sopenharmony_ci * @vol: volume structure for which to setup the allocators 93962306a36Sopenharmony_ci * 94062306a36Sopenharmony_ci * Setup the cluster (lcn) and mft allocators to the starting values. 94162306a36Sopenharmony_ci */ 94262306a36Sopenharmony_cistatic void ntfs_setup_allocators(ntfs_volume *vol) 94362306a36Sopenharmony_ci{ 94462306a36Sopenharmony_ci#ifdef NTFS_RW 94562306a36Sopenharmony_ci LCN mft_zone_size, mft_lcn; 94662306a36Sopenharmony_ci#endif /* NTFS_RW */ 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci ntfs_debug("vol->mft_zone_multiplier = 0x%x", 94962306a36Sopenharmony_ci vol->mft_zone_multiplier); 95062306a36Sopenharmony_ci#ifdef NTFS_RW 95162306a36Sopenharmony_ci /* Determine the size of the MFT zone. */ 95262306a36Sopenharmony_ci mft_zone_size = vol->nr_clusters; 95362306a36Sopenharmony_ci switch (vol->mft_zone_multiplier) { /* % of volume size in clusters */ 95462306a36Sopenharmony_ci case 4: 95562306a36Sopenharmony_ci mft_zone_size >>= 1; /* 50% */ 95662306a36Sopenharmony_ci break; 95762306a36Sopenharmony_ci case 3: 95862306a36Sopenharmony_ci mft_zone_size = (mft_zone_size + 95962306a36Sopenharmony_ci (mft_zone_size >> 1)) >> 2; /* 37.5% */ 96062306a36Sopenharmony_ci break; 96162306a36Sopenharmony_ci case 2: 96262306a36Sopenharmony_ci mft_zone_size >>= 2; /* 25% */ 96362306a36Sopenharmony_ci break; 96462306a36Sopenharmony_ci /* case 1: */ 96562306a36Sopenharmony_ci default: 96662306a36Sopenharmony_ci mft_zone_size >>= 3; /* 12.5% */ 96762306a36Sopenharmony_ci break; 96862306a36Sopenharmony_ci } 96962306a36Sopenharmony_ci /* Setup the mft zone. */ 97062306a36Sopenharmony_ci vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn; 97162306a36Sopenharmony_ci ntfs_debug("vol->mft_zone_pos = 0x%llx", 97262306a36Sopenharmony_ci (unsigned long long)vol->mft_zone_pos); 97362306a36Sopenharmony_ci /* 97462306a36Sopenharmony_ci * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs 97562306a36Sopenharmony_ci * source) and if the actual mft_lcn is in the expected place or even 97662306a36Sopenharmony_ci * further to the front of the volume, extend the mft_zone to cover the 97762306a36Sopenharmony_ci * beginning of the volume as well. This is in order to protect the 97862306a36Sopenharmony_ci * area reserved for the mft bitmap as well within the mft_zone itself. 97962306a36Sopenharmony_ci * On non-standard volumes we do not protect it as the overhead would 98062306a36Sopenharmony_ci * be higher than the speed increase we would get by doing it. 98162306a36Sopenharmony_ci */ 98262306a36Sopenharmony_ci mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size; 98362306a36Sopenharmony_ci if (mft_lcn * vol->cluster_size < 16 * 1024) 98462306a36Sopenharmony_ci mft_lcn = (16 * 1024 + vol->cluster_size - 1) / 98562306a36Sopenharmony_ci vol->cluster_size; 98662306a36Sopenharmony_ci if (vol->mft_zone_start <= mft_lcn) 98762306a36Sopenharmony_ci vol->mft_zone_start = 0; 98862306a36Sopenharmony_ci ntfs_debug("vol->mft_zone_start = 0x%llx", 98962306a36Sopenharmony_ci (unsigned long long)vol->mft_zone_start); 99062306a36Sopenharmony_ci /* 99162306a36Sopenharmony_ci * Need to cap the mft zone on non-standard volumes so that it does 99262306a36Sopenharmony_ci * not point outside the boundaries of the volume. We do this by 99362306a36Sopenharmony_ci * halving the zone size until we are inside the volume. 99462306a36Sopenharmony_ci */ 99562306a36Sopenharmony_ci vol->mft_zone_end = vol->mft_lcn + mft_zone_size; 99662306a36Sopenharmony_ci while (vol->mft_zone_end >= vol->nr_clusters) { 99762306a36Sopenharmony_ci mft_zone_size >>= 1; 99862306a36Sopenharmony_ci vol->mft_zone_end = vol->mft_lcn + mft_zone_size; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci ntfs_debug("vol->mft_zone_end = 0x%llx", 100162306a36Sopenharmony_ci (unsigned long long)vol->mft_zone_end); 100262306a36Sopenharmony_ci /* 100362306a36Sopenharmony_ci * Set the current position within each data zone to the start of the 100462306a36Sopenharmony_ci * respective zone. 100562306a36Sopenharmony_ci */ 100662306a36Sopenharmony_ci vol->data1_zone_pos = vol->mft_zone_end; 100762306a36Sopenharmony_ci ntfs_debug("vol->data1_zone_pos = 0x%llx", 100862306a36Sopenharmony_ci (unsigned long long)vol->data1_zone_pos); 100962306a36Sopenharmony_ci vol->data2_zone_pos = 0; 101062306a36Sopenharmony_ci ntfs_debug("vol->data2_zone_pos = 0x%llx", 101162306a36Sopenharmony_ci (unsigned long long)vol->data2_zone_pos); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci /* Set the mft data allocation position to mft record 24. */ 101462306a36Sopenharmony_ci vol->mft_data_pos = 24; 101562306a36Sopenharmony_ci ntfs_debug("vol->mft_data_pos = 0x%llx", 101662306a36Sopenharmony_ci (unsigned long long)vol->mft_data_pos); 101762306a36Sopenharmony_ci#endif /* NTFS_RW */ 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci#ifdef NTFS_RW 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci/** 102362306a36Sopenharmony_ci * load_and_init_mft_mirror - load and setup the mft mirror inode for a volume 102462306a36Sopenharmony_ci * @vol: ntfs super block describing device whose mft mirror to load 102562306a36Sopenharmony_ci * 102662306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 102762306a36Sopenharmony_ci */ 102862306a36Sopenharmony_cistatic bool load_and_init_mft_mirror(ntfs_volume *vol) 102962306a36Sopenharmony_ci{ 103062306a36Sopenharmony_ci struct inode *tmp_ino; 103162306a36Sopenharmony_ci ntfs_inode *tmp_ni; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci ntfs_debug("Entering."); 103462306a36Sopenharmony_ci /* Get mft mirror inode. */ 103562306a36Sopenharmony_ci tmp_ino = ntfs_iget(vol->sb, FILE_MFTMirr); 103662306a36Sopenharmony_ci if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { 103762306a36Sopenharmony_ci if (!IS_ERR(tmp_ino)) 103862306a36Sopenharmony_ci iput(tmp_ino); 103962306a36Sopenharmony_ci /* Caller will display error message. */ 104062306a36Sopenharmony_ci return false; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci /* 104362306a36Sopenharmony_ci * Re-initialize some specifics about $MFTMirr's inode as 104462306a36Sopenharmony_ci * ntfs_read_inode() will have set up the default ones. 104562306a36Sopenharmony_ci */ 104662306a36Sopenharmony_ci /* Set uid and gid to root. */ 104762306a36Sopenharmony_ci tmp_ino->i_uid = GLOBAL_ROOT_UID; 104862306a36Sopenharmony_ci tmp_ino->i_gid = GLOBAL_ROOT_GID; 104962306a36Sopenharmony_ci /* Regular file. No access for anyone. */ 105062306a36Sopenharmony_ci tmp_ino->i_mode = S_IFREG; 105162306a36Sopenharmony_ci /* No VFS initiated operations allowed for $MFTMirr. */ 105262306a36Sopenharmony_ci tmp_ino->i_op = &ntfs_empty_inode_ops; 105362306a36Sopenharmony_ci tmp_ino->i_fop = &ntfs_empty_file_ops; 105462306a36Sopenharmony_ci /* Put in our special address space operations. */ 105562306a36Sopenharmony_ci tmp_ino->i_mapping->a_ops = &ntfs_mst_aops; 105662306a36Sopenharmony_ci tmp_ni = NTFS_I(tmp_ino); 105762306a36Sopenharmony_ci /* The $MFTMirr, like the $MFT is multi sector transfer protected. */ 105862306a36Sopenharmony_ci NInoSetMstProtected(tmp_ni); 105962306a36Sopenharmony_ci NInoSetSparseDisabled(tmp_ni); 106062306a36Sopenharmony_ci /* 106162306a36Sopenharmony_ci * Set up our little cheat allowing us to reuse the async read io 106262306a36Sopenharmony_ci * completion handler for directories. 106362306a36Sopenharmony_ci */ 106462306a36Sopenharmony_ci tmp_ni->itype.index.block_size = vol->mft_record_size; 106562306a36Sopenharmony_ci tmp_ni->itype.index.block_size_bits = vol->mft_record_size_bits; 106662306a36Sopenharmony_ci vol->mftmirr_ino = tmp_ino; 106762306a36Sopenharmony_ci ntfs_debug("Done."); 106862306a36Sopenharmony_ci return true; 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci/** 107262306a36Sopenharmony_ci * check_mft_mirror - compare contents of the mft mirror with the mft 107362306a36Sopenharmony_ci * @vol: ntfs super block describing device whose mft mirror to check 107462306a36Sopenharmony_ci * 107562306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 107662306a36Sopenharmony_ci * 107762306a36Sopenharmony_ci * Note, this function also results in the mft mirror runlist being completely 107862306a36Sopenharmony_ci * mapped into memory. The mft mirror write code requires this and will BUG() 107962306a36Sopenharmony_ci * should it find an unmapped runlist element. 108062306a36Sopenharmony_ci */ 108162306a36Sopenharmony_cistatic bool check_mft_mirror(ntfs_volume *vol) 108262306a36Sopenharmony_ci{ 108362306a36Sopenharmony_ci struct super_block *sb = vol->sb; 108462306a36Sopenharmony_ci ntfs_inode *mirr_ni; 108562306a36Sopenharmony_ci struct page *mft_page, *mirr_page; 108662306a36Sopenharmony_ci u8 *kmft, *kmirr; 108762306a36Sopenharmony_ci runlist_element *rl, rl2[2]; 108862306a36Sopenharmony_ci pgoff_t index; 108962306a36Sopenharmony_ci int mrecs_per_page, i; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci ntfs_debug("Entering."); 109262306a36Sopenharmony_ci /* Compare contents of $MFT and $MFTMirr. */ 109362306a36Sopenharmony_ci mrecs_per_page = PAGE_SIZE / vol->mft_record_size; 109462306a36Sopenharmony_ci BUG_ON(!mrecs_per_page); 109562306a36Sopenharmony_ci BUG_ON(!vol->mftmirr_size); 109662306a36Sopenharmony_ci mft_page = mirr_page = NULL; 109762306a36Sopenharmony_ci kmft = kmirr = NULL; 109862306a36Sopenharmony_ci index = i = 0; 109962306a36Sopenharmony_ci do { 110062306a36Sopenharmony_ci u32 bytes; 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci /* Switch pages if necessary. */ 110362306a36Sopenharmony_ci if (!(i % mrecs_per_page)) { 110462306a36Sopenharmony_ci if (index) { 110562306a36Sopenharmony_ci ntfs_unmap_page(mft_page); 110662306a36Sopenharmony_ci ntfs_unmap_page(mirr_page); 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci /* Get the $MFT page. */ 110962306a36Sopenharmony_ci mft_page = ntfs_map_page(vol->mft_ino->i_mapping, 111062306a36Sopenharmony_ci index); 111162306a36Sopenharmony_ci if (IS_ERR(mft_page)) { 111262306a36Sopenharmony_ci ntfs_error(sb, "Failed to read $MFT."); 111362306a36Sopenharmony_ci return false; 111462306a36Sopenharmony_ci } 111562306a36Sopenharmony_ci kmft = page_address(mft_page); 111662306a36Sopenharmony_ci /* Get the $MFTMirr page. */ 111762306a36Sopenharmony_ci mirr_page = ntfs_map_page(vol->mftmirr_ino->i_mapping, 111862306a36Sopenharmony_ci index); 111962306a36Sopenharmony_ci if (IS_ERR(mirr_page)) { 112062306a36Sopenharmony_ci ntfs_error(sb, "Failed to read $MFTMirr."); 112162306a36Sopenharmony_ci goto mft_unmap_out; 112262306a36Sopenharmony_ci } 112362306a36Sopenharmony_ci kmirr = page_address(mirr_page); 112462306a36Sopenharmony_ci ++index; 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci /* Do not check the record if it is not in use. */ 112762306a36Sopenharmony_ci if (((MFT_RECORD*)kmft)->flags & MFT_RECORD_IN_USE) { 112862306a36Sopenharmony_ci /* Make sure the record is ok. */ 112962306a36Sopenharmony_ci if (ntfs_is_baad_recordp((le32*)kmft)) { 113062306a36Sopenharmony_ci ntfs_error(sb, "Incomplete multi sector " 113162306a36Sopenharmony_ci "transfer detected in mft " 113262306a36Sopenharmony_ci "record %i.", i); 113362306a36Sopenharmony_cimm_unmap_out: 113462306a36Sopenharmony_ci ntfs_unmap_page(mirr_page); 113562306a36Sopenharmony_cimft_unmap_out: 113662306a36Sopenharmony_ci ntfs_unmap_page(mft_page); 113762306a36Sopenharmony_ci return false; 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci /* Do not check the mirror record if it is not in use. */ 114162306a36Sopenharmony_ci if (((MFT_RECORD*)kmirr)->flags & MFT_RECORD_IN_USE) { 114262306a36Sopenharmony_ci if (ntfs_is_baad_recordp((le32*)kmirr)) { 114362306a36Sopenharmony_ci ntfs_error(sb, "Incomplete multi sector " 114462306a36Sopenharmony_ci "transfer detected in mft " 114562306a36Sopenharmony_ci "mirror record %i.", i); 114662306a36Sopenharmony_ci goto mm_unmap_out; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci } 114962306a36Sopenharmony_ci /* Get the amount of data in the current record. */ 115062306a36Sopenharmony_ci bytes = le32_to_cpu(((MFT_RECORD*)kmft)->bytes_in_use); 115162306a36Sopenharmony_ci if (bytes < sizeof(MFT_RECORD_OLD) || 115262306a36Sopenharmony_ci bytes > vol->mft_record_size || 115362306a36Sopenharmony_ci ntfs_is_baad_recordp((le32*)kmft)) { 115462306a36Sopenharmony_ci bytes = le32_to_cpu(((MFT_RECORD*)kmirr)->bytes_in_use); 115562306a36Sopenharmony_ci if (bytes < sizeof(MFT_RECORD_OLD) || 115662306a36Sopenharmony_ci bytes > vol->mft_record_size || 115762306a36Sopenharmony_ci ntfs_is_baad_recordp((le32*)kmirr)) 115862306a36Sopenharmony_ci bytes = vol->mft_record_size; 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci /* Compare the two records. */ 116162306a36Sopenharmony_ci if (memcmp(kmft, kmirr, bytes)) { 116262306a36Sopenharmony_ci ntfs_error(sb, "$MFT and $MFTMirr (record %i) do not " 116362306a36Sopenharmony_ci "match. Run ntfsfix or chkdsk.", i); 116462306a36Sopenharmony_ci goto mm_unmap_out; 116562306a36Sopenharmony_ci } 116662306a36Sopenharmony_ci kmft += vol->mft_record_size; 116762306a36Sopenharmony_ci kmirr += vol->mft_record_size; 116862306a36Sopenharmony_ci } while (++i < vol->mftmirr_size); 116962306a36Sopenharmony_ci /* Release the last pages. */ 117062306a36Sopenharmony_ci ntfs_unmap_page(mft_page); 117162306a36Sopenharmony_ci ntfs_unmap_page(mirr_page); 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci /* Construct the mft mirror runlist by hand. */ 117462306a36Sopenharmony_ci rl2[0].vcn = 0; 117562306a36Sopenharmony_ci rl2[0].lcn = vol->mftmirr_lcn; 117662306a36Sopenharmony_ci rl2[0].length = (vol->mftmirr_size * vol->mft_record_size + 117762306a36Sopenharmony_ci vol->cluster_size - 1) / vol->cluster_size; 117862306a36Sopenharmony_ci rl2[1].vcn = rl2[0].length; 117962306a36Sopenharmony_ci rl2[1].lcn = LCN_ENOENT; 118062306a36Sopenharmony_ci rl2[1].length = 0; 118162306a36Sopenharmony_ci /* 118262306a36Sopenharmony_ci * Because we have just read all of the mft mirror, we know we have 118362306a36Sopenharmony_ci * mapped the full runlist for it. 118462306a36Sopenharmony_ci */ 118562306a36Sopenharmony_ci mirr_ni = NTFS_I(vol->mftmirr_ino); 118662306a36Sopenharmony_ci down_read(&mirr_ni->runlist.lock); 118762306a36Sopenharmony_ci rl = mirr_ni->runlist.rl; 118862306a36Sopenharmony_ci /* Compare the two runlists. They must be identical. */ 118962306a36Sopenharmony_ci i = 0; 119062306a36Sopenharmony_ci do { 119162306a36Sopenharmony_ci if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn || 119262306a36Sopenharmony_ci rl2[i].length != rl[i].length) { 119362306a36Sopenharmony_ci ntfs_error(sb, "$MFTMirr location mismatch. " 119462306a36Sopenharmony_ci "Run chkdsk."); 119562306a36Sopenharmony_ci up_read(&mirr_ni->runlist.lock); 119662306a36Sopenharmony_ci return false; 119762306a36Sopenharmony_ci } 119862306a36Sopenharmony_ci } while (rl2[i++].length); 119962306a36Sopenharmony_ci up_read(&mirr_ni->runlist.lock); 120062306a36Sopenharmony_ci ntfs_debug("Done."); 120162306a36Sopenharmony_ci return true; 120262306a36Sopenharmony_ci} 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci/** 120562306a36Sopenharmony_ci * load_and_check_logfile - load and check the logfile inode for a volume 120662306a36Sopenharmony_ci * @vol: ntfs super block describing device whose logfile to load 120762306a36Sopenharmony_ci * 120862306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 120962306a36Sopenharmony_ci */ 121062306a36Sopenharmony_cistatic bool load_and_check_logfile(ntfs_volume *vol, 121162306a36Sopenharmony_ci RESTART_PAGE_HEADER **rp) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci struct inode *tmp_ino; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci ntfs_debug("Entering."); 121662306a36Sopenharmony_ci tmp_ino = ntfs_iget(vol->sb, FILE_LogFile); 121762306a36Sopenharmony_ci if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { 121862306a36Sopenharmony_ci if (!IS_ERR(tmp_ino)) 121962306a36Sopenharmony_ci iput(tmp_ino); 122062306a36Sopenharmony_ci /* Caller will display error message. */ 122162306a36Sopenharmony_ci return false; 122262306a36Sopenharmony_ci } 122362306a36Sopenharmony_ci if (!ntfs_check_logfile(tmp_ino, rp)) { 122462306a36Sopenharmony_ci iput(tmp_ino); 122562306a36Sopenharmony_ci /* ntfs_check_logfile() will have displayed error output. */ 122662306a36Sopenharmony_ci return false; 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci NInoSetSparseDisabled(NTFS_I(tmp_ino)); 122962306a36Sopenharmony_ci vol->logfile_ino = tmp_ino; 123062306a36Sopenharmony_ci ntfs_debug("Done."); 123162306a36Sopenharmony_ci return true; 123262306a36Sopenharmony_ci} 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci#define NTFS_HIBERFIL_HEADER_SIZE 4096 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci/** 123762306a36Sopenharmony_ci * check_windows_hibernation_status - check if Windows is suspended on a volume 123862306a36Sopenharmony_ci * @vol: ntfs super block of device to check 123962306a36Sopenharmony_ci * 124062306a36Sopenharmony_ci * Check if Windows is hibernated on the ntfs volume @vol. This is done by 124162306a36Sopenharmony_ci * looking for the file hiberfil.sys in the root directory of the volume. If 124262306a36Sopenharmony_ci * the file is not present Windows is definitely not suspended. 124362306a36Sopenharmony_ci * 124462306a36Sopenharmony_ci * If hiberfil.sys exists and is less than 4kiB in size it means Windows is 124562306a36Sopenharmony_ci * definitely suspended (this volume is not the system volume). Caveat: on a 124662306a36Sopenharmony_ci * system with many volumes it is possible that the < 4kiB check is bogus but 124762306a36Sopenharmony_ci * for now this should do fine. 124862306a36Sopenharmony_ci * 124962306a36Sopenharmony_ci * If hiberfil.sys exists and is larger than 4kiB in size, we need to read the 125062306a36Sopenharmony_ci * hiberfil header (which is the first 4kiB). If this begins with "hibr", 125162306a36Sopenharmony_ci * Windows is definitely suspended. If it is completely full of zeroes, 125262306a36Sopenharmony_ci * Windows is definitely not hibernated. Any other case is treated as if 125362306a36Sopenharmony_ci * Windows is suspended. This caters for the above mentioned caveat of a 125462306a36Sopenharmony_ci * system with many volumes where no "hibr" magic would be present and there is 125562306a36Sopenharmony_ci * no zero header. 125662306a36Sopenharmony_ci * 125762306a36Sopenharmony_ci * Return 0 if Windows is not hibernated on the volume, >0 if Windows is 125862306a36Sopenharmony_ci * hibernated on the volume, and -errno on error. 125962306a36Sopenharmony_ci */ 126062306a36Sopenharmony_cistatic int check_windows_hibernation_status(ntfs_volume *vol) 126162306a36Sopenharmony_ci{ 126262306a36Sopenharmony_ci MFT_REF mref; 126362306a36Sopenharmony_ci struct inode *vi; 126462306a36Sopenharmony_ci struct page *page; 126562306a36Sopenharmony_ci u32 *kaddr, *kend; 126662306a36Sopenharmony_ci ntfs_name *name = NULL; 126762306a36Sopenharmony_ci int ret = 1; 126862306a36Sopenharmony_ci static const ntfschar hiberfil[13] = { cpu_to_le16('h'), 126962306a36Sopenharmony_ci cpu_to_le16('i'), cpu_to_le16('b'), 127062306a36Sopenharmony_ci cpu_to_le16('e'), cpu_to_le16('r'), 127162306a36Sopenharmony_ci cpu_to_le16('f'), cpu_to_le16('i'), 127262306a36Sopenharmony_ci cpu_to_le16('l'), cpu_to_le16('.'), 127362306a36Sopenharmony_ci cpu_to_le16('s'), cpu_to_le16('y'), 127462306a36Sopenharmony_ci cpu_to_le16('s'), 0 }; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci ntfs_debug("Entering."); 127762306a36Sopenharmony_ci /* 127862306a36Sopenharmony_ci * Find the inode number for the hibernation file by looking up the 127962306a36Sopenharmony_ci * filename hiberfil.sys in the root directory. 128062306a36Sopenharmony_ci */ 128162306a36Sopenharmony_ci inode_lock(vol->root_ino); 128262306a36Sopenharmony_ci mref = ntfs_lookup_inode_by_name(NTFS_I(vol->root_ino), hiberfil, 12, 128362306a36Sopenharmony_ci &name); 128462306a36Sopenharmony_ci inode_unlock(vol->root_ino); 128562306a36Sopenharmony_ci if (IS_ERR_MREF(mref)) { 128662306a36Sopenharmony_ci ret = MREF_ERR(mref); 128762306a36Sopenharmony_ci /* If the file does not exist, Windows is not hibernated. */ 128862306a36Sopenharmony_ci if (ret == -ENOENT) { 128962306a36Sopenharmony_ci ntfs_debug("hiberfil.sys not present. Windows is not " 129062306a36Sopenharmony_ci "hibernated on the volume."); 129162306a36Sopenharmony_ci return 0; 129262306a36Sopenharmony_ci } 129362306a36Sopenharmony_ci /* A real error occurred. */ 129462306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to find inode number for " 129562306a36Sopenharmony_ci "hiberfil.sys."); 129662306a36Sopenharmony_ci return ret; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci /* We do not care for the type of match that was found. */ 129962306a36Sopenharmony_ci kfree(name); 130062306a36Sopenharmony_ci /* Get the inode. */ 130162306a36Sopenharmony_ci vi = ntfs_iget(vol->sb, MREF(mref)); 130262306a36Sopenharmony_ci if (IS_ERR(vi) || is_bad_inode(vi)) { 130362306a36Sopenharmony_ci if (!IS_ERR(vi)) 130462306a36Sopenharmony_ci iput(vi); 130562306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load hiberfil.sys."); 130662306a36Sopenharmony_ci return IS_ERR(vi) ? PTR_ERR(vi) : -EIO; 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci if (unlikely(i_size_read(vi) < NTFS_HIBERFIL_HEADER_SIZE)) { 130962306a36Sopenharmony_ci ntfs_debug("hiberfil.sys is smaller than 4kiB (0x%llx). " 131062306a36Sopenharmony_ci "Windows is hibernated on the volume. This " 131162306a36Sopenharmony_ci "is not the system volume.", i_size_read(vi)); 131262306a36Sopenharmony_ci goto iput_out; 131362306a36Sopenharmony_ci } 131462306a36Sopenharmony_ci page = ntfs_map_page(vi->i_mapping, 0); 131562306a36Sopenharmony_ci if (IS_ERR(page)) { 131662306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to read from hiberfil.sys."); 131762306a36Sopenharmony_ci ret = PTR_ERR(page); 131862306a36Sopenharmony_ci goto iput_out; 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci kaddr = (u32*)page_address(page); 132162306a36Sopenharmony_ci if (*(le32*)kaddr == cpu_to_le32(0x72626968)/*'hibr'*/) { 132262306a36Sopenharmony_ci ntfs_debug("Magic \"hibr\" found in hiberfil.sys. Windows is " 132362306a36Sopenharmony_ci "hibernated on the volume. This is the " 132462306a36Sopenharmony_ci "system volume."); 132562306a36Sopenharmony_ci goto unm_iput_out; 132662306a36Sopenharmony_ci } 132762306a36Sopenharmony_ci kend = kaddr + NTFS_HIBERFIL_HEADER_SIZE/sizeof(*kaddr); 132862306a36Sopenharmony_ci do { 132962306a36Sopenharmony_ci if (unlikely(*kaddr)) { 133062306a36Sopenharmony_ci ntfs_debug("hiberfil.sys is larger than 4kiB " 133162306a36Sopenharmony_ci "(0x%llx), does not contain the " 133262306a36Sopenharmony_ci "\"hibr\" magic, and does not have a " 133362306a36Sopenharmony_ci "zero header. Windows is hibernated " 133462306a36Sopenharmony_ci "on the volume. This is not the " 133562306a36Sopenharmony_ci "system volume.", i_size_read(vi)); 133662306a36Sopenharmony_ci goto unm_iput_out; 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci } while (++kaddr < kend); 133962306a36Sopenharmony_ci ntfs_debug("hiberfil.sys contains a zero header. Windows is not " 134062306a36Sopenharmony_ci "hibernated on the volume. This is the system " 134162306a36Sopenharmony_ci "volume."); 134262306a36Sopenharmony_ci ret = 0; 134362306a36Sopenharmony_ciunm_iput_out: 134462306a36Sopenharmony_ci ntfs_unmap_page(page); 134562306a36Sopenharmony_ciiput_out: 134662306a36Sopenharmony_ci iput(vi); 134762306a36Sopenharmony_ci return ret; 134862306a36Sopenharmony_ci} 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci/** 135162306a36Sopenharmony_ci * load_and_init_quota - load and setup the quota file for a volume if present 135262306a36Sopenharmony_ci * @vol: ntfs super block describing device whose quota file to load 135362306a36Sopenharmony_ci * 135462306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. If $Quota is not present, we 135562306a36Sopenharmony_ci * leave vol->quota_ino as NULL and return success. 135662306a36Sopenharmony_ci */ 135762306a36Sopenharmony_cistatic bool load_and_init_quota(ntfs_volume *vol) 135862306a36Sopenharmony_ci{ 135962306a36Sopenharmony_ci MFT_REF mref; 136062306a36Sopenharmony_ci struct inode *tmp_ino; 136162306a36Sopenharmony_ci ntfs_name *name = NULL; 136262306a36Sopenharmony_ci static const ntfschar Quota[7] = { cpu_to_le16('$'), 136362306a36Sopenharmony_ci cpu_to_le16('Q'), cpu_to_le16('u'), 136462306a36Sopenharmony_ci cpu_to_le16('o'), cpu_to_le16('t'), 136562306a36Sopenharmony_ci cpu_to_le16('a'), 0 }; 136662306a36Sopenharmony_ci static ntfschar Q[3] = { cpu_to_le16('$'), 136762306a36Sopenharmony_ci cpu_to_le16('Q'), 0 }; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci ntfs_debug("Entering."); 137062306a36Sopenharmony_ci /* 137162306a36Sopenharmony_ci * Find the inode number for the quota file by looking up the filename 137262306a36Sopenharmony_ci * $Quota in the extended system files directory $Extend. 137362306a36Sopenharmony_ci */ 137462306a36Sopenharmony_ci inode_lock(vol->extend_ino); 137562306a36Sopenharmony_ci mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), Quota, 6, 137662306a36Sopenharmony_ci &name); 137762306a36Sopenharmony_ci inode_unlock(vol->extend_ino); 137862306a36Sopenharmony_ci if (IS_ERR_MREF(mref)) { 137962306a36Sopenharmony_ci /* 138062306a36Sopenharmony_ci * If the file does not exist, quotas are disabled and have 138162306a36Sopenharmony_ci * never been enabled on this volume, just return success. 138262306a36Sopenharmony_ci */ 138362306a36Sopenharmony_ci if (MREF_ERR(mref) == -ENOENT) { 138462306a36Sopenharmony_ci ntfs_debug("$Quota not present. Volume does not have " 138562306a36Sopenharmony_ci "quotas enabled."); 138662306a36Sopenharmony_ci /* 138762306a36Sopenharmony_ci * No need to try to set quotas out of date if they are 138862306a36Sopenharmony_ci * not enabled. 138962306a36Sopenharmony_ci */ 139062306a36Sopenharmony_ci NVolSetQuotaOutOfDate(vol); 139162306a36Sopenharmony_ci return true; 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci /* A real error occurred. */ 139462306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to find inode number for $Quota."); 139562306a36Sopenharmony_ci return false; 139662306a36Sopenharmony_ci } 139762306a36Sopenharmony_ci /* We do not care for the type of match that was found. */ 139862306a36Sopenharmony_ci kfree(name); 139962306a36Sopenharmony_ci /* Get the inode. */ 140062306a36Sopenharmony_ci tmp_ino = ntfs_iget(vol->sb, MREF(mref)); 140162306a36Sopenharmony_ci if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { 140262306a36Sopenharmony_ci if (!IS_ERR(tmp_ino)) 140362306a36Sopenharmony_ci iput(tmp_ino); 140462306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load $Quota."); 140562306a36Sopenharmony_ci return false; 140662306a36Sopenharmony_ci } 140762306a36Sopenharmony_ci vol->quota_ino = tmp_ino; 140862306a36Sopenharmony_ci /* Get the $Q index allocation attribute. */ 140962306a36Sopenharmony_ci tmp_ino = ntfs_index_iget(vol->quota_ino, Q, 2); 141062306a36Sopenharmony_ci if (IS_ERR(tmp_ino)) { 141162306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load $Quota/$Q index."); 141262306a36Sopenharmony_ci return false; 141362306a36Sopenharmony_ci } 141462306a36Sopenharmony_ci vol->quota_q_ino = tmp_ino; 141562306a36Sopenharmony_ci ntfs_debug("Done."); 141662306a36Sopenharmony_ci return true; 141762306a36Sopenharmony_ci} 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci/** 142062306a36Sopenharmony_ci * load_and_init_usnjrnl - load and setup the transaction log if present 142162306a36Sopenharmony_ci * @vol: ntfs super block describing device whose usnjrnl file to load 142262306a36Sopenharmony_ci * 142362306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 142462306a36Sopenharmony_ci * 142562306a36Sopenharmony_ci * If $UsnJrnl is not present or in the process of being disabled, we set 142662306a36Sopenharmony_ci * NVolUsnJrnlStamped() and return success. 142762306a36Sopenharmony_ci * 142862306a36Sopenharmony_ci * If the $UsnJrnl $DATA/$J attribute has a size equal to the lowest valid usn, 142962306a36Sopenharmony_ci * i.e. transaction logging has only just been enabled or the journal has been 143062306a36Sopenharmony_ci * stamped and nothing has been logged since, we also set NVolUsnJrnlStamped() 143162306a36Sopenharmony_ci * and return success. 143262306a36Sopenharmony_ci */ 143362306a36Sopenharmony_cistatic bool load_and_init_usnjrnl(ntfs_volume *vol) 143462306a36Sopenharmony_ci{ 143562306a36Sopenharmony_ci MFT_REF mref; 143662306a36Sopenharmony_ci struct inode *tmp_ino; 143762306a36Sopenharmony_ci ntfs_inode *tmp_ni; 143862306a36Sopenharmony_ci struct page *page; 143962306a36Sopenharmony_ci ntfs_name *name = NULL; 144062306a36Sopenharmony_ci USN_HEADER *uh; 144162306a36Sopenharmony_ci static const ntfschar UsnJrnl[9] = { cpu_to_le16('$'), 144262306a36Sopenharmony_ci cpu_to_le16('U'), cpu_to_le16('s'), 144362306a36Sopenharmony_ci cpu_to_le16('n'), cpu_to_le16('J'), 144462306a36Sopenharmony_ci cpu_to_le16('r'), cpu_to_le16('n'), 144562306a36Sopenharmony_ci cpu_to_le16('l'), 0 }; 144662306a36Sopenharmony_ci static ntfschar Max[5] = { cpu_to_le16('$'), 144762306a36Sopenharmony_ci cpu_to_le16('M'), cpu_to_le16('a'), 144862306a36Sopenharmony_ci cpu_to_le16('x'), 0 }; 144962306a36Sopenharmony_ci static ntfschar J[3] = { cpu_to_le16('$'), 145062306a36Sopenharmony_ci cpu_to_le16('J'), 0 }; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci ntfs_debug("Entering."); 145362306a36Sopenharmony_ci /* 145462306a36Sopenharmony_ci * Find the inode number for the transaction log file by looking up the 145562306a36Sopenharmony_ci * filename $UsnJrnl in the extended system files directory $Extend. 145662306a36Sopenharmony_ci */ 145762306a36Sopenharmony_ci inode_lock(vol->extend_ino); 145862306a36Sopenharmony_ci mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8, 145962306a36Sopenharmony_ci &name); 146062306a36Sopenharmony_ci inode_unlock(vol->extend_ino); 146162306a36Sopenharmony_ci if (IS_ERR_MREF(mref)) { 146262306a36Sopenharmony_ci /* 146362306a36Sopenharmony_ci * If the file does not exist, transaction logging is disabled, 146462306a36Sopenharmony_ci * just return success. 146562306a36Sopenharmony_ci */ 146662306a36Sopenharmony_ci if (MREF_ERR(mref) == -ENOENT) { 146762306a36Sopenharmony_ci ntfs_debug("$UsnJrnl not present. Volume does not " 146862306a36Sopenharmony_ci "have transaction logging enabled."); 146962306a36Sopenharmony_cinot_enabled: 147062306a36Sopenharmony_ci /* 147162306a36Sopenharmony_ci * No need to try to stamp the transaction log if 147262306a36Sopenharmony_ci * transaction logging is not enabled. 147362306a36Sopenharmony_ci */ 147462306a36Sopenharmony_ci NVolSetUsnJrnlStamped(vol); 147562306a36Sopenharmony_ci return true; 147662306a36Sopenharmony_ci } 147762306a36Sopenharmony_ci /* A real error occurred. */ 147862306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to find inode number for " 147962306a36Sopenharmony_ci "$UsnJrnl."); 148062306a36Sopenharmony_ci return false; 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci /* We do not care for the type of match that was found. */ 148362306a36Sopenharmony_ci kfree(name); 148462306a36Sopenharmony_ci /* Get the inode. */ 148562306a36Sopenharmony_ci tmp_ino = ntfs_iget(vol->sb, MREF(mref)); 148662306a36Sopenharmony_ci if (IS_ERR(tmp_ino) || unlikely(is_bad_inode(tmp_ino))) { 148762306a36Sopenharmony_ci if (!IS_ERR(tmp_ino)) 148862306a36Sopenharmony_ci iput(tmp_ino); 148962306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load $UsnJrnl."); 149062306a36Sopenharmony_ci return false; 149162306a36Sopenharmony_ci } 149262306a36Sopenharmony_ci vol->usnjrnl_ino = tmp_ino; 149362306a36Sopenharmony_ci /* 149462306a36Sopenharmony_ci * If the transaction log is in the process of being deleted, we can 149562306a36Sopenharmony_ci * ignore it. 149662306a36Sopenharmony_ci */ 149762306a36Sopenharmony_ci if (unlikely(vol->vol_flags & VOLUME_DELETE_USN_UNDERWAY)) { 149862306a36Sopenharmony_ci ntfs_debug("$UsnJrnl in the process of being disabled. " 149962306a36Sopenharmony_ci "Volume does not have transaction logging " 150062306a36Sopenharmony_ci "enabled."); 150162306a36Sopenharmony_ci goto not_enabled; 150262306a36Sopenharmony_ci } 150362306a36Sopenharmony_ci /* Get the $DATA/$Max attribute. */ 150462306a36Sopenharmony_ci tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, Max, 4); 150562306a36Sopenharmony_ci if (IS_ERR(tmp_ino)) { 150662306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$Max " 150762306a36Sopenharmony_ci "attribute."); 150862306a36Sopenharmony_ci return false; 150962306a36Sopenharmony_ci } 151062306a36Sopenharmony_ci vol->usnjrnl_max_ino = tmp_ino; 151162306a36Sopenharmony_ci if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) { 151262306a36Sopenharmony_ci ntfs_error(vol->sb, "Found corrupt $UsnJrnl/$DATA/$Max " 151362306a36Sopenharmony_ci "attribute (size is 0x%llx but should be at " 151462306a36Sopenharmony_ci "least 0x%zx bytes).", i_size_read(tmp_ino), 151562306a36Sopenharmony_ci sizeof(USN_HEADER)); 151662306a36Sopenharmony_ci return false; 151762306a36Sopenharmony_ci } 151862306a36Sopenharmony_ci /* Get the $DATA/$J attribute. */ 151962306a36Sopenharmony_ci tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, J, 2); 152062306a36Sopenharmony_ci if (IS_ERR(tmp_ino)) { 152162306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$J " 152262306a36Sopenharmony_ci "attribute."); 152362306a36Sopenharmony_ci return false; 152462306a36Sopenharmony_ci } 152562306a36Sopenharmony_ci vol->usnjrnl_j_ino = tmp_ino; 152662306a36Sopenharmony_ci /* Verify $J is non-resident and sparse. */ 152762306a36Sopenharmony_ci tmp_ni = NTFS_I(vol->usnjrnl_j_ino); 152862306a36Sopenharmony_ci if (unlikely(!NInoNonResident(tmp_ni) || !NInoSparse(tmp_ni))) { 152962306a36Sopenharmony_ci ntfs_error(vol->sb, "$UsnJrnl/$DATA/$J attribute is resident " 153062306a36Sopenharmony_ci "and/or not sparse."); 153162306a36Sopenharmony_ci return false; 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci /* Read the USN_HEADER from $DATA/$Max. */ 153462306a36Sopenharmony_ci page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0); 153562306a36Sopenharmony_ci if (IS_ERR(page)) { 153662306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to read from $UsnJrnl/$DATA/$Max " 153762306a36Sopenharmony_ci "attribute."); 153862306a36Sopenharmony_ci return false; 153962306a36Sopenharmony_ci } 154062306a36Sopenharmony_ci uh = (USN_HEADER*)page_address(page); 154162306a36Sopenharmony_ci /* Sanity check the $Max. */ 154262306a36Sopenharmony_ci if (unlikely(sle64_to_cpu(uh->allocation_delta) > 154362306a36Sopenharmony_ci sle64_to_cpu(uh->maximum_size))) { 154462306a36Sopenharmony_ci ntfs_error(vol->sb, "Allocation delta (0x%llx) exceeds " 154562306a36Sopenharmony_ci "maximum size (0x%llx). $UsnJrnl is corrupt.", 154662306a36Sopenharmony_ci (long long)sle64_to_cpu(uh->allocation_delta), 154762306a36Sopenharmony_ci (long long)sle64_to_cpu(uh->maximum_size)); 154862306a36Sopenharmony_ci ntfs_unmap_page(page); 154962306a36Sopenharmony_ci return false; 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci /* 155262306a36Sopenharmony_ci * If the transaction log has been stamped and nothing has been written 155362306a36Sopenharmony_ci * to it since, we do not need to stamp it. 155462306a36Sopenharmony_ci */ 155562306a36Sopenharmony_ci if (unlikely(sle64_to_cpu(uh->lowest_valid_usn) >= 155662306a36Sopenharmony_ci i_size_read(vol->usnjrnl_j_ino))) { 155762306a36Sopenharmony_ci if (likely(sle64_to_cpu(uh->lowest_valid_usn) == 155862306a36Sopenharmony_ci i_size_read(vol->usnjrnl_j_ino))) { 155962306a36Sopenharmony_ci ntfs_unmap_page(page); 156062306a36Sopenharmony_ci ntfs_debug("$UsnJrnl is enabled but nothing has been " 156162306a36Sopenharmony_ci "logged since it was last stamped. " 156262306a36Sopenharmony_ci "Treating this as if the volume does " 156362306a36Sopenharmony_ci "not have transaction logging " 156462306a36Sopenharmony_ci "enabled."); 156562306a36Sopenharmony_ci goto not_enabled; 156662306a36Sopenharmony_ci } 156762306a36Sopenharmony_ci ntfs_error(vol->sb, "$UsnJrnl has lowest valid usn (0x%llx) " 156862306a36Sopenharmony_ci "which is out of bounds (0x%llx). $UsnJrnl " 156962306a36Sopenharmony_ci "is corrupt.", 157062306a36Sopenharmony_ci (long long)sle64_to_cpu(uh->lowest_valid_usn), 157162306a36Sopenharmony_ci i_size_read(vol->usnjrnl_j_ino)); 157262306a36Sopenharmony_ci ntfs_unmap_page(page); 157362306a36Sopenharmony_ci return false; 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci ntfs_unmap_page(page); 157662306a36Sopenharmony_ci ntfs_debug("Done."); 157762306a36Sopenharmony_ci return true; 157862306a36Sopenharmony_ci} 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci/** 158162306a36Sopenharmony_ci * load_and_init_attrdef - load the attribute definitions table for a volume 158262306a36Sopenharmony_ci * @vol: ntfs super block describing device whose attrdef to load 158362306a36Sopenharmony_ci * 158462306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 158562306a36Sopenharmony_ci */ 158662306a36Sopenharmony_cistatic bool load_and_init_attrdef(ntfs_volume *vol) 158762306a36Sopenharmony_ci{ 158862306a36Sopenharmony_ci loff_t i_size; 158962306a36Sopenharmony_ci struct super_block *sb = vol->sb; 159062306a36Sopenharmony_ci struct inode *ino; 159162306a36Sopenharmony_ci struct page *page; 159262306a36Sopenharmony_ci pgoff_t index, max_index; 159362306a36Sopenharmony_ci unsigned int size; 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci ntfs_debug("Entering."); 159662306a36Sopenharmony_ci /* Read attrdef table and setup vol->attrdef and vol->attrdef_size. */ 159762306a36Sopenharmony_ci ino = ntfs_iget(sb, FILE_AttrDef); 159862306a36Sopenharmony_ci if (IS_ERR(ino) || is_bad_inode(ino)) { 159962306a36Sopenharmony_ci if (!IS_ERR(ino)) 160062306a36Sopenharmony_ci iput(ino); 160162306a36Sopenharmony_ci goto failed; 160262306a36Sopenharmony_ci } 160362306a36Sopenharmony_ci NInoSetSparseDisabled(NTFS_I(ino)); 160462306a36Sopenharmony_ci /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */ 160562306a36Sopenharmony_ci i_size = i_size_read(ino); 160662306a36Sopenharmony_ci if (i_size <= 0 || i_size > 0x7fffffff) 160762306a36Sopenharmony_ci goto iput_failed; 160862306a36Sopenharmony_ci vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(i_size); 160962306a36Sopenharmony_ci if (!vol->attrdef) 161062306a36Sopenharmony_ci goto iput_failed; 161162306a36Sopenharmony_ci index = 0; 161262306a36Sopenharmony_ci max_index = i_size >> PAGE_SHIFT; 161362306a36Sopenharmony_ci size = PAGE_SIZE; 161462306a36Sopenharmony_ci while (index < max_index) { 161562306a36Sopenharmony_ci /* Read the attrdef table and copy it into the linear buffer. */ 161662306a36Sopenharmony_ciread_partial_attrdef_page: 161762306a36Sopenharmony_ci page = ntfs_map_page(ino->i_mapping, index); 161862306a36Sopenharmony_ci if (IS_ERR(page)) 161962306a36Sopenharmony_ci goto free_iput_failed; 162062306a36Sopenharmony_ci memcpy((u8*)vol->attrdef + (index++ << PAGE_SHIFT), 162162306a36Sopenharmony_ci page_address(page), size); 162262306a36Sopenharmony_ci ntfs_unmap_page(page); 162362306a36Sopenharmony_ci } 162462306a36Sopenharmony_ci if (size == PAGE_SIZE) { 162562306a36Sopenharmony_ci size = i_size & ~PAGE_MASK; 162662306a36Sopenharmony_ci if (size) 162762306a36Sopenharmony_ci goto read_partial_attrdef_page; 162862306a36Sopenharmony_ci } 162962306a36Sopenharmony_ci vol->attrdef_size = i_size; 163062306a36Sopenharmony_ci ntfs_debug("Read %llu bytes from $AttrDef.", i_size); 163162306a36Sopenharmony_ci iput(ino); 163262306a36Sopenharmony_ci return true; 163362306a36Sopenharmony_cifree_iput_failed: 163462306a36Sopenharmony_ci ntfs_free(vol->attrdef); 163562306a36Sopenharmony_ci vol->attrdef = NULL; 163662306a36Sopenharmony_ciiput_failed: 163762306a36Sopenharmony_ci iput(ino); 163862306a36Sopenharmony_cifailed: 163962306a36Sopenharmony_ci ntfs_error(sb, "Failed to initialize attribute definition table."); 164062306a36Sopenharmony_ci return false; 164162306a36Sopenharmony_ci} 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci#endif /* NTFS_RW */ 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci/** 164662306a36Sopenharmony_ci * load_and_init_upcase - load the upcase table for an ntfs volume 164762306a36Sopenharmony_ci * @vol: ntfs super block describing device whose upcase to load 164862306a36Sopenharmony_ci * 164962306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 165062306a36Sopenharmony_ci */ 165162306a36Sopenharmony_cistatic bool load_and_init_upcase(ntfs_volume *vol) 165262306a36Sopenharmony_ci{ 165362306a36Sopenharmony_ci loff_t i_size; 165462306a36Sopenharmony_ci struct super_block *sb = vol->sb; 165562306a36Sopenharmony_ci struct inode *ino; 165662306a36Sopenharmony_ci struct page *page; 165762306a36Sopenharmony_ci pgoff_t index, max_index; 165862306a36Sopenharmony_ci unsigned int size; 165962306a36Sopenharmony_ci int i, max; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci ntfs_debug("Entering."); 166262306a36Sopenharmony_ci /* Read upcase table and setup vol->upcase and vol->upcase_len. */ 166362306a36Sopenharmony_ci ino = ntfs_iget(sb, FILE_UpCase); 166462306a36Sopenharmony_ci if (IS_ERR(ino) || is_bad_inode(ino)) { 166562306a36Sopenharmony_ci if (!IS_ERR(ino)) 166662306a36Sopenharmony_ci iput(ino); 166762306a36Sopenharmony_ci goto upcase_failed; 166862306a36Sopenharmony_ci } 166962306a36Sopenharmony_ci /* 167062306a36Sopenharmony_ci * The upcase size must not be above 64k Unicode characters, must not 167162306a36Sopenharmony_ci * be zero and must be a multiple of sizeof(ntfschar). 167262306a36Sopenharmony_ci */ 167362306a36Sopenharmony_ci i_size = i_size_read(ino); 167462306a36Sopenharmony_ci if (!i_size || i_size & (sizeof(ntfschar) - 1) || 167562306a36Sopenharmony_ci i_size > 64ULL * 1024 * sizeof(ntfschar)) 167662306a36Sopenharmony_ci goto iput_upcase_failed; 167762306a36Sopenharmony_ci vol->upcase = (ntfschar*)ntfs_malloc_nofs(i_size); 167862306a36Sopenharmony_ci if (!vol->upcase) 167962306a36Sopenharmony_ci goto iput_upcase_failed; 168062306a36Sopenharmony_ci index = 0; 168162306a36Sopenharmony_ci max_index = i_size >> PAGE_SHIFT; 168262306a36Sopenharmony_ci size = PAGE_SIZE; 168362306a36Sopenharmony_ci while (index < max_index) { 168462306a36Sopenharmony_ci /* Read the upcase table and copy it into the linear buffer. */ 168562306a36Sopenharmony_ciread_partial_upcase_page: 168662306a36Sopenharmony_ci page = ntfs_map_page(ino->i_mapping, index); 168762306a36Sopenharmony_ci if (IS_ERR(page)) 168862306a36Sopenharmony_ci goto iput_upcase_failed; 168962306a36Sopenharmony_ci memcpy((char*)vol->upcase + (index++ << PAGE_SHIFT), 169062306a36Sopenharmony_ci page_address(page), size); 169162306a36Sopenharmony_ci ntfs_unmap_page(page); 169262306a36Sopenharmony_ci } 169362306a36Sopenharmony_ci if (size == PAGE_SIZE) { 169462306a36Sopenharmony_ci size = i_size & ~PAGE_MASK; 169562306a36Sopenharmony_ci if (size) 169662306a36Sopenharmony_ci goto read_partial_upcase_page; 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci vol->upcase_len = i_size >> UCHAR_T_SIZE_BITS; 169962306a36Sopenharmony_ci ntfs_debug("Read %llu bytes from $UpCase (expected %zu bytes).", 170062306a36Sopenharmony_ci i_size, 64 * 1024 * sizeof(ntfschar)); 170162306a36Sopenharmony_ci iput(ino); 170262306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 170362306a36Sopenharmony_ci if (!default_upcase) { 170462306a36Sopenharmony_ci ntfs_debug("Using volume specified $UpCase since default is " 170562306a36Sopenharmony_ci "not present."); 170662306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 170762306a36Sopenharmony_ci return true; 170862306a36Sopenharmony_ci } 170962306a36Sopenharmony_ci max = default_upcase_len; 171062306a36Sopenharmony_ci if (max > vol->upcase_len) 171162306a36Sopenharmony_ci max = vol->upcase_len; 171262306a36Sopenharmony_ci for (i = 0; i < max; i++) 171362306a36Sopenharmony_ci if (vol->upcase[i] != default_upcase[i]) 171462306a36Sopenharmony_ci break; 171562306a36Sopenharmony_ci if (i == max) { 171662306a36Sopenharmony_ci ntfs_free(vol->upcase); 171762306a36Sopenharmony_ci vol->upcase = default_upcase; 171862306a36Sopenharmony_ci vol->upcase_len = max; 171962306a36Sopenharmony_ci ntfs_nr_upcase_users++; 172062306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 172162306a36Sopenharmony_ci ntfs_debug("Volume specified $UpCase matches default. Using " 172262306a36Sopenharmony_ci "default."); 172362306a36Sopenharmony_ci return true; 172462306a36Sopenharmony_ci } 172562306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 172662306a36Sopenharmony_ci ntfs_debug("Using volume specified $UpCase since it does not match " 172762306a36Sopenharmony_ci "the default."); 172862306a36Sopenharmony_ci return true; 172962306a36Sopenharmony_ciiput_upcase_failed: 173062306a36Sopenharmony_ci iput(ino); 173162306a36Sopenharmony_ci ntfs_free(vol->upcase); 173262306a36Sopenharmony_ci vol->upcase = NULL; 173362306a36Sopenharmony_ciupcase_failed: 173462306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 173562306a36Sopenharmony_ci if (default_upcase) { 173662306a36Sopenharmony_ci vol->upcase = default_upcase; 173762306a36Sopenharmony_ci vol->upcase_len = default_upcase_len; 173862306a36Sopenharmony_ci ntfs_nr_upcase_users++; 173962306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 174062306a36Sopenharmony_ci ntfs_error(sb, "Failed to load $UpCase from the volume. Using " 174162306a36Sopenharmony_ci "default."); 174262306a36Sopenharmony_ci return true; 174362306a36Sopenharmony_ci } 174462306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 174562306a36Sopenharmony_ci ntfs_error(sb, "Failed to initialize upcase table."); 174662306a36Sopenharmony_ci return false; 174762306a36Sopenharmony_ci} 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci/* 175062306a36Sopenharmony_ci * The lcn and mft bitmap inodes are NTFS-internal inodes with 175162306a36Sopenharmony_ci * their own special locking rules: 175262306a36Sopenharmony_ci */ 175362306a36Sopenharmony_cistatic struct lock_class_key 175462306a36Sopenharmony_ci lcnbmp_runlist_lock_key, lcnbmp_mrec_lock_key, 175562306a36Sopenharmony_ci mftbmp_runlist_lock_key, mftbmp_mrec_lock_key; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci/** 175862306a36Sopenharmony_ci * load_system_files - open the system files using normal functions 175962306a36Sopenharmony_ci * @vol: ntfs super block describing device whose system files to load 176062306a36Sopenharmony_ci * 176162306a36Sopenharmony_ci * Open the system files with normal access functions and complete setting up 176262306a36Sopenharmony_ci * the ntfs super block @vol. 176362306a36Sopenharmony_ci * 176462306a36Sopenharmony_ci * Return 'true' on success or 'false' on error. 176562306a36Sopenharmony_ci */ 176662306a36Sopenharmony_cistatic bool load_system_files(ntfs_volume *vol) 176762306a36Sopenharmony_ci{ 176862306a36Sopenharmony_ci struct super_block *sb = vol->sb; 176962306a36Sopenharmony_ci MFT_RECORD *m; 177062306a36Sopenharmony_ci VOLUME_INFORMATION *vi; 177162306a36Sopenharmony_ci ntfs_attr_search_ctx *ctx; 177262306a36Sopenharmony_ci#ifdef NTFS_RW 177362306a36Sopenharmony_ci RESTART_PAGE_HEADER *rp; 177462306a36Sopenharmony_ci int err; 177562306a36Sopenharmony_ci#endif /* NTFS_RW */ 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci ntfs_debug("Entering."); 177862306a36Sopenharmony_ci#ifdef NTFS_RW 177962306a36Sopenharmony_ci /* Get mft mirror inode compare the contents of $MFT and $MFTMirr. */ 178062306a36Sopenharmony_ci if (!load_and_init_mft_mirror(vol) || !check_mft_mirror(vol)) { 178162306a36Sopenharmony_ci static const char *es1 = "Failed to load $MFTMirr"; 178262306a36Sopenharmony_ci static const char *es2 = "$MFTMirr does not match $MFT"; 178362306a36Sopenharmony_ci static const char *es3 = ". Run ntfsfix and/or chkdsk."; 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci /* If a read-write mount, convert it to a read-only mount. */ 178662306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 178762306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 178862306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 178962306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=" 179062306a36Sopenharmony_ci "continue nor on_errors=" 179162306a36Sopenharmony_ci "remount-ro was specified%s", 179262306a36Sopenharmony_ci !vol->mftmirr_ino ? es1 : es2, 179362306a36Sopenharmony_ci es3); 179462306a36Sopenharmony_ci goto iput_mirr_err_out; 179562306a36Sopenharmony_ci } 179662306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 179762306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", 179862306a36Sopenharmony_ci !vol->mftmirr_ino ? es1 : es2, es3); 179962306a36Sopenharmony_ci } else 180062306a36Sopenharmony_ci ntfs_warning(sb, "%s. Will not be able to remount " 180162306a36Sopenharmony_ci "read-write%s", 180262306a36Sopenharmony_ci !vol->mftmirr_ino ? es1 : es2, es3); 180362306a36Sopenharmony_ci /* This will prevent a read-write remount. */ 180462306a36Sopenharmony_ci NVolSetErrors(vol); 180562306a36Sopenharmony_ci } 180662306a36Sopenharmony_ci#endif /* NTFS_RW */ 180762306a36Sopenharmony_ci /* Get mft bitmap attribute inode. */ 180862306a36Sopenharmony_ci vol->mftbmp_ino = ntfs_attr_iget(vol->mft_ino, AT_BITMAP, NULL, 0); 180962306a36Sopenharmony_ci if (IS_ERR(vol->mftbmp_ino)) { 181062306a36Sopenharmony_ci ntfs_error(sb, "Failed to load $MFT/$BITMAP attribute."); 181162306a36Sopenharmony_ci goto iput_mirr_err_out; 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci lockdep_set_class(&NTFS_I(vol->mftbmp_ino)->runlist.lock, 181462306a36Sopenharmony_ci &mftbmp_runlist_lock_key); 181562306a36Sopenharmony_ci lockdep_set_class(&NTFS_I(vol->mftbmp_ino)->mrec_lock, 181662306a36Sopenharmony_ci &mftbmp_mrec_lock_key); 181762306a36Sopenharmony_ci /* Read upcase table and setup @vol->upcase and @vol->upcase_len. */ 181862306a36Sopenharmony_ci if (!load_and_init_upcase(vol)) 181962306a36Sopenharmony_ci goto iput_mftbmp_err_out; 182062306a36Sopenharmony_ci#ifdef NTFS_RW 182162306a36Sopenharmony_ci /* 182262306a36Sopenharmony_ci * Read attribute definitions table and setup @vol->attrdef and 182362306a36Sopenharmony_ci * @vol->attrdef_size. 182462306a36Sopenharmony_ci */ 182562306a36Sopenharmony_ci if (!load_and_init_attrdef(vol)) 182662306a36Sopenharmony_ci goto iput_upcase_err_out; 182762306a36Sopenharmony_ci#endif /* NTFS_RW */ 182862306a36Sopenharmony_ci /* 182962306a36Sopenharmony_ci * Get the cluster allocation bitmap inode and verify the size, no 183062306a36Sopenharmony_ci * need for any locking at this stage as we are already running 183162306a36Sopenharmony_ci * exclusively as we are mount in progress task. 183262306a36Sopenharmony_ci */ 183362306a36Sopenharmony_ci vol->lcnbmp_ino = ntfs_iget(sb, FILE_Bitmap); 183462306a36Sopenharmony_ci if (IS_ERR(vol->lcnbmp_ino) || is_bad_inode(vol->lcnbmp_ino)) { 183562306a36Sopenharmony_ci if (!IS_ERR(vol->lcnbmp_ino)) 183662306a36Sopenharmony_ci iput(vol->lcnbmp_ino); 183762306a36Sopenharmony_ci goto bitmap_failed; 183862306a36Sopenharmony_ci } 183962306a36Sopenharmony_ci lockdep_set_class(&NTFS_I(vol->lcnbmp_ino)->runlist.lock, 184062306a36Sopenharmony_ci &lcnbmp_runlist_lock_key); 184162306a36Sopenharmony_ci lockdep_set_class(&NTFS_I(vol->lcnbmp_ino)->mrec_lock, 184262306a36Sopenharmony_ci &lcnbmp_mrec_lock_key); 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci NInoSetSparseDisabled(NTFS_I(vol->lcnbmp_ino)); 184562306a36Sopenharmony_ci if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) { 184662306a36Sopenharmony_ci iput(vol->lcnbmp_ino); 184762306a36Sopenharmony_cibitmap_failed: 184862306a36Sopenharmony_ci ntfs_error(sb, "Failed to load $Bitmap."); 184962306a36Sopenharmony_ci goto iput_attrdef_err_out; 185062306a36Sopenharmony_ci } 185162306a36Sopenharmony_ci /* 185262306a36Sopenharmony_ci * Get the volume inode and setup our cache of the volume flags and 185362306a36Sopenharmony_ci * version. 185462306a36Sopenharmony_ci */ 185562306a36Sopenharmony_ci vol->vol_ino = ntfs_iget(sb, FILE_Volume); 185662306a36Sopenharmony_ci if (IS_ERR(vol->vol_ino) || is_bad_inode(vol->vol_ino)) { 185762306a36Sopenharmony_ci if (!IS_ERR(vol->vol_ino)) 185862306a36Sopenharmony_ci iput(vol->vol_ino); 185962306a36Sopenharmony_civolume_failed: 186062306a36Sopenharmony_ci ntfs_error(sb, "Failed to load $Volume."); 186162306a36Sopenharmony_ci goto iput_lcnbmp_err_out; 186262306a36Sopenharmony_ci } 186362306a36Sopenharmony_ci m = map_mft_record(NTFS_I(vol->vol_ino)); 186462306a36Sopenharmony_ci if (IS_ERR(m)) { 186562306a36Sopenharmony_ciiput_volume_failed: 186662306a36Sopenharmony_ci iput(vol->vol_ino); 186762306a36Sopenharmony_ci goto volume_failed; 186862306a36Sopenharmony_ci } 186962306a36Sopenharmony_ci if (!(ctx = ntfs_attr_get_search_ctx(NTFS_I(vol->vol_ino), m))) { 187062306a36Sopenharmony_ci ntfs_error(sb, "Failed to get attribute search context."); 187162306a36Sopenharmony_ci goto get_ctx_vol_failed; 187262306a36Sopenharmony_ci } 187362306a36Sopenharmony_ci if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0, 187462306a36Sopenharmony_ci ctx) || ctx->attr->non_resident || ctx->attr->flags) { 187562306a36Sopenharmony_cierr_put_vol: 187662306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 187762306a36Sopenharmony_ciget_ctx_vol_failed: 187862306a36Sopenharmony_ci unmap_mft_record(NTFS_I(vol->vol_ino)); 187962306a36Sopenharmony_ci goto iput_volume_failed; 188062306a36Sopenharmony_ci } 188162306a36Sopenharmony_ci vi = (VOLUME_INFORMATION*)((char*)ctx->attr + 188262306a36Sopenharmony_ci le16_to_cpu(ctx->attr->data.resident.value_offset)); 188362306a36Sopenharmony_ci /* Some bounds checks. */ 188462306a36Sopenharmony_ci if ((u8*)vi < (u8*)ctx->attr || (u8*)vi + 188562306a36Sopenharmony_ci le32_to_cpu(ctx->attr->data.resident.value_length) > 188662306a36Sopenharmony_ci (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) 188762306a36Sopenharmony_ci goto err_put_vol; 188862306a36Sopenharmony_ci /* Copy the volume flags and version to the ntfs_volume structure. */ 188962306a36Sopenharmony_ci vol->vol_flags = vi->flags; 189062306a36Sopenharmony_ci vol->major_ver = vi->major_ver; 189162306a36Sopenharmony_ci vol->minor_ver = vi->minor_ver; 189262306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 189362306a36Sopenharmony_ci unmap_mft_record(NTFS_I(vol->vol_ino)); 189462306a36Sopenharmony_ci pr_info("volume version %i.%i.\n", vol->major_ver, 189562306a36Sopenharmony_ci vol->minor_ver); 189662306a36Sopenharmony_ci if (vol->major_ver < 3 && NVolSparseEnabled(vol)) { 189762306a36Sopenharmony_ci ntfs_warning(vol->sb, "Disabling sparse support due to NTFS " 189862306a36Sopenharmony_ci "volume version %i.%i (need at least version " 189962306a36Sopenharmony_ci "3.0).", vol->major_ver, vol->minor_ver); 190062306a36Sopenharmony_ci NVolClearSparseEnabled(vol); 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci#ifdef NTFS_RW 190362306a36Sopenharmony_ci /* Make sure that no unsupported volume flags are set. */ 190462306a36Sopenharmony_ci if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) { 190562306a36Sopenharmony_ci static const char *es1a = "Volume is dirty"; 190662306a36Sopenharmony_ci static const char *es1b = "Volume has been modified by chkdsk"; 190762306a36Sopenharmony_ci static const char *es1c = "Volume has unsupported flags set"; 190862306a36Sopenharmony_ci static const char *es2a = ". Run chkdsk and mount in Windows."; 190962306a36Sopenharmony_ci static const char *es2b = ". Mount in Windows."; 191062306a36Sopenharmony_ci const char *es1, *es2; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci es2 = es2a; 191362306a36Sopenharmony_ci if (vol->vol_flags & VOLUME_IS_DIRTY) 191462306a36Sopenharmony_ci es1 = es1a; 191562306a36Sopenharmony_ci else if (vol->vol_flags & VOLUME_MODIFIED_BY_CHKDSK) { 191662306a36Sopenharmony_ci es1 = es1b; 191762306a36Sopenharmony_ci es2 = es2b; 191862306a36Sopenharmony_ci } else { 191962306a36Sopenharmony_ci es1 = es1c; 192062306a36Sopenharmony_ci ntfs_warning(sb, "Unsupported volume flags 0x%x " 192162306a36Sopenharmony_ci "encountered.", 192262306a36Sopenharmony_ci (unsigned)le16_to_cpu(vol->vol_flags)); 192362306a36Sopenharmony_ci } 192462306a36Sopenharmony_ci /* If a read-write mount, convert it to a read-only mount. */ 192562306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 192662306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 192762306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 192862306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=" 192962306a36Sopenharmony_ci "continue nor on_errors=" 193062306a36Sopenharmony_ci "remount-ro was specified%s", 193162306a36Sopenharmony_ci es1, es2); 193262306a36Sopenharmony_ci goto iput_vol_err_out; 193362306a36Sopenharmony_ci } 193462306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 193562306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 193662306a36Sopenharmony_ci } else 193762306a36Sopenharmony_ci ntfs_warning(sb, "%s. Will not be able to remount " 193862306a36Sopenharmony_ci "read-write%s", es1, es2); 193962306a36Sopenharmony_ci /* 194062306a36Sopenharmony_ci * Do not set NVolErrors() because ntfs_remount() re-checks the 194162306a36Sopenharmony_ci * flags which we need to do in case any flags have changed. 194262306a36Sopenharmony_ci */ 194362306a36Sopenharmony_ci } 194462306a36Sopenharmony_ci /* 194562306a36Sopenharmony_ci * Get the inode for the logfile, check it and determine if the volume 194662306a36Sopenharmony_ci * was shutdown cleanly. 194762306a36Sopenharmony_ci */ 194862306a36Sopenharmony_ci rp = NULL; 194962306a36Sopenharmony_ci if (!load_and_check_logfile(vol, &rp) || 195062306a36Sopenharmony_ci !ntfs_is_logfile_clean(vol->logfile_ino, rp)) { 195162306a36Sopenharmony_ci static const char *es1a = "Failed to load $LogFile"; 195262306a36Sopenharmony_ci static const char *es1b = "$LogFile is not clean"; 195362306a36Sopenharmony_ci static const char *es2 = ". Mount in Windows."; 195462306a36Sopenharmony_ci const char *es1; 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci es1 = !vol->logfile_ino ? es1a : es1b; 195762306a36Sopenharmony_ci /* If a read-write mount, convert it to a read-only mount. */ 195862306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 195962306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 196062306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 196162306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=" 196262306a36Sopenharmony_ci "continue nor on_errors=" 196362306a36Sopenharmony_ci "remount-ro was specified%s", 196462306a36Sopenharmony_ci es1, es2); 196562306a36Sopenharmony_ci if (vol->logfile_ino) { 196662306a36Sopenharmony_ci BUG_ON(!rp); 196762306a36Sopenharmony_ci ntfs_free(rp); 196862306a36Sopenharmony_ci } 196962306a36Sopenharmony_ci goto iput_logfile_err_out; 197062306a36Sopenharmony_ci } 197162306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 197262306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 197362306a36Sopenharmony_ci } else 197462306a36Sopenharmony_ci ntfs_warning(sb, "%s. Will not be able to remount " 197562306a36Sopenharmony_ci "read-write%s", es1, es2); 197662306a36Sopenharmony_ci /* This will prevent a read-write remount. */ 197762306a36Sopenharmony_ci NVolSetErrors(vol); 197862306a36Sopenharmony_ci } 197962306a36Sopenharmony_ci ntfs_free(rp); 198062306a36Sopenharmony_ci#endif /* NTFS_RW */ 198162306a36Sopenharmony_ci /* Get the root directory inode so we can do path lookups. */ 198262306a36Sopenharmony_ci vol->root_ino = ntfs_iget(sb, FILE_root); 198362306a36Sopenharmony_ci if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) { 198462306a36Sopenharmony_ci if (!IS_ERR(vol->root_ino)) 198562306a36Sopenharmony_ci iput(vol->root_ino); 198662306a36Sopenharmony_ci ntfs_error(sb, "Failed to load root directory."); 198762306a36Sopenharmony_ci goto iput_logfile_err_out; 198862306a36Sopenharmony_ci } 198962306a36Sopenharmony_ci#ifdef NTFS_RW 199062306a36Sopenharmony_ci /* 199162306a36Sopenharmony_ci * Check if Windows is suspended to disk on the target volume. If it 199262306a36Sopenharmony_ci * is hibernated, we must not write *anything* to the disk so set 199362306a36Sopenharmony_ci * NVolErrors() without setting the dirty volume flag and mount 199462306a36Sopenharmony_ci * read-only. This will prevent read-write remounting and it will also 199562306a36Sopenharmony_ci * prevent all writes. 199662306a36Sopenharmony_ci */ 199762306a36Sopenharmony_ci err = check_windows_hibernation_status(vol); 199862306a36Sopenharmony_ci if (unlikely(err)) { 199962306a36Sopenharmony_ci static const char *es1a = "Failed to determine if Windows is " 200062306a36Sopenharmony_ci "hibernated"; 200162306a36Sopenharmony_ci static const char *es1b = "Windows is hibernated"; 200262306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 200362306a36Sopenharmony_ci const char *es1; 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci es1 = err < 0 ? es1a : es1b; 200662306a36Sopenharmony_ci /* If a read-write mount, convert it to a read-only mount. */ 200762306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 200862306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 200962306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 201062306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=" 201162306a36Sopenharmony_ci "continue nor on_errors=" 201262306a36Sopenharmony_ci "remount-ro was specified%s", 201362306a36Sopenharmony_ci es1, es2); 201462306a36Sopenharmony_ci goto iput_root_err_out; 201562306a36Sopenharmony_ci } 201662306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 201762306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 201862306a36Sopenharmony_ci } else 201962306a36Sopenharmony_ci ntfs_warning(sb, "%s. Will not be able to remount " 202062306a36Sopenharmony_ci "read-write%s", es1, es2); 202162306a36Sopenharmony_ci /* This will prevent a read-write remount. */ 202262306a36Sopenharmony_ci NVolSetErrors(vol); 202362306a36Sopenharmony_ci } 202462306a36Sopenharmony_ci /* If (still) a read-write mount, mark the volume dirty. */ 202562306a36Sopenharmony_ci if (!sb_rdonly(sb) && ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) { 202662306a36Sopenharmony_ci static const char *es1 = "Failed to set dirty bit in volume " 202762306a36Sopenharmony_ci "information flags"; 202862306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci /* Convert to a read-only mount. */ 203162306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 203262306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 203362306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=continue nor " 203462306a36Sopenharmony_ci "on_errors=remount-ro was specified%s", 203562306a36Sopenharmony_ci es1, es2); 203662306a36Sopenharmony_ci goto iput_root_err_out; 203762306a36Sopenharmony_ci } 203862306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 203962306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 204062306a36Sopenharmony_ci /* 204162306a36Sopenharmony_ci * Do not set NVolErrors() because ntfs_remount() might manage 204262306a36Sopenharmony_ci * to set the dirty flag in which case all would be well. 204362306a36Sopenharmony_ci */ 204462306a36Sopenharmony_ci } 204562306a36Sopenharmony_ci#if 0 204662306a36Sopenharmony_ci // TODO: Enable this code once we start modifying anything that is 204762306a36Sopenharmony_ci // different between NTFS 1.2 and 3.x... 204862306a36Sopenharmony_ci /* 204962306a36Sopenharmony_ci * If (still) a read-write mount, set the NT4 compatibility flag on 205062306a36Sopenharmony_ci * newer NTFS version volumes. 205162306a36Sopenharmony_ci */ 205262306a36Sopenharmony_ci if (!(sb->s_flags & SB_RDONLY) && (vol->major_ver > 1) && 205362306a36Sopenharmony_ci ntfs_set_volume_flags(vol, VOLUME_MOUNTED_ON_NT4)) { 205462306a36Sopenharmony_ci static const char *es1 = "Failed to set NT4 compatibility flag"; 205562306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci /* Convert to a read-only mount. */ 205862306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 205962306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 206062306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=continue nor " 206162306a36Sopenharmony_ci "on_errors=remount-ro was specified%s", 206262306a36Sopenharmony_ci es1, es2); 206362306a36Sopenharmony_ci goto iput_root_err_out; 206462306a36Sopenharmony_ci } 206562306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 206662306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 206762306a36Sopenharmony_ci NVolSetErrors(vol); 206862306a36Sopenharmony_ci } 206962306a36Sopenharmony_ci#endif 207062306a36Sopenharmony_ci /* If (still) a read-write mount, empty the logfile. */ 207162306a36Sopenharmony_ci if (!sb_rdonly(sb) && !ntfs_empty_logfile(vol->logfile_ino)) { 207262306a36Sopenharmony_ci static const char *es1 = "Failed to empty $LogFile"; 207362306a36Sopenharmony_ci static const char *es2 = ". Mount in Windows."; 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci /* Convert to a read-only mount. */ 207662306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 207762306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 207862306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=continue nor " 207962306a36Sopenharmony_ci "on_errors=remount-ro was specified%s", 208062306a36Sopenharmony_ci es1, es2); 208162306a36Sopenharmony_ci goto iput_root_err_out; 208262306a36Sopenharmony_ci } 208362306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 208462306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 208562306a36Sopenharmony_ci NVolSetErrors(vol); 208662306a36Sopenharmony_ci } 208762306a36Sopenharmony_ci#endif /* NTFS_RW */ 208862306a36Sopenharmony_ci /* If on NTFS versions before 3.0, we are done. */ 208962306a36Sopenharmony_ci if (unlikely(vol->major_ver < 3)) 209062306a36Sopenharmony_ci return true; 209162306a36Sopenharmony_ci /* NTFS 3.0+ specific initialization. */ 209262306a36Sopenharmony_ci /* Get the security descriptors inode. */ 209362306a36Sopenharmony_ci vol->secure_ino = ntfs_iget(sb, FILE_Secure); 209462306a36Sopenharmony_ci if (IS_ERR(vol->secure_ino) || is_bad_inode(vol->secure_ino)) { 209562306a36Sopenharmony_ci if (!IS_ERR(vol->secure_ino)) 209662306a36Sopenharmony_ci iput(vol->secure_ino); 209762306a36Sopenharmony_ci ntfs_error(sb, "Failed to load $Secure."); 209862306a36Sopenharmony_ci goto iput_root_err_out; 209962306a36Sopenharmony_ci } 210062306a36Sopenharmony_ci // TODO: Initialize security. 210162306a36Sopenharmony_ci /* Get the extended system files' directory inode. */ 210262306a36Sopenharmony_ci vol->extend_ino = ntfs_iget(sb, FILE_Extend); 210362306a36Sopenharmony_ci if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino) || 210462306a36Sopenharmony_ci !S_ISDIR(vol->extend_ino->i_mode)) { 210562306a36Sopenharmony_ci if (!IS_ERR(vol->extend_ino)) 210662306a36Sopenharmony_ci iput(vol->extend_ino); 210762306a36Sopenharmony_ci ntfs_error(sb, "Failed to load $Extend."); 210862306a36Sopenharmony_ci goto iput_sec_err_out; 210962306a36Sopenharmony_ci } 211062306a36Sopenharmony_ci#ifdef NTFS_RW 211162306a36Sopenharmony_ci /* Find the quota file, load it if present, and set it up. */ 211262306a36Sopenharmony_ci if (!load_and_init_quota(vol)) { 211362306a36Sopenharmony_ci static const char *es1 = "Failed to load $Quota"; 211462306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci /* If a read-write mount, convert it to a read-only mount. */ 211762306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 211862306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 211962306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 212062306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=" 212162306a36Sopenharmony_ci "continue nor on_errors=" 212262306a36Sopenharmony_ci "remount-ro was specified%s", 212362306a36Sopenharmony_ci es1, es2); 212462306a36Sopenharmony_ci goto iput_quota_err_out; 212562306a36Sopenharmony_ci } 212662306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 212762306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 212862306a36Sopenharmony_ci } else 212962306a36Sopenharmony_ci ntfs_warning(sb, "%s. Will not be able to remount " 213062306a36Sopenharmony_ci "read-write%s", es1, es2); 213162306a36Sopenharmony_ci /* This will prevent a read-write remount. */ 213262306a36Sopenharmony_ci NVolSetErrors(vol); 213362306a36Sopenharmony_ci } 213462306a36Sopenharmony_ci /* If (still) a read-write mount, mark the quotas out of date. */ 213562306a36Sopenharmony_ci if (!sb_rdonly(sb) && !ntfs_mark_quotas_out_of_date(vol)) { 213662306a36Sopenharmony_ci static const char *es1 = "Failed to mark quotas out of date"; 213762306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci /* Convert to a read-only mount. */ 214062306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 214162306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 214262306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=continue nor " 214362306a36Sopenharmony_ci "on_errors=remount-ro was specified%s", 214462306a36Sopenharmony_ci es1, es2); 214562306a36Sopenharmony_ci goto iput_quota_err_out; 214662306a36Sopenharmony_ci } 214762306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 214862306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 214962306a36Sopenharmony_ci NVolSetErrors(vol); 215062306a36Sopenharmony_ci } 215162306a36Sopenharmony_ci /* 215262306a36Sopenharmony_ci * Find the transaction log file ($UsnJrnl), load it if present, check 215362306a36Sopenharmony_ci * it, and set it up. 215462306a36Sopenharmony_ci */ 215562306a36Sopenharmony_ci if (!load_and_init_usnjrnl(vol)) { 215662306a36Sopenharmony_ci static const char *es1 = "Failed to load $UsnJrnl"; 215762306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci /* If a read-write mount, convert it to a read-only mount. */ 216062306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 216162306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 216262306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 216362306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=" 216462306a36Sopenharmony_ci "continue nor on_errors=" 216562306a36Sopenharmony_ci "remount-ro was specified%s", 216662306a36Sopenharmony_ci es1, es2); 216762306a36Sopenharmony_ci goto iput_usnjrnl_err_out; 216862306a36Sopenharmony_ci } 216962306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 217062306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 217162306a36Sopenharmony_ci } else 217262306a36Sopenharmony_ci ntfs_warning(sb, "%s. Will not be able to remount " 217362306a36Sopenharmony_ci "read-write%s", es1, es2); 217462306a36Sopenharmony_ci /* This will prevent a read-write remount. */ 217562306a36Sopenharmony_ci NVolSetErrors(vol); 217662306a36Sopenharmony_ci } 217762306a36Sopenharmony_ci /* If (still) a read-write mount, stamp the transaction log. */ 217862306a36Sopenharmony_ci if (!sb_rdonly(sb) && !ntfs_stamp_usnjrnl(vol)) { 217962306a36Sopenharmony_ci static const char *es1 = "Failed to stamp transaction log " 218062306a36Sopenharmony_ci "($UsnJrnl)"; 218162306a36Sopenharmony_ci static const char *es2 = ". Run chkdsk."; 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci /* Convert to a read-only mount. */ 218462306a36Sopenharmony_ci if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | 218562306a36Sopenharmony_ci ON_ERRORS_CONTINUE))) { 218662306a36Sopenharmony_ci ntfs_error(sb, "%s and neither on_errors=continue nor " 218762306a36Sopenharmony_ci "on_errors=remount-ro was specified%s", 218862306a36Sopenharmony_ci es1, es2); 218962306a36Sopenharmony_ci goto iput_usnjrnl_err_out; 219062306a36Sopenharmony_ci } 219162306a36Sopenharmony_ci ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 219262306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 219362306a36Sopenharmony_ci NVolSetErrors(vol); 219462306a36Sopenharmony_ci } 219562306a36Sopenharmony_ci#endif /* NTFS_RW */ 219662306a36Sopenharmony_ci return true; 219762306a36Sopenharmony_ci#ifdef NTFS_RW 219862306a36Sopenharmony_ciiput_usnjrnl_err_out: 219962306a36Sopenharmony_ci iput(vol->usnjrnl_j_ino); 220062306a36Sopenharmony_ci iput(vol->usnjrnl_max_ino); 220162306a36Sopenharmony_ci iput(vol->usnjrnl_ino); 220262306a36Sopenharmony_ciiput_quota_err_out: 220362306a36Sopenharmony_ci iput(vol->quota_q_ino); 220462306a36Sopenharmony_ci iput(vol->quota_ino); 220562306a36Sopenharmony_ci iput(vol->extend_ino); 220662306a36Sopenharmony_ci#endif /* NTFS_RW */ 220762306a36Sopenharmony_ciiput_sec_err_out: 220862306a36Sopenharmony_ci iput(vol->secure_ino); 220962306a36Sopenharmony_ciiput_root_err_out: 221062306a36Sopenharmony_ci iput(vol->root_ino); 221162306a36Sopenharmony_ciiput_logfile_err_out: 221262306a36Sopenharmony_ci#ifdef NTFS_RW 221362306a36Sopenharmony_ci iput(vol->logfile_ino); 221462306a36Sopenharmony_ciiput_vol_err_out: 221562306a36Sopenharmony_ci#endif /* NTFS_RW */ 221662306a36Sopenharmony_ci iput(vol->vol_ino); 221762306a36Sopenharmony_ciiput_lcnbmp_err_out: 221862306a36Sopenharmony_ci iput(vol->lcnbmp_ino); 221962306a36Sopenharmony_ciiput_attrdef_err_out: 222062306a36Sopenharmony_ci vol->attrdef_size = 0; 222162306a36Sopenharmony_ci if (vol->attrdef) { 222262306a36Sopenharmony_ci ntfs_free(vol->attrdef); 222362306a36Sopenharmony_ci vol->attrdef = NULL; 222462306a36Sopenharmony_ci } 222562306a36Sopenharmony_ci#ifdef NTFS_RW 222662306a36Sopenharmony_ciiput_upcase_err_out: 222762306a36Sopenharmony_ci#endif /* NTFS_RW */ 222862306a36Sopenharmony_ci vol->upcase_len = 0; 222962306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 223062306a36Sopenharmony_ci if (vol->upcase == default_upcase) { 223162306a36Sopenharmony_ci ntfs_nr_upcase_users--; 223262306a36Sopenharmony_ci vol->upcase = NULL; 223362306a36Sopenharmony_ci } 223462306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 223562306a36Sopenharmony_ci if (vol->upcase) { 223662306a36Sopenharmony_ci ntfs_free(vol->upcase); 223762306a36Sopenharmony_ci vol->upcase = NULL; 223862306a36Sopenharmony_ci } 223962306a36Sopenharmony_ciiput_mftbmp_err_out: 224062306a36Sopenharmony_ci iput(vol->mftbmp_ino); 224162306a36Sopenharmony_ciiput_mirr_err_out: 224262306a36Sopenharmony_ci#ifdef NTFS_RW 224362306a36Sopenharmony_ci iput(vol->mftmirr_ino); 224462306a36Sopenharmony_ci#endif /* NTFS_RW */ 224562306a36Sopenharmony_ci return false; 224662306a36Sopenharmony_ci} 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci/** 224962306a36Sopenharmony_ci * ntfs_put_super - called by the vfs to unmount a volume 225062306a36Sopenharmony_ci * @sb: vfs superblock of volume to unmount 225162306a36Sopenharmony_ci * 225262306a36Sopenharmony_ci * ntfs_put_super() is called by the VFS (from fs/super.c::do_umount()) when 225362306a36Sopenharmony_ci * the volume is being unmounted (umount system call has been invoked) and it 225462306a36Sopenharmony_ci * releases all inodes and memory belonging to the NTFS specific part of the 225562306a36Sopenharmony_ci * super block. 225662306a36Sopenharmony_ci */ 225762306a36Sopenharmony_cistatic void ntfs_put_super(struct super_block *sb) 225862306a36Sopenharmony_ci{ 225962306a36Sopenharmony_ci ntfs_volume *vol = NTFS_SB(sb); 226062306a36Sopenharmony_ci 226162306a36Sopenharmony_ci ntfs_debug("Entering."); 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci#ifdef NTFS_RW 226462306a36Sopenharmony_ci /* 226562306a36Sopenharmony_ci * Commit all inodes while they are still open in case some of them 226662306a36Sopenharmony_ci * cause others to be dirtied. 226762306a36Sopenharmony_ci */ 226862306a36Sopenharmony_ci ntfs_commit_inode(vol->vol_ino); 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci /* NTFS 3.0+ specific. */ 227162306a36Sopenharmony_ci if (vol->major_ver >= 3) { 227262306a36Sopenharmony_ci if (vol->usnjrnl_j_ino) 227362306a36Sopenharmony_ci ntfs_commit_inode(vol->usnjrnl_j_ino); 227462306a36Sopenharmony_ci if (vol->usnjrnl_max_ino) 227562306a36Sopenharmony_ci ntfs_commit_inode(vol->usnjrnl_max_ino); 227662306a36Sopenharmony_ci if (vol->usnjrnl_ino) 227762306a36Sopenharmony_ci ntfs_commit_inode(vol->usnjrnl_ino); 227862306a36Sopenharmony_ci if (vol->quota_q_ino) 227962306a36Sopenharmony_ci ntfs_commit_inode(vol->quota_q_ino); 228062306a36Sopenharmony_ci if (vol->quota_ino) 228162306a36Sopenharmony_ci ntfs_commit_inode(vol->quota_ino); 228262306a36Sopenharmony_ci if (vol->extend_ino) 228362306a36Sopenharmony_ci ntfs_commit_inode(vol->extend_ino); 228462306a36Sopenharmony_ci if (vol->secure_ino) 228562306a36Sopenharmony_ci ntfs_commit_inode(vol->secure_ino); 228662306a36Sopenharmony_ci } 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci ntfs_commit_inode(vol->root_ino); 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci down_write(&vol->lcnbmp_lock); 229162306a36Sopenharmony_ci ntfs_commit_inode(vol->lcnbmp_ino); 229262306a36Sopenharmony_ci up_write(&vol->lcnbmp_lock); 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_ci down_write(&vol->mftbmp_lock); 229562306a36Sopenharmony_ci ntfs_commit_inode(vol->mftbmp_ino); 229662306a36Sopenharmony_ci up_write(&vol->mftbmp_lock); 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci if (vol->logfile_ino) 229962306a36Sopenharmony_ci ntfs_commit_inode(vol->logfile_ino); 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci if (vol->mftmirr_ino) 230262306a36Sopenharmony_ci ntfs_commit_inode(vol->mftmirr_ino); 230362306a36Sopenharmony_ci ntfs_commit_inode(vol->mft_ino); 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_ci /* 230662306a36Sopenharmony_ci * If a read-write mount and no volume errors have occurred, mark the 230762306a36Sopenharmony_ci * volume clean. Also, re-commit all affected inodes. 230862306a36Sopenharmony_ci */ 230962306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 231062306a36Sopenharmony_ci if (!NVolErrors(vol)) { 231162306a36Sopenharmony_ci if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) 231262306a36Sopenharmony_ci ntfs_warning(sb, "Failed to clear dirty bit " 231362306a36Sopenharmony_ci "in volume information " 231462306a36Sopenharmony_ci "flags. Run chkdsk."); 231562306a36Sopenharmony_ci ntfs_commit_inode(vol->vol_ino); 231662306a36Sopenharmony_ci ntfs_commit_inode(vol->root_ino); 231762306a36Sopenharmony_ci if (vol->mftmirr_ino) 231862306a36Sopenharmony_ci ntfs_commit_inode(vol->mftmirr_ino); 231962306a36Sopenharmony_ci ntfs_commit_inode(vol->mft_ino); 232062306a36Sopenharmony_ci } else { 232162306a36Sopenharmony_ci ntfs_warning(sb, "Volume has errors. Leaving volume " 232262306a36Sopenharmony_ci "marked dirty. Run chkdsk."); 232362306a36Sopenharmony_ci } 232462306a36Sopenharmony_ci } 232562306a36Sopenharmony_ci#endif /* NTFS_RW */ 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci iput(vol->vol_ino); 232862306a36Sopenharmony_ci vol->vol_ino = NULL; 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci /* NTFS 3.0+ specific clean up. */ 233162306a36Sopenharmony_ci if (vol->major_ver >= 3) { 233262306a36Sopenharmony_ci#ifdef NTFS_RW 233362306a36Sopenharmony_ci if (vol->usnjrnl_j_ino) { 233462306a36Sopenharmony_ci iput(vol->usnjrnl_j_ino); 233562306a36Sopenharmony_ci vol->usnjrnl_j_ino = NULL; 233662306a36Sopenharmony_ci } 233762306a36Sopenharmony_ci if (vol->usnjrnl_max_ino) { 233862306a36Sopenharmony_ci iput(vol->usnjrnl_max_ino); 233962306a36Sopenharmony_ci vol->usnjrnl_max_ino = NULL; 234062306a36Sopenharmony_ci } 234162306a36Sopenharmony_ci if (vol->usnjrnl_ino) { 234262306a36Sopenharmony_ci iput(vol->usnjrnl_ino); 234362306a36Sopenharmony_ci vol->usnjrnl_ino = NULL; 234462306a36Sopenharmony_ci } 234562306a36Sopenharmony_ci if (vol->quota_q_ino) { 234662306a36Sopenharmony_ci iput(vol->quota_q_ino); 234762306a36Sopenharmony_ci vol->quota_q_ino = NULL; 234862306a36Sopenharmony_ci } 234962306a36Sopenharmony_ci if (vol->quota_ino) { 235062306a36Sopenharmony_ci iput(vol->quota_ino); 235162306a36Sopenharmony_ci vol->quota_ino = NULL; 235262306a36Sopenharmony_ci } 235362306a36Sopenharmony_ci#endif /* NTFS_RW */ 235462306a36Sopenharmony_ci if (vol->extend_ino) { 235562306a36Sopenharmony_ci iput(vol->extend_ino); 235662306a36Sopenharmony_ci vol->extend_ino = NULL; 235762306a36Sopenharmony_ci } 235862306a36Sopenharmony_ci if (vol->secure_ino) { 235962306a36Sopenharmony_ci iput(vol->secure_ino); 236062306a36Sopenharmony_ci vol->secure_ino = NULL; 236162306a36Sopenharmony_ci } 236262306a36Sopenharmony_ci } 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci iput(vol->root_ino); 236562306a36Sopenharmony_ci vol->root_ino = NULL; 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci down_write(&vol->lcnbmp_lock); 236862306a36Sopenharmony_ci iput(vol->lcnbmp_ino); 236962306a36Sopenharmony_ci vol->lcnbmp_ino = NULL; 237062306a36Sopenharmony_ci up_write(&vol->lcnbmp_lock); 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci down_write(&vol->mftbmp_lock); 237362306a36Sopenharmony_ci iput(vol->mftbmp_ino); 237462306a36Sopenharmony_ci vol->mftbmp_ino = NULL; 237562306a36Sopenharmony_ci up_write(&vol->mftbmp_lock); 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci#ifdef NTFS_RW 237862306a36Sopenharmony_ci if (vol->logfile_ino) { 237962306a36Sopenharmony_ci iput(vol->logfile_ino); 238062306a36Sopenharmony_ci vol->logfile_ino = NULL; 238162306a36Sopenharmony_ci } 238262306a36Sopenharmony_ci if (vol->mftmirr_ino) { 238362306a36Sopenharmony_ci /* Re-commit the mft mirror and mft just in case. */ 238462306a36Sopenharmony_ci ntfs_commit_inode(vol->mftmirr_ino); 238562306a36Sopenharmony_ci ntfs_commit_inode(vol->mft_ino); 238662306a36Sopenharmony_ci iput(vol->mftmirr_ino); 238762306a36Sopenharmony_ci vol->mftmirr_ino = NULL; 238862306a36Sopenharmony_ci } 238962306a36Sopenharmony_ci /* 239062306a36Sopenharmony_ci * We should have no dirty inodes left, due to 239162306a36Sopenharmony_ci * mft.c::ntfs_mft_writepage() cleaning all the dirty pages as 239262306a36Sopenharmony_ci * the underlying mft records are written out and cleaned. 239362306a36Sopenharmony_ci */ 239462306a36Sopenharmony_ci ntfs_commit_inode(vol->mft_ino); 239562306a36Sopenharmony_ci write_inode_now(vol->mft_ino, 1); 239662306a36Sopenharmony_ci#endif /* NTFS_RW */ 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci iput(vol->mft_ino); 239962306a36Sopenharmony_ci vol->mft_ino = NULL; 240062306a36Sopenharmony_ci 240162306a36Sopenharmony_ci /* Throw away the table of attribute definitions. */ 240262306a36Sopenharmony_ci vol->attrdef_size = 0; 240362306a36Sopenharmony_ci if (vol->attrdef) { 240462306a36Sopenharmony_ci ntfs_free(vol->attrdef); 240562306a36Sopenharmony_ci vol->attrdef = NULL; 240662306a36Sopenharmony_ci } 240762306a36Sopenharmony_ci vol->upcase_len = 0; 240862306a36Sopenharmony_ci /* 240962306a36Sopenharmony_ci * Destroy the global default upcase table if necessary. Also decrease 241062306a36Sopenharmony_ci * the number of upcase users if we are a user. 241162306a36Sopenharmony_ci */ 241262306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 241362306a36Sopenharmony_ci if (vol->upcase == default_upcase) { 241462306a36Sopenharmony_ci ntfs_nr_upcase_users--; 241562306a36Sopenharmony_ci vol->upcase = NULL; 241662306a36Sopenharmony_ci } 241762306a36Sopenharmony_ci if (!ntfs_nr_upcase_users && default_upcase) { 241862306a36Sopenharmony_ci ntfs_free(default_upcase); 241962306a36Sopenharmony_ci default_upcase = NULL; 242062306a36Sopenharmony_ci } 242162306a36Sopenharmony_ci if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) 242262306a36Sopenharmony_ci free_compression_buffers(); 242362306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 242462306a36Sopenharmony_ci if (vol->upcase) { 242562306a36Sopenharmony_ci ntfs_free(vol->upcase); 242662306a36Sopenharmony_ci vol->upcase = NULL; 242762306a36Sopenharmony_ci } 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_ci unload_nls(vol->nls_map); 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci sb->s_fs_info = NULL; 243262306a36Sopenharmony_ci kfree(vol); 243362306a36Sopenharmony_ci} 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci/** 243662306a36Sopenharmony_ci * get_nr_free_clusters - return the number of free clusters on a volume 243762306a36Sopenharmony_ci * @vol: ntfs volume for which to obtain free cluster count 243862306a36Sopenharmony_ci * 243962306a36Sopenharmony_ci * Calculate the number of free clusters on the mounted NTFS volume @vol. We 244062306a36Sopenharmony_ci * actually calculate the number of clusters in use instead because this 244162306a36Sopenharmony_ci * allows us to not care about partial pages as these will be just zero filled 244262306a36Sopenharmony_ci * and hence not be counted as allocated clusters. 244362306a36Sopenharmony_ci * 244462306a36Sopenharmony_ci * The only particularity is that clusters beyond the end of the logical ntfs 244562306a36Sopenharmony_ci * volume will be marked as allocated to prevent errors which means we have to 244662306a36Sopenharmony_ci * discount those at the end. This is important as the cluster bitmap always 244762306a36Sopenharmony_ci * has a size in multiples of 8 bytes, i.e. up to 63 clusters could be outside 244862306a36Sopenharmony_ci * the logical volume and marked in use when they are not as they do not exist. 244962306a36Sopenharmony_ci * 245062306a36Sopenharmony_ci * If any pages cannot be read we assume all clusters in the erroring pages are 245162306a36Sopenharmony_ci * in use. This means we return an underestimate on errors which is better than 245262306a36Sopenharmony_ci * an overestimate. 245362306a36Sopenharmony_ci */ 245462306a36Sopenharmony_cistatic s64 get_nr_free_clusters(ntfs_volume *vol) 245562306a36Sopenharmony_ci{ 245662306a36Sopenharmony_ci s64 nr_free = vol->nr_clusters; 245762306a36Sopenharmony_ci struct address_space *mapping = vol->lcnbmp_ino->i_mapping; 245862306a36Sopenharmony_ci struct page *page; 245962306a36Sopenharmony_ci pgoff_t index, max_index; 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci ntfs_debug("Entering."); 246262306a36Sopenharmony_ci /* Serialize accesses to the cluster bitmap. */ 246362306a36Sopenharmony_ci down_read(&vol->lcnbmp_lock); 246462306a36Sopenharmony_ci /* 246562306a36Sopenharmony_ci * Convert the number of bits into bytes rounded up, then convert into 246662306a36Sopenharmony_ci * multiples of PAGE_SIZE, rounding up so that if we have one 246762306a36Sopenharmony_ci * full and one partial page max_index = 2. 246862306a36Sopenharmony_ci */ 246962306a36Sopenharmony_ci max_index = (((vol->nr_clusters + 7) >> 3) + PAGE_SIZE - 1) >> 247062306a36Sopenharmony_ci PAGE_SHIFT; 247162306a36Sopenharmony_ci /* Use multiples of 4 bytes, thus max_size is PAGE_SIZE / 4. */ 247262306a36Sopenharmony_ci ntfs_debug("Reading $Bitmap, max_index = 0x%lx, max_size = 0x%lx.", 247362306a36Sopenharmony_ci max_index, PAGE_SIZE / 4); 247462306a36Sopenharmony_ci for (index = 0; index < max_index; index++) { 247562306a36Sopenharmony_ci unsigned long *kaddr; 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci /* 247862306a36Sopenharmony_ci * Read the page from page cache, getting it from backing store 247962306a36Sopenharmony_ci * if necessary, and increment the use count. 248062306a36Sopenharmony_ci */ 248162306a36Sopenharmony_ci page = read_mapping_page(mapping, index, NULL); 248262306a36Sopenharmony_ci /* Ignore pages which errored synchronously. */ 248362306a36Sopenharmony_ci if (IS_ERR(page)) { 248462306a36Sopenharmony_ci ntfs_debug("read_mapping_page() error. Skipping " 248562306a36Sopenharmony_ci "page (index 0x%lx).", index); 248662306a36Sopenharmony_ci nr_free -= PAGE_SIZE * 8; 248762306a36Sopenharmony_ci continue; 248862306a36Sopenharmony_ci } 248962306a36Sopenharmony_ci kaddr = kmap_atomic(page); 249062306a36Sopenharmony_ci /* 249162306a36Sopenharmony_ci * Subtract the number of set bits. If this 249262306a36Sopenharmony_ci * is the last page and it is partial we don't really care as 249362306a36Sopenharmony_ci * it just means we do a little extra work but it won't affect 249462306a36Sopenharmony_ci * the result as all out of range bytes are set to zero by 249562306a36Sopenharmony_ci * ntfs_readpage(). 249662306a36Sopenharmony_ci */ 249762306a36Sopenharmony_ci nr_free -= bitmap_weight(kaddr, 249862306a36Sopenharmony_ci PAGE_SIZE * BITS_PER_BYTE); 249962306a36Sopenharmony_ci kunmap_atomic(kaddr); 250062306a36Sopenharmony_ci put_page(page); 250162306a36Sopenharmony_ci } 250262306a36Sopenharmony_ci ntfs_debug("Finished reading $Bitmap, last index = 0x%lx.", index - 1); 250362306a36Sopenharmony_ci /* 250462306a36Sopenharmony_ci * Fixup for eventual bits outside logical ntfs volume (see function 250562306a36Sopenharmony_ci * description above). 250662306a36Sopenharmony_ci */ 250762306a36Sopenharmony_ci if (vol->nr_clusters & 63) 250862306a36Sopenharmony_ci nr_free += 64 - (vol->nr_clusters & 63); 250962306a36Sopenharmony_ci up_read(&vol->lcnbmp_lock); 251062306a36Sopenharmony_ci /* If errors occurred we may well have gone below zero, fix this. */ 251162306a36Sopenharmony_ci if (nr_free < 0) 251262306a36Sopenharmony_ci nr_free = 0; 251362306a36Sopenharmony_ci ntfs_debug("Exiting."); 251462306a36Sopenharmony_ci return nr_free; 251562306a36Sopenharmony_ci} 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci/** 251862306a36Sopenharmony_ci * __get_nr_free_mft_records - return the number of free inodes on a volume 251962306a36Sopenharmony_ci * @vol: ntfs volume for which to obtain free inode count 252062306a36Sopenharmony_ci * @nr_free: number of mft records in filesystem 252162306a36Sopenharmony_ci * @max_index: maximum number of pages containing set bits 252262306a36Sopenharmony_ci * 252362306a36Sopenharmony_ci * Calculate the number of free mft records (inodes) on the mounted NTFS 252462306a36Sopenharmony_ci * volume @vol. We actually calculate the number of mft records in use instead 252562306a36Sopenharmony_ci * because this allows us to not care about partial pages as these will be just 252662306a36Sopenharmony_ci * zero filled and hence not be counted as allocated mft record. 252762306a36Sopenharmony_ci * 252862306a36Sopenharmony_ci * If any pages cannot be read we assume all mft records in the erroring pages 252962306a36Sopenharmony_ci * are in use. This means we return an underestimate on errors which is better 253062306a36Sopenharmony_ci * than an overestimate. 253162306a36Sopenharmony_ci * 253262306a36Sopenharmony_ci * NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing. 253362306a36Sopenharmony_ci */ 253462306a36Sopenharmony_cistatic unsigned long __get_nr_free_mft_records(ntfs_volume *vol, 253562306a36Sopenharmony_ci s64 nr_free, const pgoff_t max_index) 253662306a36Sopenharmony_ci{ 253762306a36Sopenharmony_ci struct address_space *mapping = vol->mftbmp_ino->i_mapping; 253862306a36Sopenharmony_ci struct page *page; 253962306a36Sopenharmony_ci pgoff_t index; 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci ntfs_debug("Entering."); 254262306a36Sopenharmony_ci /* Use multiples of 4 bytes, thus max_size is PAGE_SIZE / 4. */ 254362306a36Sopenharmony_ci ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = " 254462306a36Sopenharmony_ci "0x%lx.", max_index, PAGE_SIZE / 4); 254562306a36Sopenharmony_ci for (index = 0; index < max_index; index++) { 254662306a36Sopenharmony_ci unsigned long *kaddr; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci /* 254962306a36Sopenharmony_ci * Read the page from page cache, getting it from backing store 255062306a36Sopenharmony_ci * if necessary, and increment the use count. 255162306a36Sopenharmony_ci */ 255262306a36Sopenharmony_ci page = read_mapping_page(mapping, index, NULL); 255362306a36Sopenharmony_ci /* Ignore pages which errored synchronously. */ 255462306a36Sopenharmony_ci if (IS_ERR(page)) { 255562306a36Sopenharmony_ci ntfs_debug("read_mapping_page() error. Skipping " 255662306a36Sopenharmony_ci "page (index 0x%lx).", index); 255762306a36Sopenharmony_ci nr_free -= PAGE_SIZE * 8; 255862306a36Sopenharmony_ci continue; 255962306a36Sopenharmony_ci } 256062306a36Sopenharmony_ci kaddr = kmap_atomic(page); 256162306a36Sopenharmony_ci /* 256262306a36Sopenharmony_ci * Subtract the number of set bits. If this 256362306a36Sopenharmony_ci * is the last page and it is partial we don't really care as 256462306a36Sopenharmony_ci * it just means we do a little extra work but it won't affect 256562306a36Sopenharmony_ci * the result as all out of range bytes are set to zero by 256662306a36Sopenharmony_ci * ntfs_readpage(). 256762306a36Sopenharmony_ci */ 256862306a36Sopenharmony_ci nr_free -= bitmap_weight(kaddr, 256962306a36Sopenharmony_ci PAGE_SIZE * BITS_PER_BYTE); 257062306a36Sopenharmony_ci kunmap_atomic(kaddr); 257162306a36Sopenharmony_ci put_page(page); 257262306a36Sopenharmony_ci } 257362306a36Sopenharmony_ci ntfs_debug("Finished reading $MFT/$BITMAP, last index = 0x%lx.", 257462306a36Sopenharmony_ci index - 1); 257562306a36Sopenharmony_ci /* If errors occurred we may well have gone below zero, fix this. */ 257662306a36Sopenharmony_ci if (nr_free < 0) 257762306a36Sopenharmony_ci nr_free = 0; 257862306a36Sopenharmony_ci ntfs_debug("Exiting."); 257962306a36Sopenharmony_ci return nr_free; 258062306a36Sopenharmony_ci} 258162306a36Sopenharmony_ci 258262306a36Sopenharmony_ci/** 258362306a36Sopenharmony_ci * ntfs_statfs - return information about mounted NTFS volume 258462306a36Sopenharmony_ci * @dentry: dentry from mounted volume 258562306a36Sopenharmony_ci * @sfs: statfs structure in which to return the information 258662306a36Sopenharmony_ci * 258762306a36Sopenharmony_ci * Return information about the mounted NTFS volume @dentry in the statfs structure 258862306a36Sopenharmony_ci * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is 258962306a36Sopenharmony_ci * called). We interpret the values to be correct of the moment in time at 259062306a36Sopenharmony_ci * which we are called. Most values are variable otherwise and this isn't just 259162306a36Sopenharmony_ci * the free values but the totals as well. For example we can increase the 259262306a36Sopenharmony_ci * total number of file nodes if we run out and we can keep doing this until 259362306a36Sopenharmony_ci * there is no more space on the volume left at all. 259462306a36Sopenharmony_ci * 259562306a36Sopenharmony_ci * Called from vfs_statfs which is used to handle the statfs, fstatfs, and 259662306a36Sopenharmony_ci * ustat system calls. 259762306a36Sopenharmony_ci * 259862306a36Sopenharmony_ci * Return 0 on success or -errno on error. 259962306a36Sopenharmony_ci */ 260062306a36Sopenharmony_cistatic int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs) 260162306a36Sopenharmony_ci{ 260262306a36Sopenharmony_ci struct super_block *sb = dentry->d_sb; 260362306a36Sopenharmony_ci s64 size; 260462306a36Sopenharmony_ci ntfs_volume *vol = NTFS_SB(sb); 260562306a36Sopenharmony_ci ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); 260662306a36Sopenharmony_ci pgoff_t max_index; 260762306a36Sopenharmony_ci unsigned long flags; 260862306a36Sopenharmony_ci 260962306a36Sopenharmony_ci ntfs_debug("Entering."); 261062306a36Sopenharmony_ci /* Type of filesystem. */ 261162306a36Sopenharmony_ci sfs->f_type = NTFS_SB_MAGIC; 261262306a36Sopenharmony_ci /* Optimal transfer block size. */ 261362306a36Sopenharmony_ci sfs->f_bsize = PAGE_SIZE; 261462306a36Sopenharmony_ci /* 261562306a36Sopenharmony_ci * Total data blocks in filesystem in units of f_bsize and since 261662306a36Sopenharmony_ci * inodes are also stored in data blocs ($MFT is a file) this is just 261762306a36Sopenharmony_ci * the total clusters. 261862306a36Sopenharmony_ci */ 261962306a36Sopenharmony_ci sfs->f_blocks = vol->nr_clusters << vol->cluster_size_bits >> 262062306a36Sopenharmony_ci PAGE_SHIFT; 262162306a36Sopenharmony_ci /* Free data blocks in filesystem in units of f_bsize. */ 262262306a36Sopenharmony_ci size = get_nr_free_clusters(vol) << vol->cluster_size_bits >> 262362306a36Sopenharmony_ci PAGE_SHIFT; 262462306a36Sopenharmony_ci if (size < 0LL) 262562306a36Sopenharmony_ci size = 0LL; 262662306a36Sopenharmony_ci /* Free blocks avail to non-superuser, same as above on NTFS. */ 262762306a36Sopenharmony_ci sfs->f_bavail = sfs->f_bfree = size; 262862306a36Sopenharmony_ci /* Serialize accesses to the inode bitmap. */ 262962306a36Sopenharmony_ci down_read(&vol->mftbmp_lock); 263062306a36Sopenharmony_ci read_lock_irqsave(&mft_ni->size_lock, flags); 263162306a36Sopenharmony_ci size = i_size_read(vol->mft_ino) >> vol->mft_record_size_bits; 263262306a36Sopenharmony_ci /* 263362306a36Sopenharmony_ci * Convert the maximum number of set bits into bytes rounded up, then 263462306a36Sopenharmony_ci * convert into multiples of PAGE_SIZE, rounding up so that if we 263562306a36Sopenharmony_ci * have one full and one partial page max_index = 2. 263662306a36Sopenharmony_ci */ 263762306a36Sopenharmony_ci max_index = ((((mft_ni->initialized_size >> vol->mft_record_size_bits) 263862306a36Sopenharmony_ci + 7) >> 3) + PAGE_SIZE - 1) >> PAGE_SHIFT; 263962306a36Sopenharmony_ci read_unlock_irqrestore(&mft_ni->size_lock, flags); 264062306a36Sopenharmony_ci /* Number of inodes in filesystem (at this point in time). */ 264162306a36Sopenharmony_ci sfs->f_files = size; 264262306a36Sopenharmony_ci /* Free inodes in fs (based on current total count). */ 264362306a36Sopenharmony_ci sfs->f_ffree = __get_nr_free_mft_records(vol, size, max_index); 264462306a36Sopenharmony_ci up_read(&vol->mftbmp_lock); 264562306a36Sopenharmony_ci /* 264662306a36Sopenharmony_ci * File system id. This is extremely *nix flavour dependent and even 264762306a36Sopenharmony_ci * within Linux itself all fs do their own thing. I interpret this to 264862306a36Sopenharmony_ci * mean a unique id associated with the mounted fs and not the id 264962306a36Sopenharmony_ci * associated with the filesystem driver, the latter is already given 265062306a36Sopenharmony_ci * by the filesystem type in sfs->f_type. Thus we use the 64-bit 265162306a36Sopenharmony_ci * volume serial number splitting it into two 32-bit parts. We enter 265262306a36Sopenharmony_ci * the least significant 32-bits in f_fsid[0] and the most significant 265362306a36Sopenharmony_ci * 32-bits in f_fsid[1]. 265462306a36Sopenharmony_ci */ 265562306a36Sopenharmony_ci sfs->f_fsid = u64_to_fsid(vol->serial_no); 265662306a36Sopenharmony_ci /* Maximum length of filenames. */ 265762306a36Sopenharmony_ci sfs->f_namelen = NTFS_MAX_NAME_LEN; 265862306a36Sopenharmony_ci return 0; 265962306a36Sopenharmony_ci} 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_ci#ifdef NTFS_RW 266262306a36Sopenharmony_cistatic int ntfs_write_inode(struct inode *vi, struct writeback_control *wbc) 266362306a36Sopenharmony_ci{ 266462306a36Sopenharmony_ci return __ntfs_write_inode(vi, wbc->sync_mode == WB_SYNC_ALL); 266562306a36Sopenharmony_ci} 266662306a36Sopenharmony_ci#endif 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci/* 266962306a36Sopenharmony_ci * The complete super operations. 267062306a36Sopenharmony_ci */ 267162306a36Sopenharmony_cistatic const struct super_operations ntfs_sops = { 267262306a36Sopenharmony_ci .alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */ 267362306a36Sopenharmony_ci .free_inode = ntfs_free_big_inode, /* VFS: Deallocate inode. */ 267462306a36Sopenharmony_ci#ifdef NTFS_RW 267562306a36Sopenharmony_ci .write_inode = ntfs_write_inode, /* VFS: Write dirty inode to 267662306a36Sopenharmony_ci disk. */ 267762306a36Sopenharmony_ci#endif /* NTFS_RW */ 267862306a36Sopenharmony_ci .put_super = ntfs_put_super, /* Syscall: umount. */ 267962306a36Sopenharmony_ci .statfs = ntfs_statfs, /* Syscall: statfs */ 268062306a36Sopenharmony_ci .remount_fs = ntfs_remount, /* Syscall: mount -o remount. */ 268162306a36Sopenharmony_ci .evict_inode = ntfs_evict_big_inode, /* VFS: Called when an inode is 268262306a36Sopenharmony_ci removed from memory. */ 268362306a36Sopenharmony_ci .show_options = ntfs_show_options, /* Show mount options in 268462306a36Sopenharmony_ci proc. */ 268562306a36Sopenharmony_ci}; 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ci/** 268862306a36Sopenharmony_ci * ntfs_fill_super - mount an ntfs filesystem 268962306a36Sopenharmony_ci * @sb: super block of ntfs filesystem to mount 269062306a36Sopenharmony_ci * @opt: string containing the mount options 269162306a36Sopenharmony_ci * @silent: silence error output 269262306a36Sopenharmony_ci * 269362306a36Sopenharmony_ci * ntfs_fill_super() is called by the VFS to mount the device described by @sb 269462306a36Sopenharmony_ci * with the mount otions in @data with the NTFS filesystem. 269562306a36Sopenharmony_ci * 269662306a36Sopenharmony_ci * If @silent is true, remain silent even if errors are detected. This is used 269762306a36Sopenharmony_ci * during bootup, when the kernel tries to mount the root filesystem with all 269862306a36Sopenharmony_ci * registered filesystems one after the other until one succeeds. This implies 269962306a36Sopenharmony_ci * that all filesystems except the correct one will quite correctly and 270062306a36Sopenharmony_ci * expectedly return an error, but nobody wants to see error messages when in 270162306a36Sopenharmony_ci * fact this is what is supposed to happen. 270262306a36Sopenharmony_ci * 270362306a36Sopenharmony_ci * NOTE: @sb->s_flags contains the mount options flags. 270462306a36Sopenharmony_ci */ 270562306a36Sopenharmony_cistatic int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) 270662306a36Sopenharmony_ci{ 270762306a36Sopenharmony_ci ntfs_volume *vol; 270862306a36Sopenharmony_ci struct buffer_head *bh; 270962306a36Sopenharmony_ci struct inode *tmp_ino; 271062306a36Sopenharmony_ci int blocksize, result; 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci /* 271362306a36Sopenharmony_ci * We do a pretty difficult piece of bootstrap by reading the 271462306a36Sopenharmony_ci * MFT (and other metadata) from disk into memory. We'll only 271562306a36Sopenharmony_ci * release this metadata during umount, so the locking patterns 271662306a36Sopenharmony_ci * observed during bootstrap do not count. So turn off the 271762306a36Sopenharmony_ci * observation of locking patterns (strictly for this context 271862306a36Sopenharmony_ci * only) while mounting NTFS. [The validator is still active 271962306a36Sopenharmony_ci * otherwise, even for this context: it will for example record 272062306a36Sopenharmony_ci * lock class registrations.] 272162306a36Sopenharmony_ci */ 272262306a36Sopenharmony_ci lockdep_off(); 272362306a36Sopenharmony_ci ntfs_debug("Entering."); 272462306a36Sopenharmony_ci#ifndef NTFS_RW 272562306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 272662306a36Sopenharmony_ci#endif /* ! NTFS_RW */ 272762306a36Sopenharmony_ci /* Allocate a new ntfs_volume and place it in sb->s_fs_info. */ 272862306a36Sopenharmony_ci sb->s_fs_info = kmalloc(sizeof(ntfs_volume), GFP_NOFS); 272962306a36Sopenharmony_ci vol = NTFS_SB(sb); 273062306a36Sopenharmony_ci if (!vol) { 273162306a36Sopenharmony_ci if (!silent) 273262306a36Sopenharmony_ci ntfs_error(sb, "Allocation of NTFS volume structure " 273362306a36Sopenharmony_ci "failed. Aborting mount..."); 273462306a36Sopenharmony_ci lockdep_on(); 273562306a36Sopenharmony_ci return -ENOMEM; 273662306a36Sopenharmony_ci } 273762306a36Sopenharmony_ci /* Initialize ntfs_volume structure. */ 273862306a36Sopenharmony_ci *vol = (ntfs_volume) { 273962306a36Sopenharmony_ci .sb = sb, 274062306a36Sopenharmony_ci /* 274162306a36Sopenharmony_ci * Default is group and other don't have any access to files or 274262306a36Sopenharmony_ci * directories while owner has full access. Further, files by 274362306a36Sopenharmony_ci * default are not executable but directories are of course 274462306a36Sopenharmony_ci * browseable. 274562306a36Sopenharmony_ci */ 274662306a36Sopenharmony_ci .fmask = 0177, 274762306a36Sopenharmony_ci .dmask = 0077, 274862306a36Sopenharmony_ci }; 274962306a36Sopenharmony_ci init_rwsem(&vol->mftbmp_lock); 275062306a36Sopenharmony_ci init_rwsem(&vol->lcnbmp_lock); 275162306a36Sopenharmony_ci 275262306a36Sopenharmony_ci /* By default, enable sparse support. */ 275362306a36Sopenharmony_ci NVolSetSparseEnabled(vol); 275462306a36Sopenharmony_ci 275562306a36Sopenharmony_ci /* Important to get the mount options dealt with now. */ 275662306a36Sopenharmony_ci if (!parse_options(vol, (char*)opt)) 275762306a36Sopenharmony_ci goto err_out_now; 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_ci /* We support sector sizes up to the PAGE_SIZE. */ 276062306a36Sopenharmony_ci if (bdev_logical_block_size(sb->s_bdev) > PAGE_SIZE) { 276162306a36Sopenharmony_ci if (!silent) 276262306a36Sopenharmony_ci ntfs_error(sb, "Device has unsupported sector size " 276362306a36Sopenharmony_ci "(%i). The maximum supported sector " 276462306a36Sopenharmony_ci "size on this architecture is %lu " 276562306a36Sopenharmony_ci "bytes.", 276662306a36Sopenharmony_ci bdev_logical_block_size(sb->s_bdev), 276762306a36Sopenharmony_ci PAGE_SIZE); 276862306a36Sopenharmony_ci goto err_out_now; 276962306a36Sopenharmony_ci } 277062306a36Sopenharmony_ci /* 277162306a36Sopenharmony_ci * Setup the device access block size to NTFS_BLOCK_SIZE or the hard 277262306a36Sopenharmony_ci * sector size, whichever is bigger. 277362306a36Sopenharmony_ci */ 277462306a36Sopenharmony_ci blocksize = sb_min_blocksize(sb, NTFS_BLOCK_SIZE); 277562306a36Sopenharmony_ci if (blocksize < NTFS_BLOCK_SIZE) { 277662306a36Sopenharmony_ci if (!silent) 277762306a36Sopenharmony_ci ntfs_error(sb, "Unable to set device block size."); 277862306a36Sopenharmony_ci goto err_out_now; 277962306a36Sopenharmony_ci } 278062306a36Sopenharmony_ci BUG_ON(blocksize != sb->s_blocksize); 278162306a36Sopenharmony_ci ntfs_debug("Set device block size to %i bytes (block size bits %i).", 278262306a36Sopenharmony_ci blocksize, sb->s_blocksize_bits); 278362306a36Sopenharmony_ci /* Determine the size of the device in units of block_size bytes. */ 278462306a36Sopenharmony_ci vol->nr_blocks = sb_bdev_nr_blocks(sb); 278562306a36Sopenharmony_ci if (!vol->nr_blocks) { 278662306a36Sopenharmony_ci if (!silent) 278762306a36Sopenharmony_ci ntfs_error(sb, "Unable to determine device size."); 278862306a36Sopenharmony_ci goto err_out_now; 278962306a36Sopenharmony_ci } 279062306a36Sopenharmony_ci /* Read the boot sector and return unlocked buffer head to it. */ 279162306a36Sopenharmony_ci if (!(bh = read_ntfs_boot_sector(sb, silent))) { 279262306a36Sopenharmony_ci if (!silent) 279362306a36Sopenharmony_ci ntfs_error(sb, "Not an NTFS volume."); 279462306a36Sopenharmony_ci goto err_out_now; 279562306a36Sopenharmony_ci } 279662306a36Sopenharmony_ci /* 279762306a36Sopenharmony_ci * Extract the data from the boot sector and setup the ntfs volume 279862306a36Sopenharmony_ci * using it. 279962306a36Sopenharmony_ci */ 280062306a36Sopenharmony_ci result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data); 280162306a36Sopenharmony_ci brelse(bh); 280262306a36Sopenharmony_ci if (!result) { 280362306a36Sopenharmony_ci if (!silent) 280462306a36Sopenharmony_ci ntfs_error(sb, "Unsupported NTFS filesystem."); 280562306a36Sopenharmony_ci goto err_out_now; 280662306a36Sopenharmony_ci } 280762306a36Sopenharmony_ci /* 280862306a36Sopenharmony_ci * If the boot sector indicates a sector size bigger than the current 280962306a36Sopenharmony_ci * device block size, switch the device block size to the sector size. 281062306a36Sopenharmony_ci * TODO: It may be possible to support this case even when the set 281162306a36Sopenharmony_ci * below fails, we would just be breaking up the i/o for each sector 281262306a36Sopenharmony_ci * into multiple blocks for i/o purposes but otherwise it should just 281362306a36Sopenharmony_ci * work. However it is safer to leave disabled until someone hits this 281462306a36Sopenharmony_ci * error message and then we can get them to try it without the setting 281562306a36Sopenharmony_ci * so we know for sure that it works. 281662306a36Sopenharmony_ci */ 281762306a36Sopenharmony_ci if (vol->sector_size > blocksize) { 281862306a36Sopenharmony_ci blocksize = sb_set_blocksize(sb, vol->sector_size); 281962306a36Sopenharmony_ci if (blocksize != vol->sector_size) { 282062306a36Sopenharmony_ci if (!silent) 282162306a36Sopenharmony_ci ntfs_error(sb, "Unable to set device block " 282262306a36Sopenharmony_ci "size to sector size (%i).", 282362306a36Sopenharmony_ci vol->sector_size); 282462306a36Sopenharmony_ci goto err_out_now; 282562306a36Sopenharmony_ci } 282662306a36Sopenharmony_ci BUG_ON(blocksize != sb->s_blocksize); 282762306a36Sopenharmony_ci vol->nr_blocks = sb_bdev_nr_blocks(sb); 282862306a36Sopenharmony_ci ntfs_debug("Changed device block size to %i bytes (block size " 282962306a36Sopenharmony_ci "bits %i) to match volume sector size.", 283062306a36Sopenharmony_ci blocksize, sb->s_blocksize_bits); 283162306a36Sopenharmony_ci } 283262306a36Sopenharmony_ci /* Initialize the cluster and mft allocators. */ 283362306a36Sopenharmony_ci ntfs_setup_allocators(vol); 283462306a36Sopenharmony_ci /* Setup remaining fields in the super block. */ 283562306a36Sopenharmony_ci sb->s_magic = NTFS_SB_MAGIC; 283662306a36Sopenharmony_ci /* 283762306a36Sopenharmony_ci * Ntfs allows 63 bits for the file size, i.e. correct would be: 283862306a36Sopenharmony_ci * sb->s_maxbytes = ~0ULL >> 1; 283962306a36Sopenharmony_ci * But the kernel uses a long as the page cache page index which on 284062306a36Sopenharmony_ci * 32-bit architectures is only 32-bits. MAX_LFS_FILESIZE is kernel 284162306a36Sopenharmony_ci * defined to the maximum the page cache page index can cope with 284262306a36Sopenharmony_ci * without overflowing the index or to 2^63 - 1, whichever is smaller. 284362306a36Sopenharmony_ci */ 284462306a36Sopenharmony_ci sb->s_maxbytes = MAX_LFS_FILESIZE; 284562306a36Sopenharmony_ci /* Ntfs measures time in 100ns intervals. */ 284662306a36Sopenharmony_ci sb->s_time_gran = 100; 284762306a36Sopenharmony_ci /* 284862306a36Sopenharmony_ci * Now load the metadata required for the page cache and our address 284962306a36Sopenharmony_ci * space operations to function. We do this by setting up a specialised 285062306a36Sopenharmony_ci * read_inode method and then just calling the normal iget() to obtain 285162306a36Sopenharmony_ci * the inode for $MFT which is sufficient to allow our normal inode 285262306a36Sopenharmony_ci * operations and associated address space operations to function. 285362306a36Sopenharmony_ci */ 285462306a36Sopenharmony_ci sb->s_op = &ntfs_sops; 285562306a36Sopenharmony_ci tmp_ino = new_inode(sb); 285662306a36Sopenharmony_ci if (!tmp_ino) { 285762306a36Sopenharmony_ci if (!silent) 285862306a36Sopenharmony_ci ntfs_error(sb, "Failed to load essential metadata."); 285962306a36Sopenharmony_ci goto err_out_now; 286062306a36Sopenharmony_ci } 286162306a36Sopenharmony_ci tmp_ino->i_ino = FILE_MFT; 286262306a36Sopenharmony_ci insert_inode_hash(tmp_ino); 286362306a36Sopenharmony_ci if (ntfs_read_inode_mount(tmp_ino) < 0) { 286462306a36Sopenharmony_ci if (!silent) 286562306a36Sopenharmony_ci ntfs_error(sb, "Failed to load essential metadata."); 286662306a36Sopenharmony_ci goto iput_tmp_ino_err_out_now; 286762306a36Sopenharmony_ci } 286862306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 286962306a36Sopenharmony_ci /* 287062306a36Sopenharmony_ci * The current mount is a compression user if the cluster size is 287162306a36Sopenharmony_ci * less than or equal 4kiB. 287262306a36Sopenharmony_ci */ 287362306a36Sopenharmony_ci if (vol->cluster_size <= 4096 && !ntfs_nr_compression_users++) { 287462306a36Sopenharmony_ci result = allocate_compression_buffers(); 287562306a36Sopenharmony_ci if (result) { 287662306a36Sopenharmony_ci ntfs_error(NULL, "Failed to allocate buffers " 287762306a36Sopenharmony_ci "for compression engine."); 287862306a36Sopenharmony_ci ntfs_nr_compression_users--; 287962306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 288062306a36Sopenharmony_ci goto iput_tmp_ino_err_out_now; 288162306a36Sopenharmony_ci } 288262306a36Sopenharmony_ci } 288362306a36Sopenharmony_ci /* 288462306a36Sopenharmony_ci * Generate the global default upcase table if necessary. Also 288562306a36Sopenharmony_ci * temporarily increment the number of upcase users to avoid race 288662306a36Sopenharmony_ci * conditions with concurrent (u)mounts. 288762306a36Sopenharmony_ci */ 288862306a36Sopenharmony_ci if (!default_upcase) 288962306a36Sopenharmony_ci default_upcase = generate_default_upcase(); 289062306a36Sopenharmony_ci ntfs_nr_upcase_users++; 289162306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 289262306a36Sopenharmony_ci /* 289362306a36Sopenharmony_ci * From now on, ignore @silent parameter. If we fail below this line, 289462306a36Sopenharmony_ci * it will be due to a corrupt fs or a system error, so we report it. 289562306a36Sopenharmony_ci */ 289662306a36Sopenharmony_ci /* 289762306a36Sopenharmony_ci * Open the system files with normal access functions and complete 289862306a36Sopenharmony_ci * setting up the ntfs super block. 289962306a36Sopenharmony_ci */ 290062306a36Sopenharmony_ci if (!load_system_files(vol)) { 290162306a36Sopenharmony_ci ntfs_error(sb, "Failed to load system files."); 290262306a36Sopenharmony_ci goto unl_upcase_iput_tmp_ino_err_out_now; 290362306a36Sopenharmony_ci } 290462306a36Sopenharmony_ci 290562306a36Sopenharmony_ci /* We grab a reference, simulating an ntfs_iget(). */ 290662306a36Sopenharmony_ci ihold(vol->root_ino); 290762306a36Sopenharmony_ci if ((sb->s_root = d_make_root(vol->root_ino))) { 290862306a36Sopenharmony_ci ntfs_debug("Exiting, status successful."); 290962306a36Sopenharmony_ci /* Release the default upcase if it has no users. */ 291062306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 291162306a36Sopenharmony_ci if (!--ntfs_nr_upcase_users && default_upcase) { 291262306a36Sopenharmony_ci ntfs_free(default_upcase); 291362306a36Sopenharmony_ci default_upcase = NULL; 291462306a36Sopenharmony_ci } 291562306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 291662306a36Sopenharmony_ci sb->s_export_op = &ntfs_export_ops; 291762306a36Sopenharmony_ci lockdep_on(); 291862306a36Sopenharmony_ci return 0; 291962306a36Sopenharmony_ci } 292062306a36Sopenharmony_ci ntfs_error(sb, "Failed to allocate root directory."); 292162306a36Sopenharmony_ci /* Clean up after the successful load_system_files() call from above. */ 292262306a36Sopenharmony_ci // TODO: Use ntfs_put_super() instead of repeating all this code... 292362306a36Sopenharmony_ci // FIXME: Should mark the volume clean as the error is most likely 292462306a36Sopenharmony_ci // -ENOMEM. 292562306a36Sopenharmony_ci iput(vol->vol_ino); 292662306a36Sopenharmony_ci vol->vol_ino = NULL; 292762306a36Sopenharmony_ci /* NTFS 3.0+ specific clean up. */ 292862306a36Sopenharmony_ci if (vol->major_ver >= 3) { 292962306a36Sopenharmony_ci#ifdef NTFS_RW 293062306a36Sopenharmony_ci if (vol->usnjrnl_j_ino) { 293162306a36Sopenharmony_ci iput(vol->usnjrnl_j_ino); 293262306a36Sopenharmony_ci vol->usnjrnl_j_ino = NULL; 293362306a36Sopenharmony_ci } 293462306a36Sopenharmony_ci if (vol->usnjrnl_max_ino) { 293562306a36Sopenharmony_ci iput(vol->usnjrnl_max_ino); 293662306a36Sopenharmony_ci vol->usnjrnl_max_ino = NULL; 293762306a36Sopenharmony_ci } 293862306a36Sopenharmony_ci if (vol->usnjrnl_ino) { 293962306a36Sopenharmony_ci iput(vol->usnjrnl_ino); 294062306a36Sopenharmony_ci vol->usnjrnl_ino = NULL; 294162306a36Sopenharmony_ci } 294262306a36Sopenharmony_ci if (vol->quota_q_ino) { 294362306a36Sopenharmony_ci iput(vol->quota_q_ino); 294462306a36Sopenharmony_ci vol->quota_q_ino = NULL; 294562306a36Sopenharmony_ci } 294662306a36Sopenharmony_ci if (vol->quota_ino) { 294762306a36Sopenharmony_ci iput(vol->quota_ino); 294862306a36Sopenharmony_ci vol->quota_ino = NULL; 294962306a36Sopenharmony_ci } 295062306a36Sopenharmony_ci#endif /* NTFS_RW */ 295162306a36Sopenharmony_ci if (vol->extend_ino) { 295262306a36Sopenharmony_ci iput(vol->extend_ino); 295362306a36Sopenharmony_ci vol->extend_ino = NULL; 295462306a36Sopenharmony_ci } 295562306a36Sopenharmony_ci if (vol->secure_ino) { 295662306a36Sopenharmony_ci iput(vol->secure_ino); 295762306a36Sopenharmony_ci vol->secure_ino = NULL; 295862306a36Sopenharmony_ci } 295962306a36Sopenharmony_ci } 296062306a36Sopenharmony_ci iput(vol->root_ino); 296162306a36Sopenharmony_ci vol->root_ino = NULL; 296262306a36Sopenharmony_ci iput(vol->lcnbmp_ino); 296362306a36Sopenharmony_ci vol->lcnbmp_ino = NULL; 296462306a36Sopenharmony_ci iput(vol->mftbmp_ino); 296562306a36Sopenharmony_ci vol->mftbmp_ino = NULL; 296662306a36Sopenharmony_ci#ifdef NTFS_RW 296762306a36Sopenharmony_ci if (vol->logfile_ino) { 296862306a36Sopenharmony_ci iput(vol->logfile_ino); 296962306a36Sopenharmony_ci vol->logfile_ino = NULL; 297062306a36Sopenharmony_ci } 297162306a36Sopenharmony_ci if (vol->mftmirr_ino) { 297262306a36Sopenharmony_ci iput(vol->mftmirr_ino); 297362306a36Sopenharmony_ci vol->mftmirr_ino = NULL; 297462306a36Sopenharmony_ci } 297562306a36Sopenharmony_ci#endif /* NTFS_RW */ 297662306a36Sopenharmony_ci /* Throw away the table of attribute definitions. */ 297762306a36Sopenharmony_ci vol->attrdef_size = 0; 297862306a36Sopenharmony_ci if (vol->attrdef) { 297962306a36Sopenharmony_ci ntfs_free(vol->attrdef); 298062306a36Sopenharmony_ci vol->attrdef = NULL; 298162306a36Sopenharmony_ci } 298262306a36Sopenharmony_ci vol->upcase_len = 0; 298362306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 298462306a36Sopenharmony_ci if (vol->upcase == default_upcase) { 298562306a36Sopenharmony_ci ntfs_nr_upcase_users--; 298662306a36Sopenharmony_ci vol->upcase = NULL; 298762306a36Sopenharmony_ci } 298862306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 298962306a36Sopenharmony_ci if (vol->upcase) { 299062306a36Sopenharmony_ci ntfs_free(vol->upcase); 299162306a36Sopenharmony_ci vol->upcase = NULL; 299262306a36Sopenharmony_ci } 299362306a36Sopenharmony_ci if (vol->nls_map) { 299462306a36Sopenharmony_ci unload_nls(vol->nls_map); 299562306a36Sopenharmony_ci vol->nls_map = NULL; 299662306a36Sopenharmony_ci } 299762306a36Sopenharmony_ci /* Error exit code path. */ 299862306a36Sopenharmony_ciunl_upcase_iput_tmp_ino_err_out_now: 299962306a36Sopenharmony_ci /* 300062306a36Sopenharmony_ci * Decrease the number of upcase users and destroy the global default 300162306a36Sopenharmony_ci * upcase table if necessary. 300262306a36Sopenharmony_ci */ 300362306a36Sopenharmony_ci mutex_lock(&ntfs_lock); 300462306a36Sopenharmony_ci if (!--ntfs_nr_upcase_users && default_upcase) { 300562306a36Sopenharmony_ci ntfs_free(default_upcase); 300662306a36Sopenharmony_ci default_upcase = NULL; 300762306a36Sopenharmony_ci } 300862306a36Sopenharmony_ci if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) 300962306a36Sopenharmony_ci free_compression_buffers(); 301062306a36Sopenharmony_ci mutex_unlock(&ntfs_lock); 301162306a36Sopenharmony_ciiput_tmp_ino_err_out_now: 301262306a36Sopenharmony_ci iput(tmp_ino); 301362306a36Sopenharmony_ci if (vol->mft_ino && vol->mft_ino != tmp_ino) 301462306a36Sopenharmony_ci iput(vol->mft_ino); 301562306a36Sopenharmony_ci vol->mft_ino = NULL; 301662306a36Sopenharmony_ci /* Errors at this stage are irrelevant. */ 301762306a36Sopenharmony_cierr_out_now: 301862306a36Sopenharmony_ci sb->s_fs_info = NULL; 301962306a36Sopenharmony_ci kfree(vol); 302062306a36Sopenharmony_ci ntfs_debug("Failed, returning -EINVAL."); 302162306a36Sopenharmony_ci lockdep_on(); 302262306a36Sopenharmony_ci return -EINVAL; 302362306a36Sopenharmony_ci} 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ci/* 302662306a36Sopenharmony_ci * This is a slab cache to optimize allocations and deallocations of Unicode 302762306a36Sopenharmony_ci * strings of the maximum length allowed by NTFS, which is NTFS_MAX_NAME_LEN 302862306a36Sopenharmony_ci * (255) Unicode characters + a terminating NULL Unicode character. 302962306a36Sopenharmony_ci */ 303062306a36Sopenharmony_cistruct kmem_cache *ntfs_name_cache; 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci/* Slab caches for efficient allocation/deallocation of inodes. */ 303362306a36Sopenharmony_cistruct kmem_cache *ntfs_inode_cache; 303462306a36Sopenharmony_cistruct kmem_cache *ntfs_big_inode_cache; 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_ci/* Init once constructor for the inode slab cache. */ 303762306a36Sopenharmony_cistatic void ntfs_big_inode_init_once(void *foo) 303862306a36Sopenharmony_ci{ 303962306a36Sopenharmony_ci ntfs_inode *ni = (ntfs_inode *)foo; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci inode_init_once(VFS_I(ni)); 304262306a36Sopenharmony_ci} 304362306a36Sopenharmony_ci 304462306a36Sopenharmony_ci/* 304562306a36Sopenharmony_ci * Slab caches to optimize allocations and deallocations of attribute search 304662306a36Sopenharmony_ci * contexts and index contexts, respectively. 304762306a36Sopenharmony_ci */ 304862306a36Sopenharmony_cistruct kmem_cache *ntfs_attr_ctx_cache; 304962306a36Sopenharmony_cistruct kmem_cache *ntfs_index_ctx_cache; 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci/* Driver wide mutex. */ 305262306a36Sopenharmony_ciDEFINE_MUTEX(ntfs_lock); 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_cistatic struct dentry *ntfs_mount(struct file_system_type *fs_type, 305562306a36Sopenharmony_ci int flags, const char *dev_name, void *data) 305662306a36Sopenharmony_ci{ 305762306a36Sopenharmony_ci return mount_bdev(fs_type, flags, dev_name, data, ntfs_fill_super); 305862306a36Sopenharmony_ci} 305962306a36Sopenharmony_ci 306062306a36Sopenharmony_cistatic struct file_system_type ntfs_fs_type = { 306162306a36Sopenharmony_ci .owner = THIS_MODULE, 306262306a36Sopenharmony_ci .name = "ntfs", 306362306a36Sopenharmony_ci .mount = ntfs_mount, 306462306a36Sopenharmony_ci .kill_sb = kill_block_super, 306562306a36Sopenharmony_ci .fs_flags = FS_REQUIRES_DEV, 306662306a36Sopenharmony_ci}; 306762306a36Sopenharmony_ciMODULE_ALIAS_FS("ntfs"); 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_ci/* Stable names for the slab caches. */ 307062306a36Sopenharmony_cistatic const char ntfs_index_ctx_cache_name[] = "ntfs_index_ctx_cache"; 307162306a36Sopenharmony_cistatic const char ntfs_attr_ctx_cache_name[] = "ntfs_attr_ctx_cache"; 307262306a36Sopenharmony_cistatic const char ntfs_name_cache_name[] = "ntfs_name_cache"; 307362306a36Sopenharmony_cistatic const char ntfs_inode_cache_name[] = "ntfs_inode_cache"; 307462306a36Sopenharmony_cistatic const char ntfs_big_inode_cache_name[] = "ntfs_big_inode_cache"; 307562306a36Sopenharmony_ci 307662306a36Sopenharmony_cistatic int __init init_ntfs_fs(void) 307762306a36Sopenharmony_ci{ 307862306a36Sopenharmony_ci int err = 0; 307962306a36Sopenharmony_ci 308062306a36Sopenharmony_ci /* This may be ugly but it results in pretty output so who cares. (-8 */ 308162306a36Sopenharmony_ci pr_info("driver " NTFS_VERSION " [Flags: R/" 308262306a36Sopenharmony_ci#ifdef NTFS_RW 308362306a36Sopenharmony_ci "W" 308462306a36Sopenharmony_ci#else 308562306a36Sopenharmony_ci "O" 308662306a36Sopenharmony_ci#endif 308762306a36Sopenharmony_ci#ifdef DEBUG 308862306a36Sopenharmony_ci " DEBUG" 308962306a36Sopenharmony_ci#endif 309062306a36Sopenharmony_ci#ifdef MODULE 309162306a36Sopenharmony_ci " MODULE" 309262306a36Sopenharmony_ci#endif 309362306a36Sopenharmony_ci "].\n"); 309462306a36Sopenharmony_ci 309562306a36Sopenharmony_ci ntfs_debug("Debug messages are enabled."); 309662306a36Sopenharmony_ci 309762306a36Sopenharmony_ci ntfs_index_ctx_cache = kmem_cache_create(ntfs_index_ctx_cache_name, 309862306a36Sopenharmony_ci sizeof(ntfs_index_context), 0 /* offset */, 309962306a36Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL /* ctor */); 310062306a36Sopenharmony_ci if (!ntfs_index_ctx_cache) { 310162306a36Sopenharmony_ci pr_crit("Failed to create %s!\n", ntfs_index_ctx_cache_name); 310262306a36Sopenharmony_ci goto ictx_err_out; 310362306a36Sopenharmony_ci } 310462306a36Sopenharmony_ci ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name, 310562306a36Sopenharmony_ci sizeof(ntfs_attr_search_ctx), 0 /* offset */, 310662306a36Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL /* ctor */); 310762306a36Sopenharmony_ci if (!ntfs_attr_ctx_cache) { 310862306a36Sopenharmony_ci pr_crit("NTFS: Failed to create %s!\n", 310962306a36Sopenharmony_ci ntfs_attr_ctx_cache_name); 311062306a36Sopenharmony_ci goto actx_err_out; 311162306a36Sopenharmony_ci } 311262306a36Sopenharmony_ci 311362306a36Sopenharmony_ci ntfs_name_cache = kmem_cache_create(ntfs_name_cache_name, 311462306a36Sopenharmony_ci (NTFS_MAX_NAME_LEN+1) * sizeof(ntfschar), 0, 311562306a36Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL); 311662306a36Sopenharmony_ci if (!ntfs_name_cache) { 311762306a36Sopenharmony_ci pr_crit("Failed to create %s!\n", ntfs_name_cache_name); 311862306a36Sopenharmony_ci goto name_err_out; 311962306a36Sopenharmony_ci } 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name, 312262306a36Sopenharmony_ci sizeof(ntfs_inode), 0, 312362306a36Sopenharmony_ci SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL); 312462306a36Sopenharmony_ci if (!ntfs_inode_cache) { 312562306a36Sopenharmony_ci pr_crit("Failed to create %s!\n", ntfs_inode_cache_name); 312662306a36Sopenharmony_ci goto inode_err_out; 312762306a36Sopenharmony_ci } 312862306a36Sopenharmony_ci 312962306a36Sopenharmony_ci ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name, 313062306a36Sopenharmony_ci sizeof(big_ntfs_inode), 0, 313162306a36Sopenharmony_ci SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD| 313262306a36Sopenharmony_ci SLAB_ACCOUNT, ntfs_big_inode_init_once); 313362306a36Sopenharmony_ci if (!ntfs_big_inode_cache) { 313462306a36Sopenharmony_ci pr_crit("Failed to create %s!\n", ntfs_big_inode_cache_name); 313562306a36Sopenharmony_ci goto big_inode_err_out; 313662306a36Sopenharmony_ci } 313762306a36Sopenharmony_ci 313862306a36Sopenharmony_ci /* Register the ntfs sysctls. */ 313962306a36Sopenharmony_ci err = ntfs_sysctl(1); 314062306a36Sopenharmony_ci if (err) { 314162306a36Sopenharmony_ci pr_crit("Failed to register NTFS sysctls!\n"); 314262306a36Sopenharmony_ci goto sysctl_err_out; 314362306a36Sopenharmony_ci } 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci err = register_filesystem(&ntfs_fs_type); 314662306a36Sopenharmony_ci if (!err) { 314762306a36Sopenharmony_ci ntfs_debug("NTFS driver registered successfully."); 314862306a36Sopenharmony_ci return 0; /* Success! */ 314962306a36Sopenharmony_ci } 315062306a36Sopenharmony_ci pr_crit("Failed to register NTFS filesystem driver!\n"); 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci /* Unregister the ntfs sysctls. */ 315362306a36Sopenharmony_ci ntfs_sysctl(0); 315462306a36Sopenharmony_cisysctl_err_out: 315562306a36Sopenharmony_ci kmem_cache_destroy(ntfs_big_inode_cache); 315662306a36Sopenharmony_cibig_inode_err_out: 315762306a36Sopenharmony_ci kmem_cache_destroy(ntfs_inode_cache); 315862306a36Sopenharmony_ciinode_err_out: 315962306a36Sopenharmony_ci kmem_cache_destroy(ntfs_name_cache); 316062306a36Sopenharmony_ciname_err_out: 316162306a36Sopenharmony_ci kmem_cache_destroy(ntfs_attr_ctx_cache); 316262306a36Sopenharmony_ciactx_err_out: 316362306a36Sopenharmony_ci kmem_cache_destroy(ntfs_index_ctx_cache); 316462306a36Sopenharmony_ciictx_err_out: 316562306a36Sopenharmony_ci if (!err) { 316662306a36Sopenharmony_ci pr_crit("Aborting NTFS filesystem driver registration...\n"); 316762306a36Sopenharmony_ci err = -ENOMEM; 316862306a36Sopenharmony_ci } 316962306a36Sopenharmony_ci return err; 317062306a36Sopenharmony_ci} 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_cistatic void __exit exit_ntfs_fs(void) 317362306a36Sopenharmony_ci{ 317462306a36Sopenharmony_ci ntfs_debug("Unregistering NTFS driver."); 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci unregister_filesystem(&ntfs_fs_type); 317762306a36Sopenharmony_ci 317862306a36Sopenharmony_ci /* 317962306a36Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 318062306a36Sopenharmony_ci * destroy cache. 318162306a36Sopenharmony_ci */ 318262306a36Sopenharmony_ci rcu_barrier(); 318362306a36Sopenharmony_ci kmem_cache_destroy(ntfs_big_inode_cache); 318462306a36Sopenharmony_ci kmem_cache_destroy(ntfs_inode_cache); 318562306a36Sopenharmony_ci kmem_cache_destroy(ntfs_name_cache); 318662306a36Sopenharmony_ci kmem_cache_destroy(ntfs_attr_ctx_cache); 318762306a36Sopenharmony_ci kmem_cache_destroy(ntfs_index_ctx_cache); 318862306a36Sopenharmony_ci /* Unregister the ntfs sysctls. */ 318962306a36Sopenharmony_ci ntfs_sysctl(0); 319062306a36Sopenharmony_ci} 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ciMODULE_AUTHOR("Anton Altaparmakov <anton@tuxera.com>"); 319362306a36Sopenharmony_ciMODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc."); 319462306a36Sopenharmony_ciMODULE_VERSION(NTFS_VERSION); 319562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 319662306a36Sopenharmony_ci#ifdef DEBUG 319762306a36Sopenharmony_cimodule_param(debug_msgs, bint, 0); 319862306a36Sopenharmony_ciMODULE_PARM_DESC(debug_msgs, "Enable debug messages."); 319962306a36Sopenharmony_ci#endif 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_cimodule_init(init_ntfs_fs) 320262306a36Sopenharmony_cimodule_exit(exit_ntfs_fs) 3203