Skip to content

Commit 6f8cd03

Browse files
committed
Merge tag 'for-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat fixes from Namjae Jeon: - several bug fixes(broken mount discard option, remount failure, memory leak) - add missing MODULE_ALIAS_FS for automatically loading exfat module. - set s_time_gran and truncate atime with exfat timestamp granularity. * tag 'for-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: truncate atimes to 2s granularity exfat: properly set s_time_gran exfat: remove 'bps' mount-option exfat: Unify access to the boot sector exfat: add missing MODULE_ALIAS_FS() exfat: Fix discard support
2 parents 3cda779 + 81df1ad commit 6f8cd03

File tree

6 files changed

+45
-35
lines changed

6 files changed

+45
-35
lines changed

fs/exfat/balloc.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ static int exfat_allocate_bitmap(struct super_block *sb,
9191
}
9292
}
9393

94-
sbi->pbr_bh = NULL;
9594
return 0;
9695
}
9796

@@ -137,8 +136,6 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi)
137136
{
138137
int i;
139138

140-
brelse(sbi->pbr_bh);
141-
142139
for (i = 0; i < sbi->map_sectors; i++)
143140
__brelse(sbi->vol_amap[i]);
144141

fs/exfat/exfat_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...)
507507
__printf(3, 4) __cold;
508508
void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
509509
u8 tz, __le16 time, __le16 date, u8 time_ms);
510+
void exfat_truncate_atime(struct timespec64 *ts);
510511
void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
511512
u8 *tz, __le16 *time, __le16 *date, u8 *time_ms);
512513
unsigned short exfat_calc_chksum_2byte(void *data, int len,

fs/exfat/file.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ int exfat_getattr(const struct path *path, struct kstat *stat,
273273
struct exfat_inode_info *ei = EXFAT_I(inode);
274274

275275
generic_fillattr(inode, stat);
276+
exfat_truncate_atime(&stat->atime);
276277
stat->result_mask |= STATX_BTIME;
277278
stat->btime.tv_sec = ei->i_crtime.tv_sec;
278279
stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
@@ -339,6 +340,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
339340
}
340341

341342
setattr_copy(inode, attr);
343+
exfat_truncate_atime(&inode->i_atime);
342344
mark_inode_dirty(inode);
343345

344346
out:

fs/exfat/misc.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
8888
if (time_ms) {
8989
ts->tv_sec += time_ms / 100;
9090
ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC;
91-
}
91+
} else
92+
ts->tv_nsec = 0;
9293

9394
if (tz & EXFAT_TZ_VALID)
9495
/* Adjust timezone to UTC0. */
@@ -124,6 +125,17 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
124125
*tz = EXFAT_TZ_VALID;
125126
}
126127

128+
/*
129+
* The timestamp for access_time has double seconds granularity.
130+
* (There is no 10msIncrement field for access_time unlike create/modify_time)
131+
* atime also has only a 2-second resolution.
132+
*/
133+
void exfat_truncate_atime(struct timespec64 *ts)
134+
{
135+
ts->tv_sec = round_down(ts->tv_sec, 2);
136+
ts->tv_nsec = 0;
137+
}
138+
127139
unsigned short exfat_calc_chksum_2byte(void *data, int len,
128140
unsigned short chksum, int type)
129141
{

fs/exfat/namei.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
595595
inode_inc_iversion(inode);
596596
inode->i_mtime = inode->i_atime = inode->i_ctime =
597597
EXFAT_I(inode)->i_crtime = current_time(inode);
598+
exfat_truncate_atime(&inode->i_atime);
598599
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
599600

600601
d_instantiate(dentry, inode);
@@ -854,13 +855,15 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
854855

855856
inode_inc_iversion(dir);
856857
dir->i_mtime = dir->i_atime = current_time(dir);
858+
exfat_truncate_atime(&dir->i_atime);
857859
if (IS_DIRSYNC(dir))
858860
exfat_sync_inode(dir);
859861
else
860862
mark_inode_dirty(dir);
861863

862864
clear_nlink(inode);
863865
inode->i_mtime = inode->i_atime = current_time(inode);
866+
exfat_truncate_atime(&inode->i_atime);
864867
exfat_unhash_inode(inode);
865868
exfat_d_version_set(dentry, inode_query_iversion(dir));
866869
unlock:
@@ -903,6 +906,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
903906
inode_inc_iversion(inode);
904907
inode->i_mtime = inode->i_atime = inode->i_ctime =
905908
EXFAT_I(inode)->i_crtime = current_time(inode);
909+
exfat_truncate_atime(&inode->i_atime);
906910
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
907911

908912
d_instantiate(dentry, inode);
@@ -1019,6 +1023,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
10191023

10201024
inode_inc_iversion(dir);
10211025
dir->i_mtime = dir->i_atime = current_time(dir);
1026+
exfat_truncate_atime(&dir->i_atime);
10221027
if (IS_DIRSYNC(dir))
10231028
exfat_sync_inode(dir);
10241029
else
@@ -1027,6 +1032,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
10271032

10281033
clear_nlink(inode);
10291034
inode->i_mtime = inode->i_atime = current_time(inode);
1035+
exfat_truncate_atime(&inode->i_atime);
10301036
exfat_unhash_inode(inode);
10311037
exfat_d_version_set(dentry, inode_query_iversion(dir));
10321038
unlock:
@@ -1387,6 +1393,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
13871393
inode_inc_iversion(new_dir);
13881394
new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
13891395
EXFAT_I(new_dir)->i_crtime = current_time(new_dir);
1396+
exfat_truncate_atime(&new_dir->i_atime);
13901397
if (IS_DIRSYNC(new_dir))
13911398
exfat_sync_inode(new_dir);
13921399
else

fs/exfat/super.c

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static void exfat_put_super(struct super_block *sb)
4949
sync_blockdev(sb->s_bdev);
5050
exfat_set_vol_flags(sb, VOL_CLEAN);
5151
exfat_free_bitmap(sbi);
52+
brelse(sbi->pbr_bh);
5253
mutex_unlock(&sbi->s_lock);
5354

5455
call_rcu(&sbi->rcu, exfat_delayed_free);
@@ -100,7 +101,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
100101
int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
101102
{
102103
struct exfat_sb_info *sbi = EXFAT_SB(sb);
103-
struct pbr64 *bpb;
104+
struct pbr64 *bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
104105
bool sync = 0;
105106

106107
/* flags are not changed */
@@ -115,15 +116,6 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
115116
if (sb_rdonly(sb))
116117
return 0;
117118

118-
if (!sbi->pbr_bh) {
119-
sbi->pbr_bh = sb_bread(sb, 0);
120-
if (!sbi->pbr_bh) {
121-
exfat_msg(sb, KERN_ERR, "failed to read boot sector");
122-
return -ENOMEM;
123-
}
124-
}
125-
126-
bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
127119
bpb->bsx.vol_flags = cpu_to_le16(new_flag);
128120

129121
if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh))
@@ -159,7 +151,6 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
159151
seq_puts(m, ",iocharset=utf8");
160152
else if (sbi->nls_io)
161153
seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
162-
seq_printf(m, ",bps=%ld", sb->s_blocksize);
163154
if (opts->errors == EXFAT_ERRORS_CONT)
164155
seq_puts(m, ",errors=continue");
165156
else if (opts->errors == EXFAT_ERRORS_PANIC)
@@ -351,14 +342,15 @@ static int exfat_read_root(struct inode *inode)
351342
exfat_save_attr(inode, ATTR_SUBDIR);
352343
inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
353344
current_time(inode);
345+
exfat_truncate_atime(&inode->i_atime);
354346
exfat_cache_init_inode(inode);
355347
return 0;
356348
}
357349

358-
static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
359-
struct buffer_head **prev_bh)
350+
static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb)
360351
{
361-
struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data;
352+
struct exfat_sb_info *sbi = EXFAT_SB(sb);
353+
struct pbr *p_pbr = (struct pbr *) (sbi->pbr_bh)->b_data;
362354
unsigned short logical_sect = 0;
363355

364356
logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits;
@@ -378,26 +370,23 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
378370
}
379371

380372
if (logical_sect > sb->s_blocksize) {
381-
struct buffer_head *bh = NULL;
382-
383-
__brelse(*prev_bh);
384-
*prev_bh = NULL;
373+
brelse(sbi->pbr_bh);
374+
sbi->pbr_bh = NULL;
385375

386376
if (!sb_set_blocksize(sb, logical_sect)) {
387377
exfat_msg(sb, KERN_ERR,
388378
"unable to set blocksize %u", logical_sect);
389379
return NULL;
390380
}
391-
bh = sb_bread(sb, 0);
392-
if (!bh) {
381+
sbi->pbr_bh = sb_bread(sb, 0);
382+
if (!sbi->pbr_bh) {
393383
exfat_msg(sb, KERN_ERR,
394384
"unable to read boot sector (logical sector size = %lu)",
395385
sb->s_blocksize);
396386
return NULL;
397387
}
398388

399-
*prev_bh = bh;
400-
p_pbr = (struct pbr *) bh->b_data;
389+
p_pbr = (struct pbr *)sbi->pbr_bh->b_data;
401390
}
402391
return p_pbr;
403392
}
@@ -408,21 +397,20 @@ static int __exfat_fill_super(struct super_block *sb)
408397
int ret;
409398
struct pbr *p_pbr;
410399
struct pbr64 *p_bpb;
411-
struct buffer_head *bh;
412400
struct exfat_sb_info *sbi = EXFAT_SB(sb);
413401

414402
/* set block size to read super block */
415403
sb_min_blocksize(sb, 512);
416404

417405
/* read boot sector */
418-
bh = sb_bread(sb, 0);
419-
if (!bh) {
406+
sbi->pbr_bh = sb_bread(sb, 0);
407+
if (!sbi->pbr_bh) {
420408
exfat_msg(sb, KERN_ERR, "unable to read boot sector");
421409
return -EIO;
422410
}
423411

424412
/* PRB is read */
425-
p_pbr = (struct pbr *)bh->b_data;
413+
p_pbr = (struct pbr *)sbi->pbr_bh->b_data;
426414

427415
/* check the validity of PBR */
428416
if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) {
@@ -433,7 +421,7 @@ static int __exfat_fill_super(struct super_block *sb)
433421

434422

435423
/* check logical sector size */
436-
p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh);
424+
p_pbr = exfat_read_pbr_with_logical_sector(sb);
437425
if (!p_pbr) {
438426
ret = -EIO;
439427
goto free_bh;
@@ -514,7 +502,7 @@ static int __exfat_fill_super(struct super_block *sb)
514502
free_upcase_table:
515503
exfat_free_upcase_table(sbi);
516504
free_bh:
517-
brelse(bh);
505+
brelse(sbi->pbr_bh);
518506
return ret;
519507
}
520508

@@ -531,17 +519,18 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
531519
if (opts->discard) {
532520
struct request_queue *q = bdev_get_queue(sb->s_bdev);
533521

534-
if (!blk_queue_discard(q))
522+
if (!blk_queue_discard(q)) {
535523
exfat_msg(sb, KERN_WARNING,
536524
"mounting with \"discard\" option, but the device does not support discard");
537-
opts->discard = 0;
525+
opts->discard = 0;
526+
}
538527
}
539528

540529
sb->s_flags |= SB_NODIRATIME;
541530
sb->s_magic = EXFAT_SUPER_MAGIC;
542531
sb->s_op = &exfat_sops;
543532

544-
sb->s_time_gran = 1;
533+
sb->s_time_gran = 10 * NSEC_PER_MSEC;
545534
sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;
546535
sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;
547536

@@ -605,6 +594,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
605594
free_table:
606595
exfat_free_upcase_table(sbi);
607596
exfat_free_bitmap(sbi);
597+
brelse(sbi->pbr_bh);
608598

609599
check_nls_io:
610600
unload_nls(sbi->nls_io);
@@ -717,6 +707,7 @@ static void __exit exit_exfat_fs(void)
717707
module_init(init_exfat_fs);
718708
module_exit(exit_exfat_fs);
719709

710+
MODULE_ALIAS_FS("exfat");
720711
MODULE_LICENSE("GPL");
721712
MODULE_DESCRIPTION("exFAT filesystem support");
722713
MODULE_AUTHOR("Samsung Electronics Co., Ltd.");

0 commit comments

Comments
 (0)