History

Merge tag 'exfat-for-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat

Pull exfat updates from Namjae Jeon: - Replace the internal table lookup algorithm with the hweight library and ffs of the bitops library. - Handle the two types of stream entry, valid data size (has been written) and data size separately. It improves compatibility with two differently sized files created on Windows. * tag 'exfat-for-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: do not zero the extended part exfat: change to get file size from DataLength exfat: using ffs instead of internal logic exfat: using hweight instead of internal logic

Linus Torvalds committed 2 years ago

Commit 052d5342 parents f16ab99 f55c0965 files · +335 −92Browse files

Unified · Split

5 files
  1. fs/exfat/balloc.c +35 −52
  2. fs/exfat/exfat_fs.h +3 −2
  3. fs/exfat/file.c +172 −21
  4. fs/exfat/inode.c +119 −17
  5. fs/exfat/namei.c +6 −0
fs/exfat/balloc.c+35−52
@@ -5,42 +5,23 @@ · 4 unmodified lines
5 5
6#include <linux/blkdev.h>6#include <linux/blkdev.h>
7#include <linux/slab.h>7#include <linux/slab.h>
8#include <linux/bitmap.h>
8#include <linux/buffer_head.h>9#include <linux/buffer_head.h>
9 10
10#include "exfat_raw.h"11#include "exfat_raw.h"
11#include "exfat_fs.h"12#include "exfat_fs.h"
12 13
13static const unsigned char free_bit[] = {14#if BITS_PER_LONG == 32
14 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/15#define __le_long __le32
15 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/16#define lel_to_cpu(A) le32_to_cpu(A)
16 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/17#define cpu_to_lel(A) cpu_to_le32(A)
17 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/18#elif BITS_PER_LONG == 64
18 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/19#define __le_long __le64
19 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/20#define lel_to_cpu(A) le64_to_cpu(A)
20 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/21#define cpu_to_lel(A) cpu_to_le64(A)
21 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/22#else
22 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/23#error "BITS_PER_LONG not 32 or 64"
23 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/24#endif
24 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/
25 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/
26 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/
27};
28
29static const unsigned char used_bit[] = {
30 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/
31 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/
32 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/
33 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/
34 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/
35 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/
36 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/
37 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/
38 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/
39 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/
40 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/
41 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/
42 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/
43};
44 25
45/*26/*
46 * Allocation Bitmap Management Functions27 * Allocation Bitmap Management Functions
@@ -200,32 +181,35 @@ unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu) · 153 unmodified lines
200{181{
201 unsigned int i, map_i, map_b, ent_idx;182 unsigned int i, map_i, map_b, ent_idx;
202 unsigned int clu_base, clu_free;183 unsigned int clu_base, clu_free;
203 unsigned char k, clu_mask;184 unsigned long clu_bits, clu_mask;
204 struct exfat_sb_info *sbi = EXFAT_SB(sb);185 struct exfat_sb_info *sbi = EXFAT_SB(sb);
186 __le_long bitval;
205 187
206 WARN_ON(clu < EXFAT_FIRST_CLUSTER);188 WARN_ON(clu < EXFAT_FIRST_CLUSTER);
207 ent_idx = CLUSTER_TO_BITMAP_ENT(clu);189 ent_idx = ALIGN_DOWN(CLUSTER_TO_BITMAP_ENT(clu), BITS_PER_LONG);
208 clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx & ~(BITS_PER_BYTE_MASK));190 clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx);
209 clu_mask = IGNORED_BITS_REMAINED(clu, clu_base);191 clu_mask = IGNORED_BITS_REMAINED(clu, clu_base);
210 192
211 map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);193 map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
212 map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx);194 map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx);
213 195
214 for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters;196 for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters;
215 i += BITS_PER_BYTE) {197 i += BITS_PER_LONG) {
216 k = *(sbi->vol_amap[map_i]->b_data + map_b);198 bitval = *(__le_long *)(sbi->vol_amap[map_i]->b_data + map_b);
217 if (clu_mask > 0) {199 if (clu_mask > 0) {
218 k |= clu_mask;200 bitval |= cpu_to_lel(clu_mask);
219 clu_mask = 0;201 clu_mask = 0;
220 }202 }
221 if (k < 0xFF) {203 if (lel_to_cpu(bitval) != ULONG_MAX) {
222 clu_free = clu_base + free_bit[k];204 clu_bits = lel_to_cpu(bitval);
205 clu_free = clu_base + ffz(clu_bits);
223 if (clu_free < sbi->num_clusters)206 if (clu_free < sbi->num_clusters)
224 return clu_free;207 return clu_free;
225 }208 }
226 clu_base += BITS_PER_BYTE;209 clu_base += BITS_PER_LONG;
210 map_b += sizeof(long);
227 211
228 if (++map_b >= sb->s_blocksize ||212 if (map_b >= sb->s_blocksize ||
229 clu_base >= sbi->num_clusters) {213 clu_base >= sbi->num_clusters) {
230 if (++map_i >= sbi->map_sectors) {214 if (++map_i >= sbi->map_sectors) {
231 clu_base = EXFAT_FIRST_CLUSTER;215 clu_base = EXFAT_FIRST_CLUSTER;
@@ -244,25 +228,24 @@ int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count) · 12 unmodified lines
244 unsigned int count = 0;228 unsigned int count = 0;
245 unsigned int i, map_i = 0, map_b = 0;229 unsigned int i, map_i = 0, map_b = 0;
246 unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi);230 unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi);
247 unsigned int last_mask = total_clus & BITS_PER_BYTE_MASK;231 unsigned int last_mask = total_clus & (BITS_PER_LONG - 1);
248 unsigned char clu_bits;232 unsigned long *bitmap, clu_bits;
249 const unsigned char last_bit_mask[] = {0, 0b00000001, 0b00000011,
250 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111};
251 233
252 total_clus &= ~last_mask;234 total_clus &= ~last_mask;
253 for (i = 0; i < total_clus; i += BITS_PER_BYTE) {235 for (i = 0; i < total_clus; i += BITS_PER_LONG) {
254 clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);236 bitmap = (void *)(sbi->vol_amap[map_i]->b_data + map_b);
255 count += used_bit[clu_bits];237 count += hweight_long(*bitmap);
256 if (++map_b >= (unsigned int)sb->s_blocksize) {238 map_b += sizeof(long);
239 if (map_b >= (unsigned int)sb->s_blocksize) {
257 map_i++;240 map_i++;
258 map_b = 0;241 map_b = 0;
259 }242 }
260 }243 }
261 244
262 if (last_mask) {245 if (last_mask) {
263 clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);246 bitmap = (void *)(sbi->vol_amap[map_i]->b_data + map_b);
264 clu_bits &= last_bit_mask[last_mask];247 clu_bits = lel_to_cpu(*(__le_long *)bitmap);
265 count += used_bit[clu_bits];248 count += hweight_long(clu_bits & BITMAP_LAST_WORD_MASK(last_mask));
266 }249 }
267 250
268 *ret_count = count;251 *ret_count = count;
fs/exfat/exfat_fs.h+3−2
@@ -135,8 +135,7 @@ enum { · 134 unmodified lines
135#define BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent) (ent & BITS_PER_SECTOR_MASK(sb))135#define BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent) (ent & BITS_PER_SECTOR_MASK(sb))
136#define BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent) \136#define BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent) \
137 ((ent / BITS_PER_BYTE) & ((sb)->s_blocksize - 1))137 ((ent / BITS_PER_BYTE) & ((sb)->s_blocksize - 1))
138#define BITS_PER_BYTE_MASK 0x7138#define IGNORED_BITS_REMAINED(clu, clu_base) ((1UL << ((clu) - (clu_base))) - 1)
139#define IGNORED_BITS_REMAINED(clu, clu_base) ((1 << ((clu) - (clu_base))) - 1)
140 139
141#define ES_ENTRY_NUM(name_len) (ES_IDX_LAST_FILENAME(name_len) + 1)140#define ES_ENTRY_NUM(name_len) (ES_IDX_LAST_FILENAME(name_len) + 1)
142/* 19 entries = 1 file entry + 1 stream entry + 17 filename entries */141/* 19 entries = 1 file entry + 1 stream entry + 17 filename entries */
@@ -208,6 +207,7 @@ struct exfat_dir_entry { · 65 unmodified lines
208 unsigned char flags;207 unsigned char flags;
209 unsigned short attr;208 unsigned short attr;
210 loff_t size;209 loff_t size;
210 loff_t valid_size;
211 unsigned int num_subdirs;211 unsigned int num_subdirs;
212 struct timespec64 atime;212 struct timespec64 atime;
213 struct timespec64 mtime;213 struct timespec64 mtime;
@@ -317,6 +317,7 @@ struct exfat_inode_info { · 103 unmodified lines
317 loff_t i_size_aligned;317 loff_t i_size_aligned;
318 /* on-disk position of directory entry or 0 */318 /* on-disk position of directory entry or 0 */
319 loff_t i_pos;319 loff_t i_pos;
320 loff_t valid_size;
320 /* hash by i_location */321 /* hash by i_location */
321 struct hlist_node i_hash_fat;322 struct hlist_node i_hash_fat;
322 /* protect bmap against truncate */323 /* protect bmap against truncate */
fs/exfat/file.c+172−21
@@ -11,37 +11,76 @@ · 10 unmodified lines
11#include <linux/fsnotify.h>11#include <linux/fsnotify.h>
12#include <linux/security.h>12#include <linux/security.h>
13#include <linux/msdos_fs.h>13#include <linux/msdos_fs.h>
14#include <linux/writeback.h>
14 15
15#include "exfat_raw.h"16#include "exfat_raw.h"
16#include "exfat_fs.h"17#include "exfat_fs.h"
17 18
18static int exfat_cont_expand(struct inode *inode, loff_t size)19static int exfat_cont_expand(struct inode *inode, loff_t size)
19{20{
20 struct address_space *mapping = inode->i_mapping;21 int ret;
21 loff_t start = i_size_read(inode), count = size - i_size_read(inode);22 unsigned int num_clusters, new_num_clusters, last_clu;
22 int err, err2;23 struct exfat_inode_info *ei = EXFAT_I(inode);
24 struct super_block *sb = inode->i_sb;
25 struct exfat_sb_info *sbi = EXFAT_SB(sb);
26 struct exfat_chain clu;
23 27
24 err = generic_cont_expand_simple(inode, size);28 ret = inode_newsize_ok(inode, size);
25 if (err)29 if (ret)
26 return err;30 return ret;
31
32 num_clusters = EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi);
33 new_num_clusters = EXFAT_B_TO_CLU_ROUND_UP(size, sbi);
34
35 if (new_num_clusters == num_clusters)
36 goto out;
37
38 exfat_chain_set(&clu, ei->start_clu, num_clusters, ei->flags);
39 ret = exfat_find_last_cluster(sb, &clu, &last_clu);
40 if (ret)
41 return ret;
42
43 clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
44 EXFAT_EOF_CLUSTER : last_clu + 1;
45 clu.size = 0;
46 clu.flags = ei->flags;
47
48 ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters,
49 &clu, IS_DIRSYNC(inode));
50 if (ret)
51 return ret;
52
53 /* Append new clusters to chain */
54 if (clu.flags != ei->flags) {
55 exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters);
56 ei->flags = ALLOC_FAT_CHAIN;
57 }
58 if (clu.flags == ALLOC_FAT_CHAIN)
59 if (exfat_ent_set(sb, last_clu, clu.dir))
60 goto free_clu;
27 61
62 if (num_clusters == 0)
63 ei->start_clu = clu.dir;
64
65out:
28 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));66 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
29 mark_inode_dirty(inode);67 /* Expanded range not zeroed, do not update valid_size */
68 i_size_write(inode, size);
30 69
31 if (!IS_SYNC(inode))70 ei->i_size_aligned = round_up(size, sb->s_blocksize);
32 return 0;71 ei->i_size_ondisk = ei->i_size_aligned;
72 inode->i_blocks = round_up(size, sbi->cluster_size) >> 9;
33 73
34 err = filemap_fdatawrite_range(mapping, start, start + count - 1);74 if (IS_DIRSYNC(inode))
35 err2 = sync_mapping_buffers(mapping);75 return write_inode_now(inode, 1);
36 if (!err)76
37 err = err2;77 mark_inode_dirty(inode);
38 err2 = write_inode_now(inode, 1);
39 if (!err)
40 err = err2;
41 if (err)
42 return err;
43 78
44 return filemap_fdatawait_range(mapping, start, start + count - 1);79 return 0;
80
81free_clu:
82 exfat_free_cluster(inode, &clu);
83 return -EIO;
45}84}
46 85
47static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)86static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
@@ -146,6 +185,9 @@ int __exfat_truncate(struct inode *inode) · 98 unmodified lines
146 ei->start_clu = EXFAT_EOF_CLUSTER;185 ei->start_clu = EXFAT_EOF_CLUSTER;
147 }186 }
148 187
188 if (i_size_read(inode) < ei->valid_size)
189 ei->valid_size = i_size_read(inode);
190
149 if (ei->type == TYPE_FILE)191 if (ei->type == TYPE_FILE)
150 ei->attr |= EXFAT_ATTR_ARCHIVE;192 ei->attr |= EXFAT_ATTR_ARCHIVE;
151 193
@@ -474,15 +516,124 @@ int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) · 322 unmodified lines
474 return blkdev_issue_flush(inode->i_sb->s_bdev);516 return blkdev_issue_flush(inode->i_sb->s_bdev);
475}517}
476 518
519static int exfat_file_zeroed_range(struct file *file, loff_t start, loff_t end)
520{
521 int err;
522 struct inode *inode = file_inode(file);
523 struct address_space *mapping = inode->i_mapping;
524 const struct address_space_operations *ops = mapping->a_ops;
525
526 while (start < end) {
527 u32 zerofrom, len;
528 struct page *page = NULL;
529
530 zerofrom = start & (PAGE_SIZE - 1);
531 len = PAGE_SIZE - zerofrom;
532 if (start + len > end)
533 len = end - start;
534
535 err = ops->write_begin(file, mapping, start, len, &page, NULL);
536 if (err)
537 goto out;
538
539 zero_user_segment(page, zerofrom, zerofrom + len);
540
541 err = ops->write_end(file, mapping, start, len, len, page, NULL);
542 if (err < 0)
543 goto out;
544 start += len;
545
546 balance_dirty_pages_ratelimited(mapping);
547 cond_resched();
548 }
549
550out:
551 return err;
552}
553
554static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
555{
556 ssize_t ret;
557 struct file *file = iocb->ki_filp;
558 struct inode *inode = file_inode(file);
559 struct exfat_inode_info *ei = EXFAT_I(inode);
560 loff_t pos = iocb->ki_pos;
561 loff_t valid_size;
562
563 inode_lock(inode);
564
565 valid_size = ei->valid_size;
566
567 ret = generic_write_checks(iocb, iter);
568 if (ret < 0)
569 goto unlock;
570
571 if (pos > valid_size) {
572 ret = exfat_file_zeroed_range(file, valid_size, pos);
573 if (ret < 0 && ret != -ENOSPC) {
574 exfat_err(inode->i_sb,
575 "write: fail to zero from %llu to %llu(%zd)",
576 valid_size, pos, ret);
577 }
578 if (ret < 0)
579 goto unlock;
580 }
581
582 ret = __generic_file_write_iter(iocb, iter);
583 if (ret < 0)
584 goto unlock;
585
586 inode_unlock(inode);
587
588 if (pos > valid_size)
589 pos = valid_size;
590
591 if (iocb_is_dsync(iocb) && iocb->ki_pos > pos) {
592 ssize_t err = vfs_fsync_range(file, pos, iocb->ki_pos - 1,
593 iocb->ki_flags & IOCB_SYNC);
594 if (err < 0)
595 return err;
596 }
597
598 return ret;
599
600unlock:
601 inode_unlock(inode);
602
603 return ret;
604}
605
606static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma)
607{
608 int ret;
609 struct inode *inode = file_inode(file);
610 struct exfat_inode_info *ei = EXFAT_I(inode);
611 loff_t start = ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
612 loff_t end = min_t(loff_t, i_size_read(inode),
613 start + vma->vm_end - vma->vm_start);
614
615 if ((vma->vm_flags & VM_WRITE) && ei->valid_size < end) {
616 ret = exfat_file_zeroed_range(file, ei->valid_size, end);
617 if (ret < 0) {
618 exfat_err(inode->i_sb,
619 "mmap: fail to zero from %llu to %llu(%d)",
620 start, end, ret);
621 return ret;
622 }
623 }
624
625 return generic_file_mmap(file, vma);
626}
627
477const struct file_operations exfat_file_operations = {628const struct file_operations exfat_file_operations = {
478 .llseek = generic_file_llseek,629 .llseek = generic_file_llseek,
479 .read_iter = generic_file_read_iter,630 .read_iter = generic_file_read_iter,
480 .write_iter = generic_file_write_iter,631 .write_iter = exfat_file_write_iter,
481 .unlocked_ioctl = exfat_ioctl,632 .unlocked_ioctl = exfat_ioctl,
482#ifdef CONFIG_COMPAT633#ifdef CONFIG_COMPAT
483 .compat_ioctl = exfat_compat_ioctl,634 .compat_ioctl = exfat_compat_ioctl,
484#endif635#endif
485 .mmap = generic_file_mmap,636 .mmap = exfat_file_mmap,
486 .fsync = exfat_file_fsync,637 .fsync = exfat_file_fsync,
487 .splice_read = filemap_splice_read,638 .splice_read = filemap_splice_read,
488 .splice_write = iter_file_splice_write,639 .splice_write = iter_file_splice_write,
fs/exfat/inode.c+119−17
@@ -75,8 +75,17 @@ int __exfat_write_inode(struct inode *inode, int sync) · 74 unmodified lines
75 if (ei->start_clu == EXFAT_EOF_CLUSTER)75 if (ei->start_clu == EXFAT_EOF_CLUSTER)
76 on_disk_size = 0;76 on_disk_size = 0;
77 77
78 ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size);78 ep2->dentry.stream.size = cpu_to_le64(on_disk_size);
79 ep2->dentry.stream.size = ep2->dentry.stream.valid_size;79 /*
80 * mmap write does not use exfat_write_end(), valid_size may be
81 * extended to the sector-aligned length in exfat_get_block().
82 * So we need to fixup valid_size to the writren length.
83 */
84 if (on_disk_size < ei->valid_size)
85 ep2->dentry.stream.valid_size = ep2->dentry.stream.size;
86 else
87 ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size);
88
80 if (on_disk_size) {89 if (on_disk_size) {
81 ep2->dentry.stream.flags = ei->flags;90 ep2->dentry.stream.flags = ei->flags;
82 ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu);91 ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu);
@@ -278,6 +287,7 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, · 195 unmodified lines
278 unsigned int cluster, sec_offset;287 unsigned int cluster, sec_offset;
279 sector_t last_block;288 sector_t last_block;
280 sector_t phys = 0;289 sector_t phys = 0;
290 sector_t valid_blks;
281 loff_t pos;291 loff_t pos;
282 292
283 mutex_lock(&sbi->s_lock);293 mutex_lock(&sbi->s_lock);
@@ -306,17 +316,32 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, · 22 unmodified lines
306 mapped_blocks = sbi->sect_per_clus - sec_offset;316 mapped_blocks = sbi->sect_per_clus - sec_offset;
307 max_blocks = min(mapped_blocks, max_blocks);317 max_blocks = min(mapped_blocks, max_blocks);
308 318
309 /* Treat newly added block / cluster */319 pos = EXFAT_BLK_TO_B((iblock + 1), sb);
310 if (iblock < last_block)320 if ((create && iblock >= last_block) || buffer_delay(bh_result)) {
311 create = 0;
312
313 if (create || buffer_delay(bh_result)) {
314 pos = EXFAT_BLK_TO_B((iblock + 1), sb);
315 if (ei->i_size_ondisk < pos)321 if (ei->i_size_ondisk < pos)
316 ei->i_size_ondisk = pos;322 ei->i_size_ondisk = pos;
317 }323 }
318 324
325 map_bh(bh_result, sb, phys);
326 if (buffer_delay(bh_result))
327 clear_buffer_delay(bh_result);
328
319 if (create) {329 if (create) {
330 valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb);
331
332 if (iblock + max_blocks < valid_blks) {
333 /* The range has been written, map it */
334 goto done;
335 } else if (iblock < valid_blks) {
336 /*
337 * The range has been partially written,
338 * map the written part.
339 */
340 max_blocks = valid_blks - iblock;
341 goto done;
342 }
343
344 /* The area has not been written, map and mark as new. */
320 err = exfat_map_new_buffer(ei, bh_result, pos);345 err = exfat_map_new_buffer(ei, bh_result, pos);
321 if (err) {346 if (err) {
322 exfat_fs_error(sb,347 exfat_fs_error(sb,
@@ -324,11 +349,58 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, · 1 unmodified line
324 pos, ei->i_size_aligned);349 pos, ei->i_size_aligned);
325 goto unlock_ret;350 goto unlock_ret;
326 }351 }
327 }
328 352
329 if (buffer_delay(bh_result))353 ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
330 clear_buffer_delay(bh_result);354 mark_inode_dirty(inode);
331 map_bh(bh_result, sb, phys);355 } else {
356 valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
357
358 if (iblock + max_blocks < valid_blks) {
359 /* The range has been written, map it */
360 goto done;
361 } else if (iblock < valid_blks) {
362 /*
363 * The area has been partially written,
364 * map the written part.
365 */
366 max_blocks = valid_blks - iblock;
367 goto done;
368 } else if (iblock == valid_blks &&
369 (ei->valid_size & (sb->s_blocksize - 1))) {
370 /*
371 * The block has been partially written,
372 * zero the unwritten part and map the block.
373 */
374 loff_t size, off;
375
376 max_blocks = 1;
377
378 /*
379 * For direct read, the unwritten part will be zeroed in
380 * exfat_direct_IO()
381 */
382 if (!bh_result->b_folio)
383 goto done;
384
385 pos -= sb->s_blocksize;
386 size = ei->valid_size - pos;
387 off = pos & (PAGE_SIZE - 1);
388
389 folio_set_bh(bh_result, bh_result->b_folio, off);
390 err = bh_read(bh_result, 0);
391 if (err < 0)
392 goto unlock_ret;
393
394 folio_zero_segment(bh_result->b_folio, off + size,
395 off + sb->s_blocksize);
396 } else {
397 /*
398 * The range has not been written, clear the mapped flag
399 * to only zero the cache and do not read from disk.
400 */
401 clear_buffer_mapped(bh_result);
402 }
403 }
332done:404done:
333 bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);405 bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);
334unlock_ret:406unlock_ret:
@@ -343,6 +415,17 @@ static int exfat_read_folio(struct file *file, struct folio *folio) · 8 unmodified lines
343 415
344static void exfat_readahead(struct readahead_control *rac)416static void exfat_readahead(struct readahead_control *rac)
345{417{
418 struct address_space *mapping = rac->mapping;
419 struct inode *inode = mapping->host;
420 struct exfat_inode_info *ei = EXFAT_I(inode);
421 loff_t pos = readahead_pos(rac);
422
423 /* Range cross valid_size, read it page by page. */
424 if (ei->valid_size < i_size_read(inode) &&
425 pos <= ei->valid_size &&
426 ei->valid_size < pos + readahead_length(rac))
427 return;
428
346 mpage_readahead(rac, exfat_get_block);429 mpage_readahead(rac, exfat_get_block);
347}430}
348 431
@@ -370,9 +453,7 @@ static int exfat_write_begin(struct file *file, struct address_space *mapping, · 21 unmodified lines
370 int ret;453 int ret;
371 454
372 *pagep = NULL;455 *pagep = NULL;
373 ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,456 ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
374 exfat_get_block,
375 &EXFAT_I(mapping->host)->i_size_ondisk);
376 457
377 if (ret < 0)458 if (ret < 0)
378 exfat_write_failed(mapping, pos+len);459 exfat_write_failed(mapping, pos+len);
@@ -400,6 +481,11 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, · 21 unmodified lines
400 if (err < len)481 if (err < len)
401 exfat_write_failed(mapping, pos+len);482 exfat_write_failed(mapping, pos+len);
402 483
484 if (!(err < 0) && pos + err > ei->valid_size) {
485 ei->valid_size = pos + err;
486 mark_inode_dirty(inode);
487 }
488
403 if (!(err < 0) && !(ei->attr & EXFAT_ATTR_ARCHIVE)) {489 if (!(err < 0) && !(ei->attr & EXFAT_ATTR_ARCHIVE)) {
404 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));490 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
405 ei->attr |= EXFAT_ATTR_ARCHIVE;491 ei->attr |= EXFAT_ATTR_ARCHIVE;
@@ -413,6 +499,8 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) · 7 unmodified lines
413{499{
414 struct address_space *mapping = iocb->ki_filp->f_mapping;500 struct address_space *mapping = iocb->ki_filp->f_mapping;
415 struct inode *inode = mapping->host;501 struct inode *inode = mapping->host;
502 struct exfat_inode_info *ei = EXFAT_I(inode);
503 loff_t pos = iocb->ki_pos;
416 loff_t size = iocb->ki_pos + iov_iter_count(iter);504 loff_t size = iocb->ki_pos + iov_iter_count(iter);
417 int rw = iov_iter_rw(iter);505 int rw = iov_iter_rw(iter);
418 ssize_t ret;506 ssize_t ret;
@@ -436,8 +524,21 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) · 17 unmodified lines
436 * condition of exfat_get_block() and ->truncate().524 * condition of exfat_get_block() and ->truncate().
437 */525 */
438 ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block);526 ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block);
439 if (ret < 0 && (rw & WRITE))527 if (ret < 0) {
440 exfat_write_failed(mapping, size);528 if (rw == WRITE)
529 exfat_write_failed(mapping, size);
530
531 if (ret != -EIOCBQUEUED)
532 return ret;
533 } else
534 size = pos + ret;
535
536 /* zero the unwritten part in the partially written block */
537 if (rw == READ && pos < ei->valid_size && ei->valid_size < size) {
538 iov_iter_revert(iter, size - ei->valid_size);
539 iov_iter_zero(size - ei->valid_size, iter);
540 }
541
441 return ret;542 return ret;
442}543}
443 544
@@ -537,6 +638,7 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) · 93 unmodified lines
537 ei->start_clu = info->start_clu;638 ei->start_clu = info->start_clu;
538 ei->flags = info->flags;639 ei->flags = info->flags;
539 ei->type = info->type;640 ei->type = info->type;
641 ei->valid_size = info->valid_size;
540 642
541 ei->version = 0;643 ei->version = 0;
542 ei->hint_stat.eidx = 0;644 ei->hint_stat.eidx = 0;
fs/exfat/namei.c+6−0
@@ -406,6 +406,7 @@ static int exfat_find_empty_entry(struct inode *inode, · 405 unmodified lines
406 i_size_write(inode, size);406 i_size_write(inode, size);
407 ei->i_size_ondisk += sbi->cluster_size;407 ei->i_size_ondisk += sbi->cluster_size;
408 ei->i_size_aligned += sbi->cluster_size;408 ei->i_size_aligned += sbi->cluster_size;
409 ei->valid_size += sbi->cluster_size;
409 ei->flags = p_dir->flags;410 ei->flags = p_dir->flags;
410 inode->i_blocks += sbi->cluster_size >> 9;411 inode->i_blocks += sbi->cluster_size >> 9;
411 }412 }
@@ -558,6 +559,8 @@ static int exfat_add_entry(struct inode *inode, const char *path, · 146 unmodified lines
558 info->size = clu_size;559 info->size = clu_size;
559 info->num_subdirs = EXFAT_MIN_SUBDIR;560 info->num_subdirs = EXFAT_MIN_SUBDIR;
560 }561 }
562 info->valid_size = info->size;
563
561 memset(&info->crtime, 0, sizeof(info->crtime));564 memset(&info->crtime, 0, sizeof(info->crtime));
562 memset(&info->mtime, 0, sizeof(info->mtime));565 memset(&info->mtime, 0, sizeof(info->mtime));
563 memset(&info->atime, 0, sizeof(info->atime));566 memset(&info->atime, 0, sizeof(info->atime));
@@ -660,6 +663,8 @@ static int exfat_find(struct inode *dir, struct qstr *qname, · 96 unmodified lines
660 info->type = exfat_get_entry_type(ep);663 info->type = exfat_get_entry_type(ep);
661 info->attr = le16_to_cpu(ep->dentry.file.attr);664 info->attr = le16_to_cpu(ep->dentry.file.attr);
662 info->size = le64_to_cpu(ep2->dentry.stream.valid_size);665 info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
666 info->valid_size = le64_to_cpu(ep2->dentry.stream.valid_size);
667 info->size = le64_to_cpu(ep2->dentry.stream.size);
663 if (info->size == 0) {668 if (info->size == 0) {
664 info->flags = ALLOC_NO_FAT_CHAIN;669 info->flags = ALLOC_NO_FAT_CHAIN;
665 info->start_clu = EXFAT_EOF_CLUSTER;670 info->start_clu = EXFAT_EOF_CLUSTER;
@@ -1288,6 +1293,7 @@ static int __exfat_rename(struct inode *old_parent_inode, · 622 unmodified lines
1288 }1293 }
1289 1294
1290 i_size_write(new_inode, 0);1295 i_size_write(new_inode, 0);
1296 new_ei->valid_size = 0;
1291 new_ei->start_clu = EXFAT_EOF_CLUSTER;1297 new_ei->start_clu = EXFAT_EOF_CLUSTER;
1292 new_ei->flags = ALLOC_NO_FAT_CHAIN;1298 new_ei->flags = ALLOC_NO_FAT_CHAIN;
1293 }1299 }