mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
Description for this pull request:
- Add keep_last_dots mount option to allow access to paths with trailing dots. - Avoid repetitive volume dirty bit set/clear to improve storage life time. -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEE6NzKS6Uv/XAAGHgyZwv7A1FEIQgFAmJGW7IWHGxpbmtpbmpl b25Aa2VybmVsLm9yZwAKCRBnC/sDUUQhCDp3D/49MeePwrzH8Aon+0MMWH2C23aZ UWkHQhedSmnscyb3xbaqT6UJHk3CbIdgMqJpJd1zwRs7U9o37zPQy8ma1DcOPWA9 Bn1NUTdj/RWye+2t/6YT44xODsG5sRrzKeG2AcenivVxCW1+Xl9YBGk9J8XXIxm0 IQTsswGuLfDdtGoHWXiSRPTatTxPsJospZER94nhGEiPxyOgVuLHUWxWxAUMXY8w RL9B/t7AlRFSk8HXW5aL5tNsd6OBeLybBN51lToPGPRq1qd9Aarlp0mlwMnaie2z 1AoTXzExd1IBglfcKhppTIUqAioeIdTOkfSudaLPAoTc6PDjJAxEOQJx2NfBNimC JM209+MtJh5nTiNmpfGxT64vHkR70Kf1+Vdasv/iFfHQlhIbGJ+necIPHXUgA20Y 0iZ9bksiYGNoHFc5wKQ1wBmMxsKNLVz0GYJJez/pw+JfwCGztiSlxQWDkFxj5qNW 2L/9YRJLVpI4vmNTAFM3sHaDaYkXWfAtgWhlS0c95SVVUsvR4vu7UYTOKYlsc1mC T0ABV8TJIXQwlD6HzNGpU0OKD6/ddA81GrIdkoRuzT9KGJDGA1oz8ehHO+Hs796K ivRkARLIVwoQZAoZJR17tYnMd4GnSC/qr70HqCBFnFeNTOkl3fpzjEzxoIXL+A9t KbPtJlbxQao7DKLo6g== =PoqS -----END PGP SIGNATURE----- Merge tag 'exfat-for-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat Pull exfat updates from Namjae Jeon: - Add keep_last_dots mount option to allow access to paths with trailing dots - Avoid repetitive volume dirty bit set/clear to improve storage life time * tag 'exfat-for-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: do not clear VolumeDirty in writeback exfat: allow access to paths with trailing dots
This commit is contained in:
commit
ec251f3e18
@ -203,7 +203,8 @@ struct exfat_mount_options {
|
|||||||
/* on error: continue, panic, remount-ro */
|
/* on error: continue, panic, remount-ro */
|
||||||
enum exfat_error_mode errors;
|
enum exfat_error_mode errors;
|
||||||
unsigned utf8:1, /* Use of UTF-8 character set */
|
unsigned utf8:1, /* Use of UTF-8 character set */
|
||||||
discard:1; /* Issue discard requests on deletions */
|
discard:1, /* Issue discard requests on deletions */
|
||||||
|
keep_last_dots:1; /* Keep trailing periods in paths */
|
||||||
int time_offset; /* Offset of timestamps from UTC (in minutes) */
|
int time_offset; /* Offset of timestamps from UTC (in minutes) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,8 +218,6 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
|
|||||||
if (exfat_free_cluster(inode, &clu))
|
if (exfat_free_cluster(inode, &clu))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
exfat_clear_volume_dirty(sb);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,11 +65,14 @@ static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns the length of a struct qstr, ignoring trailing dots */
|
/* returns the length of a struct qstr, ignoring trailing dots if necessary */
|
||||||
static unsigned int exfat_striptail_len(unsigned int len, const char *name)
|
static unsigned int exfat_striptail_len(unsigned int len, const char *name,
|
||||||
|
bool keep_last_dots)
|
||||||
{
|
{
|
||||||
while (len && name[len - 1] == '.')
|
if (!keep_last_dots) {
|
||||||
len--;
|
while (len && name[len - 1] == '.')
|
||||||
|
len--;
|
||||||
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +86,8 @@ static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr)
|
|||||||
struct super_block *sb = dentry->d_sb;
|
struct super_block *sb = dentry->d_sb;
|
||||||
struct nls_table *t = EXFAT_SB(sb)->nls_io;
|
struct nls_table *t = EXFAT_SB(sb)->nls_io;
|
||||||
const unsigned char *name = qstr->name;
|
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);
|
unsigned long hash = init_name_hash(dentry);
|
||||||
int i, charlen;
|
int i, charlen;
|
||||||
wchar_t c;
|
wchar_t c;
|
||||||
@ -104,8 +108,10 @@ static int exfat_d_cmp(const struct dentry *dentry, unsigned int len,
|
|||||||
{
|
{
|
||||||
struct super_block *sb = dentry->d_sb;
|
struct super_block *sb = dentry->d_sb;
|
||||||
struct nls_table *t = EXFAT_SB(sb)->nls_io;
|
struct nls_table *t = EXFAT_SB(sb)->nls_io;
|
||||||
unsigned int alen = exfat_striptail_len(name->len, name->name);
|
unsigned int alen = exfat_striptail_len(name->len, name->name,
|
||||||
unsigned int blen = exfat_striptail_len(len, str);
|
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;
|
wchar_t c1, c2;
|
||||||
int charlen, i;
|
int charlen, i;
|
||||||
|
|
||||||
@ -136,7 +142,8 @@ static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr)
|
|||||||
{
|
{
|
||||||
struct super_block *sb = dentry->d_sb;
|
struct super_block *sb = dentry->d_sb;
|
||||||
const unsigned char *name = qstr->name;
|
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);
|
unsigned long hash = init_name_hash(dentry);
|
||||||
int i, charlen;
|
int i, charlen;
|
||||||
unicode_t u;
|
unicode_t u;
|
||||||
@ -161,8 +168,11 @@ static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len,
|
|||||||
const char *str, const struct qstr *name)
|
const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
struct super_block *sb = dentry->d_sb;
|
struct super_block *sb = dentry->d_sb;
|
||||||
unsigned int alen = exfat_striptail_len(name->len, name->name);
|
unsigned int alen = exfat_striptail_len(name->len, name->name,
|
||||||
unsigned int blen = exfat_striptail_len(len, str);
|
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;
|
unicode_t u_a, u_b;
|
||||||
int charlen, i;
|
int charlen, i;
|
||||||
|
|
||||||
@ -416,13 +426,25 @@ static int __exfat_resolve_path(struct inode *inode, const unsigned char *path,
|
|||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
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)
|
if (!namelen)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
if (pathlen > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
|
||||||
if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
|
|
||||||
return -ENAMETOOLONG;
|
return -ENAMETOOLONG;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -554,7 +576,6 @@ static int exfat_create(struct user_namespace *mnt_userns, struct inode *dir,
|
|||||||
exfat_set_volume_dirty(sb);
|
exfat_set_volume_dirty(sb);
|
||||||
err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE,
|
err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE,
|
||||||
&info);
|
&info);
|
||||||
exfat_clear_volume_dirty(sb);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
@ -812,7 +833,6 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
|
|||||||
|
|
||||||
/* This doesn't modify ei */
|
/* This doesn't modify ei */
|
||||||
ei->dir.dir = DIR_DELETED;
|
ei->dir.dir = DIR_DELETED;
|
||||||
exfat_clear_volume_dirty(sb);
|
|
||||||
|
|
||||||
inode_inc_iversion(dir);
|
inode_inc_iversion(dir);
|
||||||
dir->i_mtime = dir->i_atime = current_time(dir);
|
dir->i_mtime = dir->i_atime = current_time(dir);
|
||||||
@ -846,7 +866,6 @@ static int exfat_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
|
|||||||
exfat_set_volume_dirty(sb);
|
exfat_set_volume_dirty(sb);
|
||||||
err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR,
|
err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR,
|
||||||
&info);
|
&info);
|
||||||
exfat_clear_volume_dirty(sb);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
@ -976,7 +995,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
ei->dir.dir = DIR_DELETED;
|
ei->dir.dir = DIR_DELETED;
|
||||||
exfat_clear_volume_dirty(sb);
|
|
||||||
|
|
||||||
inode_inc_iversion(dir);
|
inode_inc_iversion(dir);
|
||||||
dir->i_mtime = dir->i_atime = current_time(dir);
|
dir->i_mtime = dir->i_atime = current_time(dir);
|
||||||
@ -1311,7 +1329,6 @@ del_out:
|
|||||||
*/
|
*/
|
||||||
new_ei->dir.dir = DIR_DELETED;
|
new_ei->dir.dir = DIR_DELETED;
|
||||||
}
|
}
|
||||||
exfat_clear_volume_dirty(sb);
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,6 @@ static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flags)
|
|||||||
{
|
{
|
||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data;
|
struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data;
|
||||||
bool sync;
|
|
||||||
|
|
||||||
/* retain persistent-flags */
|
/* retain persistent-flags */
|
||||||
new_flags |= sbi->vol_flags_persistent;
|
new_flags |= sbi->vol_flags_persistent;
|
||||||
@ -119,16 +118,11 @@ static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flags)
|
|||||||
|
|
||||||
p_boot->vol_flags = cpu_to_le16(new_flags);
|
p_boot->vol_flags = cpu_to_le16(new_flags);
|
||||||
|
|
||||||
if ((new_flags & VOLUME_DIRTY) && !buffer_dirty(sbi->boot_bh))
|
|
||||||
sync = true;
|
|
||||||
else
|
|
||||||
sync = false;
|
|
||||||
|
|
||||||
set_buffer_uptodate(sbi->boot_bh);
|
set_buffer_uptodate(sbi->boot_bh);
|
||||||
mark_buffer_dirty(sbi->boot_bh);
|
mark_buffer_dirty(sbi->boot_bh);
|
||||||
|
|
||||||
if (sync)
|
__sync_dirty_buffer(sbi->boot_bh, REQ_SYNC | REQ_FUA | REQ_PREFLUSH);
|
||||||
sync_dirty_buffer(sbi->boot_bh);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +168,8 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
|
|||||||
seq_puts(m, ",errors=remount-ro");
|
seq_puts(m, ",errors=remount-ro");
|
||||||
if (opts->discard)
|
if (opts->discard)
|
||||||
seq_puts(m, ",discard");
|
seq_puts(m, ",discard");
|
||||||
|
if (opts->keep_last_dots)
|
||||||
|
seq_puts(m, ",keep_last_dots");
|
||||||
if (opts->time_offset)
|
if (opts->time_offset)
|
||||||
seq_printf(m, ",time_offset=%d", opts->time_offset);
|
seq_printf(m, ",time_offset=%d", opts->time_offset);
|
||||||
return 0;
|
return 0;
|
||||||
@ -217,6 +213,7 @@ enum {
|
|||||||
Opt_charset,
|
Opt_charset,
|
||||||
Opt_errors,
|
Opt_errors,
|
||||||
Opt_discard,
|
Opt_discard,
|
||||||
|
Opt_keep_last_dots,
|
||||||
Opt_time_offset,
|
Opt_time_offset,
|
||||||
|
|
||||||
/* Deprecated options */
|
/* Deprecated options */
|
||||||
@ -243,6 +240,7 @@ static const struct fs_parameter_spec exfat_parameters[] = {
|
|||||||
fsparam_string("iocharset", Opt_charset),
|
fsparam_string("iocharset", Opt_charset),
|
||||||
fsparam_enum("errors", Opt_errors, exfat_param_enums),
|
fsparam_enum("errors", Opt_errors, exfat_param_enums),
|
||||||
fsparam_flag("discard", Opt_discard),
|
fsparam_flag("discard", Opt_discard),
|
||||||
|
fsparam_flag("keep_last_dots", Opt_keep_last_dots),
|
||||||
fsparam_s32("time_offset", Opt_time_offset),
|
fsparam_s32("time_offset", Opt_time_offset),
|
||||||
__fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated,
|
__fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated,
|
||||||
NULL),
|
NULL),
|
||||||
@ -297,6 +295,9 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
case Opt_discard:
|
case Opt_discard:
|
||||||
opts->discard = 1;
|
opts->discard = 1;
|
||||||
break;
|
break;
|
||||||
|
case Opt_keep_last_dots:
|
||||||
|
opts->keep_last_dots = 1;
|
||||||
|
break;
|
||||||
case Opt_time_offset:
|
case Opt_time_offset:
|
||||||
/*
|
/*
|
||||||
* Make the limit 24 just in case someone invents something
|
* Make the limit 24 just in case someone invents something
|
||||||
|
Loading…
Reference in New Issue
Block a user