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 <qkrwngud...@gmail.com>
---
 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

Reply via email to