Few programs, especially old ones, simply don't want to work if there isn't a POSIX-compliant setattr. Follow vfat and implement a new "quiet" option to workaround this. Signed-off-by: Park Ju Hyung <qkrwngud825@xxxxxxxxx> --- fs/exfat/exfat_fs.h | 2 ++ fs/exfat/file.c | 13 +++++++++++-- fs/exfat/super.c | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index 3aed8e22087a..66837baf42d2 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -201,6 +201,8 @@ struct exfat_mount_options { unsigned short allow_utime; /* charset for filename input/display */ char *iocharset; + /* fake return success on setattr(e.g. chmods/chowns) */ + unsigned char quiet; /* on error: continue, panic, remount-ro */ enum exfat_error_mode errors; unsigned utf8:1, /* Use of UTF-8 character set */ diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 6707f3eb09b5..2ed6be7cab15 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -295,7 +295,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) attr->ia_size > i_size_read(inode)) { error = exfat_cont_expand(inode, attr->ia_size); if (error || attr->ia_valid == ATTR_SIZE) - return error; + goto out; attr->ia_valid &= ~ATTR_SIZE; } @@ -309,8 +309,11 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) error = setattr_prepare(dentry, attr); attr->ia_valid = ia_valid; - if (error) + if (error) { + if (sbi->options.quiet) + error = 0; goto out; + } if (((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, sbi->options.fs_uid)) || @@ -322,6 +325,12 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) goto out; } + if (error) { + if (sbi->options.quiet) + error = 0; + goto out; + } + /* * We don't return -EPERM here. Yes, strange, but this is too * old behavior. diff --git a/fs/exfat/super.c b/fs/exfat/super.c index b5bf6dedbe11..030db33eed35 100644 --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -145,6 +145,8 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root) seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask); if (opts->allow_utime) seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (opts->quiet) + seq_puts(m, ",quiet"); if (opts->utf8) seq_puts(m, ",iocharset=utf8"); else if (sbi->nls_io) @@ -198,6 +200,7 @@ enum { Opt_fmask, Opt_allow_utime, Opt_charset, + Opt_quiet, Opt_errors, Opt_discard, Opt_time_offset, @@ -224,6 +227,7 @@ static const struct fs_parameter_spec exfat_parameters[] = { fsparam_u32oct("fmask", Opt_fmask), fsparam_u32oct("allow_utime", Opt_allow_utime), fsparam_string("iocharset", Opt_charset), + fsparam_flag("quiet", Opt_quiet), fsparam_enum("errors", Opt_errors, exfat_param_enums), fsparam_flag("discard", Opt_discard), fsparam_s32("time_offset", Opt_time_offset), @@ -274,6 +278,9 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) opts->iocharset = param->string; param->string = NULL; break; + case Opt_quiet: + opts->quiet = 1; + break; case Opt_errors: opts->errors = result.uint_32; break; -- 2.27.0