diff options
Diffstat (limited to 'fs/ntfs3/super.c')
| -rw-r--r-- | fs/ntfs3/super.c | 89 |
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; |
