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
Unified · Split
| @@ -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 | ||
| 13 | static 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 | |||
| 29 | static 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 Functions | 27 | * 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; |
| @@ -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 0x7 | 138 | #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 */ |
| @@ -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 | ||
| 18 | static int exfat_cont_expand(struct inode *inode, loff_t size) | 19 | static 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 | |||
| 65 | out: | ||
| 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 | |||
| 81 | free_clu: | ||
| 82 | exfat_free_cluster(inode, &clu); | ||
| 83 | return -EIO; | ||
| 45 | } | 84 | } |
| 46 | 85 | ||
| 47 | static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) | 86 | static 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 | ||
| 519 | static 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 | |||
| 550 | out: | ||
| 551 | return err; | ||
| 552 | } | ||
| 553 | |||
| 554 | static 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 | |||
| 600 | unlock: | ||
| 601 | inode_unlock(inode); | ||
| 602 | |||
| 603 | return ret; | ||
| 604 | } | ||
| 605 | |||
| 606 | static 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 | |||
| 477 | const struct file_operations exfat_file_operations = { | 628 | const 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_COMPAT | 633 | #ifdef CONFIG_COMPAT |
| 483 | .compat_ioctl = exfat_compat_ioctl, | 634 | .compat_ioctl = exfat_compat_ioctl, |
| 484 | #endif | 635 | #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, |
| @@ -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 | } | ||
| 332 | done: | 404 | done: |
| 333 | bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); | 405 | bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); |
| 334 | unlock_ret: | 406 | unlock_ret: |
| @@ -343,6 +415,17 @@ static int exfat_read_folio(struct file *file, struct folio *folio) · 8 unmodified lines | |||
| 343 | 415 | ||
| 344 | static void exfat_readahead(struct readahead_control *rac) | 416 | static 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; |
| @@ -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 | } |