mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-14 11:42:57 +00:00
\n
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAmfqoncACgkQnJ2qBz9k QNkHTAgAt44H8tJ9gIFBdN5oB6ISx7TUDhz1kc+IcylmI6AZPaqDcJfLkI6r1q7A k0DfeTgSk3dbtxCdO67Xtit44uQLr1EXFgu2VFghCFhmeDTeYe0OvmNEFvgTpJto qI5DgcJDrV2LIl5Rh5Eto/Lgsw7+i/ovdcoG7pjVzVEHSt7FlKzeG9Qml7kHhMBs LegfOX4+sh7XgeFzB0nW0Wg5OuL0X7Iz0/IJqZyc7j0qabPzvehK/+VFlxOItweD NrJb+wveyMcDhYrGrt7cA+/MI+rEZxNxpTXL0LDTZZGU0eVeLBrUFMWBO/ju5vuL XX2OooLwmSXJBjSIcXZkiobI0kbIlg== =3hI9 -----END PGP SIGNATURE----- Merge tag 'fs_for_v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs Pull ext2, udf, and isofs updates from Jan Kara: - conversion of ext2 to the new mount API - small folio conversion work for ext2 - a fix of an unexpected return value in udf in inode_getblk() - a fix of handling of corrupted directory in isofs * tag 'fs_for_v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: udf: Fix inode_getblk() return value ext2: Make ext2_params_spec static ext2: create ext2_msg_fc for use during parsing ext2: convert to the new mount API ext2: Remove reference to bh->b_page isofs: fix KMSAN uninit-value bug in do_isofs_readdir()
This commit is contained in:
commit
4080cf02f1
4 changed files with 334 additions and 260 deletions
|
@ -368,6 +368,7 @@ struct ext2_inode {
|
||||||
#define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */
|
#define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */
|
||||||
#define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */
|
#define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */
|
||||||
#define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */
|
#define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */
|
||||||
|
#define EXT2_MOUNT_ERRORS_MASK 0x000070
|
||||||
#define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */
|
#define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */
|
||||||
#define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */
|
#define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */
|
||||||
#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */
|
#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */
|
||||||
|
|
589
fs/ext2/super.c
589
fs/ext2/super.c
|
@ -23,7 +23,8 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/parser.h>
|
#include <linux/fs_context.h>
|
||||||
|
#include <linux/fs_parser.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
@ -40,7 +41,6 @@
|
||||||
#include "acl.h"
|
#include "acl.h"
|
||||||
|
|
||||||
static void ext2_write_super(struct super_block *sb);
|
static void ext2_write_super(struct super_block *sb);
|
||||||
static int ext2_remount (struct super_block * sb, int * flags, char * data);
|
|
||||||
static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
|
static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
|
||||||
static int ext2_sync_fs(struct super_block *sb, int wait);
|
static int ext2_sync_fs(struct super_block *sb, int wait);
|
||||||
static int ext2_freeze(struct super_block *sb);
|
static int ext2_freeze(struct super_block *sb);
|
||||||
|
@ -81,6 +81,33 @@ void ext2_error(struct super_block *sb, const char *function,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ext2_msg_fc(struct fs_context *fc, const char *prefix,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct va_format vaf;
|
||||||
|
va_list args;
|
||||||
|
const char *s_id;
|
||||||
|
|
||||||
|
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
|
||||||
|
s_id = fc->root->d_sb->s_id;
|
||||||
|
} else {
|
||||||
|
/* get last path component of source */
|
||||||
|
s_id = strrchr(fc->source, '/');
|
||||||
|
if (s_id)
|
||||||
|
s_id++;
|
||||||
|
else
|
||||||
|
s_id = fc->source;
|
||||||
|
}
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
vaf.fmt = fmt;
|
||||||
|
vaf.va = &args;
|
||||||
|
|
||||||
|
printk("%sEXT2-fs (%s): %pV\n", prefix, s_id, &vaf);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
void ext2_msg(struct super_block *sb, const char *prefix,
|
void ext2_msg(struct super_block *sb, const char *prefix,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -346,7 +373,6 @@ static const struct super_operations ext2_sops = {
|
||||||
.freeze_fs = ext2_freeze,
|
.freeze_fs = ext2_freeze,
|
||||||
.unfreeze_fs = ext2_unfreeze,
|
.unfreeze_fs = ext2_unfreeze,
|
||||||
.statfs = ext2_statfs,
|
.statfs = ext2_statfs,
|
||||||
.remount_fs = ext2_remount,
|
|
||||||
.show_options = ext2_show_options,
|
.show_options = ext2_show_options,
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
.quota_read = ext2_quota_read,
|
.quota_read = ext2_quota_read,
|
||||||
|
@ -402,230 +428,217 @@ static const struct export_operations ext2_export_ops = {
|
||||||
.get_parent = ext2_get_parent,
|
.get_parent = ext2_get_parent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long get_sb_block(void **data)
|
enum {
|
||||||
{
|
Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, Opt_resgid, Opt_resuid,
|
||||||
unsigned long sb_block;
|
Opt_sb, Opt_errors, Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
|
||||||
char *options = (char *) *data;
|
Opt_nobh, Opt_user_xattr, Opt_acl, Opt_xip, Opt_dax, Opt_ignore,
|
||||||
|
Opt_quota, Opt_usrquota, Opt_grpquota, Opt_reservation,
|
||||||
|
};
|
||||||
|
|
||||||
if (!options || strncmp(options, "sb=", 3) != 0)
|
static const struct constant_table ext2_param_errors[] = {
|
||||||
return 1; /* Default location */
|
{"continue", EXT2_MOUNT_ERRORS_CONT},
|
||||||
options += 3;
|
{"panic", EXT2_MOUNT_ERRORS_PANIC},
|
||||||
sb_block = simple_strtoul(options, &options, 0);
|
{"remount-ro", EXT2_MOUNT_ERRORS_RO},
|
||||||
if (*options && *options != ',') {
|
{}
|
||||||
printk("EXT2-fs: Invalid sb specification: %s\n",
|
};
|
||||||
(char *) *data);
|
|
||||||
return 1;
|
static const struct fs_parameter_spec ext2_param_spec[] = {
|
||||||
}
|
fsparam_flag ("bsddf", Opt_bsd_df),
|
||||||
if (*options == ',')
|
fsparam_flag ("minixdf", Opt_minix_df),
|
||||||
options++;
|
fsparam_flag ("grpid", Opt_grpid),
|
||||||
*data = (void *) options;
|
fsparam_flag ("bsdgroups", Opt_grpid),
|
||||||
return sb_block;
|
fsparam_flag ("nogrpid", Opt_nogrpid),
|
||||||
|
fsparam_flag ("sysvgroups", Opt_nogrpid),
|
||||||
|
fsparam_gid ("resgid", Opt_resgid),
|
||||||
|
fsparam_uid ("resuid", Opt_resuid),
|
||||||
|
fsparam_u32 ("sb", Opt_sb),
|
||||||
|
fsparam_enum ("errors", Opt_errors, ext2_param_errors),
|
||||||
|
fsparam_flag ("nouid32", Opt_nouid32),
|
||||||
|
fsparam_flag ("debug", Opt_debug),
|
||||||
|
fsparam_flag ("oldalloc", Opt_oldalloc),
|
||||||
|
fsparam_flag ("orlov", Opt_orlov),
|
||||||
|
fsparam_flag ("nobh", Opt_nobh),
|
||||||
|
fsparam_flag_no ("user_xattr", Opt_user_xattr),
|
||||||
|
fsparam_flag_no ("acl", Opt_acl),
|
||||||
|
fsparam_flag ("xip", Opt_xip),
|
||||||
|
fsparam_flag ("dax", Opt_dax),
|
||||||
|
fsparam_flag ("grpquota", Opt_grpquota),
|
||||||
|
fsparam_flag ("noquota", Opt_ignore),
|
||||||
|
fsparam_flag ("quota", Opt_quota),
|
||||||
|
fsparam_flag ("usrquota", Opt_usrquota),
|
||||||
|
fsparam_flag_no ("reservation", Opt_reservation),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EXT2_SPEC_s_resuid (1 << 0)
|
||||||
|
#define EXT2_SPEC_s_resgid (1 << 1)
|
||||||
|
|
||||||
|
struct ext2_fs_context {
|
||||||
|
unsigned long vals_s_flags; /* Bits to set in s_flags */
|
||||||
|
unsigned long mask_s_flags; /* Bits changed in s_flags */
|
||||||
|
unsigned int vals_s_mount_opt;
|
||||||
|
unsigned int mask_s_mount_opt;
|
||||||
|
kuid_t s_resuid;
|
||||||
|
kgid_t s_resgid;
|
||||||
|
unsigned long s_sb_block;
|
||||||
|
unsigned int spec;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void ctx_set_mount_opt(struct ext2_fs_context *ctx,
|
||||||
|
unsigned long flag)
|
||||||
|
{
|
||||||
|
ctx->mask_s_mount_opt |= flag;
|
||||||
|
ctx->vals_s_mount_opt |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
static inline void ctx_clear_mount_opt(struct ext2_fs_context *ctx,
|
||||||
Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
|
unsigned long flag)
|
||||||
Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
|
|
||||||
Opt_err_ro, Opt_nouid32, Opt_debug,
|
|
||||||
Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
|
|
||||||
Opt_acl, Opt_noacl, Opt_xip, Opt_dax, Opt_ignore, Opt_err, Opt_quota,
|
|
||||||
Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation
|
|
||||||
};
|
|
||||||
|
|
||||||
static const match_table_t tokens = {
|
|
||||||
{Opt_bsd_df, "bsddf"},
|
|
||||||
{Opt_minix_df, "minixdf"},
|
|
||||||
{Opt_grpid, "grpid"},
|
|
||||||
{Opt_grpid, "bsdgroups"},
|
|
||||||
{Opt_nogrpid, "nogrpid"},
|
|
||||||
{Opt_nogrpid, "sysvgroups"},
|
|
||||||
{Opt_resgid, "resgid=%u"},
|
|
||||||
{Opt_resuid, "resuid=%u"},
|
|
||||||
{Opt_sb, "sb=%u"},
|
|
||||||
{Opt_err_cont, "errors=continue"},
|
|
||||||
{Opt_err_panic, "errors=panic"},
|
|
||||||
{Opt_err_ro, "errors=remount-ro"},
|
|
||||||
{Opt_nouid32, "nouid32"},
|
|
||||||
{Opt_debug, "debug"},
|
|
||||||
{Opt_oldalloc, "oldalloc"},
|
|
||||||
{Opt_orlov, "orlov"},
|
|
||||||
{Opt_nobh, "nobh"},
|
|
||||||
{Opt_user_xattr, "user_xattr"},
|
|
||||||
{Opt_nouser_xattr, "nouser_xattr"},
|
|
||||||
{Opt_acl, "acl"},
|
|
||||||
{Opt_noacl, "noacl"},
|
|
||||||
{Opt_xip, "xip"},
|
|
||||||
{Opt_dax, "dax"},
|
|
||||||
{Opt_grpquota, "grpquota"},
|
|
||||||
{Opt_ignore, "noquota"},
|
|
||||||
{Opt_quota, "quota"},
|
|
||||||
{Opt_usrquota, "usrquota"},
|
|
||||||
{Opt_reservation, "reservation"},
|
|
||||||
{Opt_noreservation, "noreservation"},
|
|
||||||
{Opt_err, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int parse_options(char *options, struct super_block *sb,
|
|
||||||
struct ext2_mount_options *opts)
|
|
||||||
{
|
{
|
||||||
char *p;
|
ctx->mask_s_mount_opt |= flag;
|
||||||
substring_t args[MAX_OPT_ARGS];
|
ctx->vals_s_mount_opt &= ~flag;
|
||||||
int option;
|
}
|
||||||
kuid_t uid;
|
|
||||||
kgid_t gid;
|
|
||||||
|
|
||||||
if (!options)
|
static inline unsigned long
|
||||||
return 1;
|
ctx_test_mount_opt(struct ext2_fs_context *ctx, unsigned long flag)
|
||||||
|
{
|
||||||
|
return (ctx->vals_s_mount_opt & flag);
|
||||||
|
}
|
||||||
|
|
||||||
while ((p = strsep (&options, ",")) != NULL) {
|
static inline bool
|
||||||
int token;
|
ctx_parsed_mount_opt(struct ext2_fs_context *ctx, unsigned long flag)
|
||||||
if (!*p)
|
{
|
||||||
continue;
|
return (ctx->mask_s_mount_opt & flag);
|
||||||
|
}
|
||||||
|
|
||||||
token = match_token(p, tokens, args);
|
static void ext2_free_fc(struct fs_context *fc)
|
||||||
switch (token) {
|
{
|
||||||
case Opt_bsd_df:
|
kfree(fc->fs_private);
|
||||||
clear_opt (opts->s_mount_opt, MINIX_DF);
|
}
|
||||||
break;
|
|
||||||
case Opt_minix_df:
|
|
||||||
set_opt (opts->s_mount_opt, MINIX_DF);
|
|
||||||
break;
|
|
||||||
case Opt_grpid:
|
|
||||||
set_opt (opts->s_mount_opt, GRPID);
|
|
||||||
break;
|
|
||||||
case Opt_nogrpid:
|
|
||||||
clear_opt (opts->s_mount_opt, GRPID);
|
|
||||||
break;
|
|
||||||
case Opt_resuid:
|
|
||||||
if (match_int(&args[0], &option))
|
|
||||||
return 0;
|
|
||||||
uid = make_kuid(current_user_ns(), option);
|
|
||||||
if (!uid_valid(uid)) {
|
|
||||||
ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
static int ext2_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||||
opts->s_resuid = uid;
|
{
|
||||||
break;
|
struct ext2_fs_context *ctx = fc->fs_private;
|
||||||
case Opt_resgid:
|
int opt;
|
||||||
if (match_int(&args[0], &option))
|
struct fs_parse_result result;
|
||||||
return 0;
|
|
||||||
gid = make_kgid(current_user_ns(), option);
|
opt = fs_parse(fc, ext2_param_spec, param, &result);
|
||||||
if (!gid_valid(gid)) {
|
if (opt < 0)
|
||||||
ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
|
return opt;
|
||||||
return 0;
|
|
||||||
}
|
switch (opt) {
|
||||||
opts->s_resgid = gid;
|
case Opt_bsd_df:
|
||||||
break;
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_MINIX_DF);
|
||||||
case Opt_sb:
|
break;
|
||||||
/* handled by get_sb_block() instead of here */
|
case Opt_minix_df:
|
||||||
/* *sb_block = match_int(&args[0]); */
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_MINIX_DF);
|
||||||
break;
|
break;
|
||||||
case Opt_err_panic:
|
case Opt_grpid:
|
||||||
clear_opt (opts->s_mount_opt, ERRORS_CONT);
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_GRPID);
|
||||||
clear_opt (opts->s_mount_opt, ERRORS_RO);
|
break;
|
||||||
set_opt (opts->s_mount_opt, ERRORS_PANIC);
|
case Opt_nogrpid:
|
||||||
break;
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_GRPID);
|
||||||
case Opt_err_ro:
|
break;
|
||||||
clear_opt (opts->s_mount_opt, ERRORS_CONT);
|
case Opt_resuid:
|
||||||
clear_opt (opts->s_mount_opt, ERRORS_PANIC);
|
ctx->s_resuid = result.uid;
|
||||||
set_opt (opts->s_mount_opt, ERRORS_RO);
|
ctx->spec |= EXT2_SPEC_s_resuid;
|
||||||
break;
|
break;
|
||||||
case Opt_err_cont:
|
case Opt_resgid:
|
||||||
clear_opt (opts->s_mount_opt, ERRORS_RO);
|
ctx->s_resgid = result.gid;
|
||||||
clear_opt (opts->s_mount_opt, ERRORS_PANIC);
|
ctx->spec |= EXT2_SPEC_s_resgid;
|
||||||
set_opt (opts->s_mount_opt, ERRORS_CONT);
|
break;
|
||||||
break;
|
case Opt_sb:
|
||||||
case Opt_nouid32:
|
/* Note that this is silently ignored on remount */
|
||||||
set_opt (opts->s_mount_opt, NO_UID32);
|
ctx->s_sb_block = result.uint_32;
|
||||||
break;
|
break;
|
||||||
case Opt_debug:
|
case Opt_errors:
|
||||||
set_opt (opts->s_mount_opt, DEBUG);
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_ERRORS_MASK);
|
||||||
break;
|
ctx_set_mount_opt(ctx, result.uint_32);
|
||||||
case Opt_oldalloc:
|
break;
|
||||||
set_opt (opts->s_mount_opt, OLDALLOC);
|
case Opt_nouid32:
|
||||||
break;
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_NO_UID32);
|
||||||
case Opt_orlov:
|
break;
|
||||||
clear_opt (opts->s_mount_opt, OLDALLOC);
|
case Opt_debug:
|
||||||
break;
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_DEBUG);
|
||||||
case Opt_nobh:
|
break;
|
||||||
ext2_msg(sb, KERN_INFO,
|
case Opt_oldalloc:
|
||||||
"nobh option not supported");
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_OLDALLOC);
|
||||||
break;
|
break;
|
||||||
|
case Opt_orlov:
|
||||||
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_OLDALLOC);
|
||||||
|
break;
|
||||||
|
case Opt_nobh:
|
||||||
|
ext2_msg_fc(fc, KERN_INFO, "nobh option not supported\n");
|
||||||
|
break;
|
||||||
#ifdef CONFIG_EXT2_FS_XATTR
|
#ifdef CONFIG_EXT2_FS_XATTR
|
||||||
case Opt_user_xattr:
|
case Opt_user_xattr:
|
||||||
set_opt (opts->s_mount_opt, XATTR_USER);
|
if (!result.negated)
|
||||||
break;
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_XATTR_USER);
|
||||||
case Opt_nouser_xattr:
|
else
|
||||||
clear_opt (opts->s_mount_opt, XATTR_USER);
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_XATTR_USER);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
case Opt_user_xattr:
|
case Opt_user_xattr:
|
||||||
case Opt_nouser_xattr:
|
ext2_msg_fc(fc, KERN_INFO, "(no)user_xattr options not supported");
|
||||||
ext2_msg(sb, KERN_INFO, "(no)user_xattr options"
|
break;
|
||||||
"not supported");
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
||||||
case Opt_acl:
|
case Opt_acl:
|
||||||
set_opt(opts->s_mount_opt, POSIX_ACL);
|
if (!result.negated)
|
||||||
break;
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_POSIX_ACL);
|
||||||
case Opt_noacl:
|
else
|
||||||
clear_opt(opts->s_mount_opt, POSIX_ACL);
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_POSIX_ACL);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
case Opt_acl:
|
case Opt_acl:
|
||||||
case Opt_noacl:
|
ext2_msg_fc(fc, KERN_INFO, "(no)acl options not supported");
|
||||||
ext2_msg(sb, KERN_INFO,
|
break;
|
||||||
"(no)acl options not supported");
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case Opt_xip:
|
case Opt_xip:
|
||||||
ext2_msg(sb, KERN_INFO, "use dax instead of xip");
|
ext2_msg_fc(fc, KERN_INFO, "use dax instead of xip");
|
||||||
set_opt(opts->s_mount_opt, XIP);
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_XIP);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case Opt_dax:
|
case Opt_dax:
|
||||||
#ifdef CONFIG_FS_DAX
|
#ifdef CONFIG_FS_DAX
|
||||||
ext2_msg(sb, KERN_WARNING,
|
ext2_msg_fc(fc, KERN_WARNING,
|
||||||
"DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
|
"DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
|
||||||
set_opt(opts->s_mount_opt, DAX);
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_DAX);
|
||||||
#else
|
#else
|
||||||
ext2_msg(sb, KERN_INFO, "dax option not supported");
|
ext2_msg_fc(fc, KERN_INFO, "dax option not supported");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(CONFIG_QUOTA)
|
#if defined(CONFIG_QUOTA)
|
||||||
case Opt_quota:
|
case Opt_quota:
|
||||||
case Opt_usrquota:
|
case Opt_usrquota:
|
||||||
set_opt(opts->s_mount_opt, USRQUOTA);
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_USRQUOTA);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Opt_grpquota:
|
case Opt_grpquota:
|
||||||
set_opt(opts->s_mount_opt, GRPQUOTA);
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_GRPQUOTA);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
case Opt_quota:
|
case Opt_quota:
|
||||||
case Opt_usrquota:
|
case Opt_usrquota:
|
||||||
case Opt_grpquota:
|
case Opt_grpquota:
|
||||||
ext2_msg(sb, KERN_INFO,
|
ext2_msg_fc(fc, KERN_INFO, "quota operations not supported");
|
||||||
"quota operations not supported");
|
break;
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
|
case Opt_reservation:
|
||||||
case Opt_reservation:
|
if (!result.negated) {
|
||||||
set_opt(opts->s_mount_opt, RESERVATION);
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_RESERVATION);
|
||||||
ext2_msg(sb, KERN_INFO, "reservations ON");
|
ext2_msg_fc(fc, KERN_INFO, "reservations ON");
|
||||||
break;
|
} else {
|
||||||
case Opt_noreservation:
|
ctx_clear_mount_opt(ctx, EXT2_MOUNT_RESERVATION);
|
||||||
clear_opt(opts->s_mount_opt, RESERVATION);
|
ext2_msg_fc(fc, KERN_INFO, "reservations OFF");
|
||||||
ext2_msg(sb, KERN_INFO, "reservations OFF");
|
|
||||||
break;
|
|
||||||
case Opt_ignore:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case Opt_ignore:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext2_setup_super (struct super_block * sb,
|
static int ext2_setup_super (struct super_block * sb,
|
||||||
|
@ -801,24 +814,83 @@ static unsigned long descriptor_loc(struct super_block *sb,
|
||||||
return ext2_group_first_block_no(sb, bg) + ext2_bg_has_super(sb, bg);
|
return ext2_group_first_block_no(sb, bg) + ext2_bg_has_super(sb, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
/*
|
||||||
|
* Set all mount options either from defaults on disk, or from parsed
|
||||||
|
* options. Parsed/specified options override on-disk defaults.
|
||||||
|
*/
|
||||||
|
static void ext2_set_options(struct fs_context *fc, struct ext2_sb_info *sbi)
|
||||||
{
|
{
|
||||||
|
struct ext2_fs_context *ctx = fc->fs_private;
|
||||||
|
struct ext2_super_block *es = sbi->s_es;
|
||||||
|
unsigned long def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
|
||||||
|
|
||||||
|
/* Copy parsed mount options to sbi */
|
||||||
|
sbi->s_mount_opt = ctx->vals_s_mount_opt;
|
||||||
|
|
||||||
|
/* Use in-superblock defaults only if not specified during parsing */
|
||||||
|
if (!ctx_parsed_mount_opt(ctx, EXT2_MOUNT_DEBUG) &&
|
||||||
|
def_mount_opts & EXT2_DEFM_DEBUG)
|
||||||
|
set_opt(sbi->s_mount_opt, DEBUG);
|
||||||
|
|
||||||
|
if (!ctx_parsed_mount_opt(ctx, EXT2_MOUNT_GRPID) &&
|
||||||
|
def_mount_opts & EXT2_DEFM_BSDGROUPS)
|
||||||
|
set_opt(sbi->s_mount_opt, GRPID);
|
||||||
|
|
||||||
|
if (!ctx_parsed_mount_opt(ctx, EXT2_MOUNT_NO_UID32) &&
|
||||||
|
def_mount_opts & EXT2_DEFM_UID16)
|
||||||
|
set_opt(sbi->s_mount_opt, NO_UID32);
|
||||||
|
|
||||||
|
#ifdef CONFIG_EXT2_FS_XATTR
|
||||||
|
if (!ctx_parsed_mount_opt(ctx, EXT2_MOUNT_XATTR_USER) &&
|
||||||
|
def_mount_opts & EXT2_DEFM_XATTR_USER)
|
||||||
|
set_opt(sbi->s_mount_opt, XATTR_USER);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
||||||
|
if (!ctx_parsed_mount_opt(ctx, EXT2_MOUNT_POSIX_ACL) &&
|
||||||
|
def_mount_opts & EXT2_DEFM_ACL)
|
||||||
|
set_opt(sbi->s_mount_opt, POSIX_ACL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ctx_parsed_mount_opt(ctx, EXT2_MOUNT_ERRORS_MASK)) {
|
||||||
|
if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
|
||||||
|
set_opt(sbi->s_mount_opt, ERRORS_PANIC);
|
||||||
|
else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
|
||||||
|
set_opt(sbi->s_mount_opt, ERRORS_CONT);
|
||||||
|
else
|
||||||
|
set_opt(sbi->s_mount_opt, ERRORS_RO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->spec & EXT2_SPEC_s_resuid)
|
||||||
|
sbi->s_resuid = ctx->s_resuid;
|
||||||
|
else
|
||||||
|
sbi->s_resuid = make_kuid(&init_user_ns,
|
||||||
|
le16_to_cpu(es->s_def_resuid));
|
||||||
|
|
||||||
|
if (ctx->spec & EXT2_SPEC_s_resgid)
|
||||||
|
sbi->s_resgid = ctx->s_resgid;
|
||||||
|
else
|
||||||
|
sbi->s_resgid = make_kgid(&init_user_ns,
|
||||||
|
le16_to_cpu(es->s_def_resgid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ext2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||||
|
{
|
||||||
|
struct ext2_fs_context *ctx = fc->fs_private;
|
||||||
|
int silent = fc->sb_flags & SB_SILENT;
|
||||||
struct buffer_head * bh;
|
struct buffer_head * bh;
|
||||||
struct ext2_sb_info * sbi;
|
struct ext2_sb_info * sbi;
|
||||||
struct ext2_super_block * es;
|
struct ext2_super_block * es;
|
||||||
struct inode *root;
|
struct inode *root;
|
||||||
unsigned long block;
|
unsigned long block;
|
||||||
unsigned long sb_block = get_sb_block(&data);
|
unsigned long sb_block = ctx->s_sb_block;
|
||||||
unsigned long logic_sb_block;
|
unsigned long logic_sb_block;
|
||||||
unsigned long offset = 0;
|
unsigned long offset = 0;
|
||||||
unsigned long def_mount_opts;
|
|
||||||
long ret = -ENOMEM;
|
long ret = -ENOMEM;
|
||||||
int blocksize = BLOCK_SIZE;
|
int blocksize = BLOCK_SIZE;
|
||||||
int db_count;
|
int db_count;
|
||||||
int i, j;
|
int i, j;
|
||||||
__le32 features;
|
__le32 features;
|
||||||
int err;
|
int err;
|
||||||
struct ext2_mount_options opts;
|
|
||||||
|
|
||||||
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
|
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
|
||||||
if (!sbi)
|
if (!sbi)
|
||||||
|
@ -877,42 +949,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
if (sb->s_magic != EXT2_SUPER_MAGIC)
|
if (sb->s_magic != EXT2_SUPER_MAGIC)
|
||||||
goto cantfind_ext2;
|
goto cantfind_ext2;
|
||||||
|
|
||||||
opts.s_mount_opt = 0;
|
ext2_set_options(fc, sbi);
|
||||||
/* Set defaults before we parse the mount options */
|
|
||||||
def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
|
|
||||||
if (def_mount_opts & EXT2_DEFM_DEBUG)
|
|
||||||
set_opt(opts.s_mount_opt, DEBUG);
|
|
||||||
if (def_mount_opts & EXT2_DEFM_BSDGROUPS)
|
|
||||||
set_opt(opts.s_mount_opt, GRPID);
|
|
||||||
if (def_mount_opts & EXT2_DEFM_UID16)
|
|
||||||
set_opt(opts.s_mount_opt, NO_UID32);
|
|
||||||
#ifdef CONFIG_EXT2_FS_XATTR
|
|
||||||
if (def_mount_opts & EXT2_DEFM_XATTR_USER)
|
|
||||||
set_opt(opts.s_mount_opt, XATTR_USER);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
|
||||||
if (def_mount_opts & EXT2_DEFM_ACL)
|
|
||||||
set_opt(opts.s_mount_opt, POSIX_ACL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
|
|
||||||
set_opt(opts.s_mount_opt, ERRORS_PANIC);
|
|
||||||
else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
|
|
||||||
set_opt(opts.s_mount_opt, ERRORS_CONT);
|
|
||||||
else
|
|
||||||
set_opt(opts.s_mount_opt, ERRORS_RO);
|
|
||||||
|
|
||||||
opts.s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid));
|
|
||||||
opts.s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid));
|
|
||||||
|
|
||||||
set_opt(opts.s_mount_opt, RESERVATION);
|
|
||||||
|
|
||||||
if (!parse_options((char *) data, sb, &opts))
|
|
||||||
goto failed_mount;
|
|
||||||
|
|
||||||
sbi->s_mount_opt = opts.s_mount_opt;
|
|
||||||
sbi->s_resuid = opts.s_resuid;
|
|
||||||
sbi->s_resgid = opts.s_resgid;
|
|
||||||
|
|
||||||
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
|
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
|
||||||
(test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
|
(test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
|
||||||
|
@ -1324,23 +1361,21 @@ static void ext2_write_super(struct super_block *sb)
|
||||||
ext2_sync_fs(sb, 1);
|
ext2_sync_fs(sb, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext2_remount (struct super_block * sb, int * flags, char * data)
|
static int ext2_reconfigure(struct fs_context *fc)
|
||||||
{
|
{
|
||||||
|
struct ext2_fs_context *ctx = fc->fs_private;
|
||||||
|
struct super_block *sb = fc->root->d_sb;
|
||||||
struct ext2_sb_info * sbi = EXT2_SB(sb);
|
struct ext2_sb_info * sbi = EXT2_SB(sb);
|
||||||
struct ext2_super_block * es;
|
struct ext2_super_block * es;
|
||||||
struct ext2_mount_options new_opts;
|
struct ext2_mount_options new_opts;
|
||||||
|
int flags = fc->sb_flags;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
sync_filesystem(sb);
|
sync_filesystem(sb);
|
||||||
|
|
||||||
spin_lock(&sbi->s_lock);
|
new_opts.s_mount_opt = ctx->vals_s_mount_opt;
|
||||||
new_opts.s_mount_opt = sbi->s_mount_opt;
|
new_opts.s_resuid = ctx->s_resuid;
|
||||||
new_opts.s_resuid = sbi->s_resuid;
|
new_opts.s_resgid = ctx->s_resgid;
|
||||||
new_opts.s_resgid = sbi->s_resgid;
|
|
||||||
spin_unlock(&sbi->s_lock);
|
|
||||||
|
|
||||||
if (!parse_options(data, sb, &new_opts))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
spin_lock(&sbi->s_lock);
|
spin_lock(&sbi->s_lock);
|
||||||
es = sbi->s_es;
|
es = sbi->s_es;
|
||||||
|
@ -1349,9 +1384,9 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
|
||||||
"dax flag with busy inodes while remounting");
|
"dax flag with busy inodes while remounting");
|
||||||
new_opts.s_mount_opt ^= EXT2_MOUNT_DAX;
|
new_opts.s_mount_opt ^= EXT2_MOUNT_DAX;
|
||||||
}
|
}
|
||||||
if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb))
|
if ((bool)(flags & SB_RDONLY) == sb_rdonly(sb))
|
||||||
goto out_set;
|
goto out_set;
|
||||||
if (*flags & SB_RDONLY) {
|
if (flags & SB_RDONLY) {
|
||||||
if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
|
if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
|
||||||
!(sbi->s_mount_state & EXT2_VALID_FS))
|
!(sbi->s_mount_state & EXT2_VALID_FS))
|
||||||
goto out_set;
|
goto out_set;
|
||||||
|
@ -1470,10 +1505,9 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *ext2_mount(struct file_system_type *fs_type,
|
static int ext2_get_tree(struct fs_context *fc)
|
||||||
int flags, const char *dev_name, void *data)
|
|
||||||
{
|
{
|
||||||
return mount_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
|
return get_tree_bdev(fc, ext2_fill_super);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
|
@ -1556,7 +1590,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
|
||||||
}
|
}
|
||||||
lock_buffer(bh);
|
lock_buffer(bh);
|
||||||
memcpy(bh->b_data+offset, data, tocopy);
|
memcpy(bh->b_data+offset, data, tocopy);
|
||||||
flush_dcache_page(bh->b_page);
|
flush_dcache_folio(bh->b_folio);
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
|
@ -1624,12 +1658,49 @@ out:
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const struct fs_context_operations ext2_context_ops = {
|
||||||
|
.parse_param = ext2_parse_param,
|
||||||
|
.get_tree = ext2_get_tree,
|
||||||
|
.reconfigure = ext2_reconfigure,
|
||||||
|
.free = ext2_free_fc,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ext2_init_fs_context(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
struct ext2_fs_context *ctx;
|
||||||
|
|
||||||
|
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||||
|
if (!ctx)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
|
||||||
|
struct super_block *sb = fc->root->d_sb;
|
||||||
|
struct ext2_sb_info *sbi = EXT2_SB(sb);
|
||||||
|
|
||||||
|
spin_lock(&sbi->s_lock);
|
||||||
|
ctx->vals_s_mount_opt = sbi->s_mount_opt;
|
||||||
|
ctx->vals_s_flags = sb->s_flags;
|
||||||
|
ctx->s_resuid = sbi->s_resuid;
|
||||||
|
ctx->s_resgid = sbi->s_resgid;
|
||||||
|
spin_unlock(&sbi->s_lock);
|
||||||
|
} else {
|
||||||
|
ctx->s_sb_block = 1;
|
||||||
|
ctx_set_mount_opt(ctx, EXT2_MOUNT_RESERVATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
fc->fs_private = ctx;
|
||||||
|
fc->ops = &ext2_context_ops;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct file_system_type ext2_fs_type = {
|
static struct file_system_type ext2_fs_type = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "ext2",
|
.name = "ext2",
|
||||||
.mount = ext2_mount,
|
|
||||||
.kill_sb = kill_block_super,
|
.kill_sb = kill_block_super,
|
||||||
.fs_flags = FS_REQUIRES_DEV,
|
.fs_flags = FS_REQUIRES_DEV,
|
||||||
|
.init_fs_context = ext2_init_fs_context,
|
||||||
|
.parameters = ext2_param_spec,
|
||||||
};
|
};
|
||||||
MODULE_ALIAS_FS("ext2");
|
MODULE_ALIAS_FS("ext2");
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *file,
|
||||||
de = tmpde;
|
de = tmpde;
|
||||||
}
|
}
|
||||||
/* Basic sanity check, whether name doesn't exceed dir entry */
|
/* Basic sanity check, whether name doesn't exceed dir entry */
|
||||||
if (de_len < de->name_len[0] +
|
if (de_len < sizeof(struct iso_directory_record) ||
|
||||||
|
de_len < de->name_len[0] +
|
||||||
sizeof(struct iso_directory_record)) {
|
sizeof(struct iso_directory_record)) {
|
||||||
printk(KERN_NOTICE "iso9660: Corrupted directory entry"
|
printk(KERN_NOTICE "iso9660: Corrupted directory entry"
|
||||||
" in block %lu of inode %lu\n", block,
|
" in block %lu of inode %lu\n", block,
|
||||||
|
|
|
@ -810,6 +810,7 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
|
||||||
}
|
}
|
||||||
map->oflags = UDF_BLK_MAPPED;
|
map->oflags = UDF_BLK_MAPPED;
|
||||||
map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
|
map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
|
||||||
|
ret = 0;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue