return ret;
 }
 
-/* returns the length of a struct qstr, ignoring trailing dots */
-static unsigned int exfat_striptail_len(unsigned int len, const char *name)
+/* returns the length of a struct qstr, ignoring trailing dots if necessary */
+static unsigned int exfat_striptail_len(unsigned int len, const char *name,
+                                       bool keep_last_dots)
 {
-       while (len && name[len - 1] == '.')
-               len--;
+       if (!keep_last_dots) {
+               while (len && name[len - 1] == '.')
+                       len--;
+       }
        return len;
 }
 
        struct super_block *sb = dentry->d_sb;
        struct nls_table *t = EXFAT_SB(sb)->nls_io;
        const unsigned char *name = qstr->name;
-       unsigned int len = exfat_striptail_len(qstr->len, qstr->name);
+       unsigned int len = exfat_striptail_len(qstr->len, qstr->name,
+                          EXFAT_SB(sb)->options.keep_last_dots);
        unsigned long hash = init_name_hash(dentry);
        int i, charlen;
        wchar_t c;
 {
        struct super_block *sb = dentry->d_sb;
        struct nls_table *t = EXFAT_SB(sb)->nls_io;
-       unsigned int alen = exfat_striptail_len(name->len, name->name);
-       unsigned int blen = exfat_striptail_len(len, str);
+       unsigned int alen = exfat_striptail_len(name->len, name->name,
+                               EXFAT_SB(sb)->options.keep_last_dots);
+       unsigned int blen = exfat_striptail_len(len, str,
+                               EXFAT_SB(sb)->options.keep_last_dots);
        wchar_t c1, c2;
        int charlen, i;
 
 {
        struct super_block *sb = dentry->d_sb;
        const unsigned char *name = qstr->name;
-       unsigned int len = exfat_striptail_len(qstr->len, qstr->name);
+       unsigned int len = exfat_striptail_len(qstr->len, qstr->name,
+                              EXFAT_SB(sb)->options.keep_last_dots);
        unsigned long hash = init_name_hash(dentry);
        int i, charlen;
        unicode_t u;
                const char *str, const struct qstr *name)
 {
        struct super_block *sb = dentry->d_sb;
-       unsigned int alen = exfat_striptail_len(name->len, name->name);
-       unsigned int blen = exfat_striptail_len(len, str);
+       unsigned int alen = exfat_striptail_len(name->len, name->name,
+                               EXFAT_SB(sb)->options.keep_last_dots);
+       unsigned int blen = exfat_striptail_len(len, str,
+                               EXFAT_SB(sb)->options.keep_last_dots);
+
        unicode_t u_a, u_b;
        int charlen, i;
 
        struct super_block *sb = inode->i_sb;
        struct exfat_sb_info *sbi = EXFAT_SB(sb);
        struct exfat_inode_info *ei = EXFAT_I(inode);
+       int pathlen = strlen(path);
 
-       /* strip all trailing periods */
-       namelen = exfat_striptail_len(strlen(path), path);
+       /*
+        * get the length of the pathname excluding
+        * trailing periods, if any.
+        */
+       namelen = exfat_striptail_len(pathlen, path, false);
+       if (EXFAT_SB(sb)->options.keep_last_dots) {
+               /*
+                * Do not allow the creation of files with names
+                * ending with period(s).
+                */
+               if (!lookup && (namelen < pathlen))
+                       return -EINVAL;
+               namelen = pathlen;
+       }
        if (!namelen)
                return -ENOENT;
-
-       if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
+       if (pathlen > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
                return -ENAMETOOLONG;
 
        /*
 
                seq_puts(m, ",errors=remount-ro");
        if (opts->discard)
                seq_puts(m, ",discard");
+       if (opts->keep_last_dots)
+               seq_puts(m, ",keep_last_dots");
        if (opts->time_offset)
                seq_printf(m, ",time_offset=%d", opts->time_offset);
        return 0;
        Opt_charset,
        Opt_errors,
        Opt_discard,
+       Opt_keep_last_dots,
        Opt_time_offset,
 
        /* Deprecated options */
        fsparam_string("iocharset",             Opt_charset),
        fsparam_enum("errors",                  Opt_errors, exfat_param_enums),
        fsparam_flag("discard",                 Opt_discard),
+       fsparam_flag("keep_last_dots",          Opt_keep_last_dots),
        fsparam_s32("time_offset",              Opt_time_offset),
        __fsparam(NULL, "utf8",                 Opt_utf8, fs_param_deprecated,
                  NULL),
        case Opt_discard:
                opts->discard = 1;
                break;
+       case Opt_keep_last_dots:
+               opts->keep_last_dots = 1;
+               break;
        case Opt_time_offset:
                /*
                 * Make the limit 24 just in case someone invents something