summaryrefslogtreecommitdiff
path: root/fs/ntfs3/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs3/super.c')
-rw-r--r--fs/ntfs3/super.c89
1 files changed, 69 insertions, 20 deletions
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index ddff94c091b8..8b0cf0ed4f72 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -16,6 +16,13 @@
* mi - MFT inode - One MFT record(usually 1024 bytes or 4K), consists of attributes.
* ni - NTFS inode - Extends linux inode. consists of one or more mft inodes.
* index - unit inside directory - 2K, 4K, <=page size, does not depend on cluster size.
+ * resident attribute - Attribute with content stored directly in the MFT record
+ * non-resident attribute - Attribute with content stored in clusters
+ * data_size - Size of attribute content in bytes. Equal to inode->i_size
+ * valid_size - Number of bytes written to the non-resident attribute
+ * allocated_size - Total size of clusters allocated for non-resident content
+ * total_size - Actual size of allocated clusters for sparse or compressed attributes
+ * - Constraint: valid_size <= data_size <= allocated_size
*
* WSL - Windows Subsystem for Linux
* https://docs.microsoft.com/en-us/windows/wsl/file-permissions
@@ -51,6 +58,7 @@
#include <linux/buffer_head.h>
#include <linux/exportfs.h>
#include <linux/fs.h>
+#include <linux/fs_struct.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include <linux/log2.h>
@@ -277,9 +285,9 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = {
fsparam_flag("hide_dot_files", Opt_hide_dot_files),
fsparam_flag("windows_names", Opt_windows_names),
fsparam_flag("showmeta", Opt_showmeta),
- fsparam_flag("acl", Opt_acl),
+ fsparam_flag_no("acl", Opt_acl),
fsparam_string("iocharset", Opt_iocharset),
- fsparam_flag("prealloc", Opt_prealloc),
+ fsparam_flag_no("prealloc", Opt_prealloc),
fsparam_flag("nocase", Opt_nocase),
{}
};
@@ -288,10 +296,8 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = {
/*
* Load nls table or if @nls is utf8 then return NULL.
*
- * It is good idea to use here "const char *nls".
- * But load_nls accepts "char*".
*/
-static struct nls_table *ntfs_load_nls(char *nls)
+static struct nls_table *ntfs_load_nls(const char *nls)
{
struct nls_table *ret;
@@ -390,7 +396,7 @@ static int ntfs_fs_parse_param(struct fs_context *fc,
param->string = NULL;
break;
case Opt_prealloc:
- opts->prealloc = 1;
+ opts->prealloc = !result.negated;
break;
case Opt_nocase:
opts->nocase = 1;
@@ -566,10 +572,8 @@ static void ntfs_create_procdir(struct super_block *sb)
if (e) {
struct ntfs_sb_info *sbi = sb->s_fs_info;
- proc_create_data("volinfo", 0444, e,
- &ntfs3_volinfo_fops, sb);
- proc_create_data("label", 0644, e,
- &ntfs3_label_fops, sb);
+ proc_create_data("volinfo", 0444, e, &ntfs3_volinfo_fops, sb);
+ proc_create_data("label", 0644, e, &ntfs3_label_fops, sb);
sbi->procdir = e;
}
}
@@ -600,10 +604,12 @@ static void ntfs_remove_proc_root(void)
}
}
#else
-static void ntfs_create_procdir(struct super_block *sb) {}
-static void ntfs_remove_procdir(struct super_block *sb) {}
-static void ntfs_create_proc_root(void) {}
-static void ntfs_remove_proc_root(void) {}
+// clang-format off
+static void ntfs_create_procdir(struct super_block *sb){}
+static void ntfs_remove_procdir(struct super_block *sb){}
+static void ntfs_create_proc_root(void){}
+static void ntfs_remove_proc_root(void){}
+// clang-format on
#endif
static struct kmem_cache *ntfs_inode_cachep;
@@ -697,6 +703,14 @@ static void ntfs_put_super(struct super_block *sb)
/* Mark rw ntfs as clear, if possible. */
ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
+
+ if (sbi->options) {
+ unload_nls(sbi->options->nls);
+ kfree(sbi->options->nls_name);
+ kfree(sbi->options);
+ sbi->options = NULL;
+ }
+
ntfs3_put_sbi(sbi);
}
@@ -933,6 +947,11 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
sbi->volume.blocks = dev_size >> PAGE_SHIFT;
+ /* Set dummy blocksize to read boot_block. */
+ if (!sb_min_blocksize(sb, PAGE_SIZE)) {
+ return -EINVAL;
+ }
+
read_boot:
bh = ntfs_bread(sb, boot_block);
if (!bh)
@@ -1057,6 +1076,7 @@ read_boot:
dev_size += sector_size - 1;
}
+ sbi->bdev_blocksize_mask = max(boot_sector_size, sector_size) - 1;
sbi->mft.lbo = mlcn << cluster_bits;
sbi->mft.lbo2 = mlcn2 << cluster_bits;
@@ -1198,7 +1218,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
int err;
struct ntfs_sb_info *sbi = sb->s_fs_info;
struct block_device *bdev = sb->s_bdev;
- struct ntfs_mount_options *options;
+ struct ntfs_mount_options *fc_opts;
+ struct ntfs_mount_options *options = NULL;
struct inode *inode;
struct ntfs_inode *ni;
size_t i, tt, bad_len, bad_frags;
@@ -1215,7 +1236,23 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
ref.high = 0;
sbi->sb = sb;
- sbi->options = options = fc->fs_private;
+ fc_opts = fc->fs_private;
+ if (!fc_opts) {
+ errorf(fc, "missing mount options");
+ return -EINVAL;
+ }
+ options = kmemdup(fc_opts, sizeof(*fc_opts), GFP_KERNEL);
+ if (!options)
+ return -ENOMEM;
+
+ if (fc_opts->nls_name) {
+ options->nls_name = kstrdup(fc_opts->nls_name, GFP_KERNEL);
+ if (!options->nls_name) {
+ kfree(options);
+ return -ENOMEM;
+ }
+ }
+ sbi->options = options;
fc->fs_private = NULL;
sb->s_flags |= SB_NODIRATIME;
sb->s_magic = 0x7366746e; // "ntfs"
@@ -1223,8 +1260,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_export_op = &ntfs_export_ops;
sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec
sb->s_xattr = ntfs_xattr_handlers;
- if (options->nocase)
- set_default_d_op(sb, &ntfs_dentry_ops);
+ set_default_d_op(sb, options->nocase ? &ntfs_dentry_ops : NULL);
options->nls = ntfs_load_nls(options->nls_name);
if (IS_ERR(options->nls)) {
@@ -1294,7 +1330,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
sbi->volume.ni = ni;
if (info->flags & VOLUME_FLAG_DIRTY) {
sbi->volume.real_dirty = true;
- ntfs_info(sb, "It is recommened to use chkdsk.");
+ ntfs_info(sb, "It is recommended to use chkdsk.");
}
/* Load $MFTMirr to estimate recs_mirr. */
@@ -1641,9 +1677,16 @@ load_root:
put_inode_out:
iput(inode);
out:
+ /* sbi->options == options */
+ if (options) {
+ unload_nls(options->nls);
+ kfree(options->nls_name);
+ kfree(options);
+ sbi->options = NULL;
+ }
+
ntfs3_put_sbi(sbi);
kfree(boot2);
- ntfs3_put_sbi(sbi);
return err;
}
@@ -1767,6 +1810,12 @@ static int __ntfs_init_fs_context(struct fs_context *fc)
opts->fs_gid = current_gid();
opts->fs_fmask_inv = ~current_umask();
opts->fs_dmask_inv = ~current_umask();
+ opts->prealloc = 1;
+
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+ /* Set the default value 'acl' */
+ fc->sb_flags |= SB_POSIXACL;
+#endif
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
goto ok;