|
18 | 18 |
|
19 | 19 | static int exfat_cont_expand(struct inode *inode, loff_t size)
|
20 | 20 | {
|
21 |
| - struct address_space *mapping = inode->i_mapping; |
22 |
| - loff_t start = i_size_read(inode), count = size - i_size_read(inode); |
23 |
| - int err, err2; |
| 21 | + int ret; |
| 22 | + unsigned int num_clusters, new_num_clusters, last_clu; |
| 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; |
24 | 27 |
|
25 |
| - err = generic_cont_expand_simple(inode, size); |
26 |
| - if (err) |
27 |
| - return err; |
| 28 | + ret = inode_newsize_ok(inode, size); |
| 29 | + if (ret) |
| 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; |
28 | 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; |
| 61 | + |
| 62 | + if (num_clusters == 0) |
| 63 | + ei->start_clu = clu.dir; |
| 64 | + |
| 65 | +out: |
29 | 66 | inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
30 |
| - EXFAT_I(inode)->valid_size = size; |
31 |
| - mark_inode_dirty(inode); |
| 67 | + /* Expanded range not zeroed, do not update valid_size */ |
| 68 | + i_size_write(inode, size); |
32 | 69 |
|
33 |
| - if (!IS_SYNC(inode)) |
34 |
| - return 0; |
| 70 | + ei->i_size_aligned = round_up(size, sb->s_blocksize); |
| 71 | + ei->i_size_ondisk = ei->i_size_aligned; |
| 72 | + inode->i_blocks = round_up(size, sbi->cluster_size) >> 9; |
35 | 73 |
|
36 |
| - err = filemap_fdatawrite_range(mapping, start, start + count - 1); |
37 |
| - err2 = sync_mapping_buffers(mapping); |
38 |
| - if (!err) |
39 |
| - err = err2; |
40 |
| - err2 = write_inode_now(inode, 1); |
41 |
| - if (!err) |
42 |
| - err = err2; |
43 |
| - if (err) |
44 |
| - return err; |
| 74 | + if (IS_DIRSYNC(inode)) |
| 75 | + return write_inode_now(inode, 1); |
| 76 | + |
| 77 | + mark_inode_dirty(inode); |
| 78 | + |
| 79 | + return 0; |
45 | 80 |
|
46 |
| - return filemap_fdatawait_range(mapping, start, start + count - 1); |
| 81 | +free_clu: |
| 82 | + exfat_free_cluster(inode, &clu); |
| 83 | + return -EIO; |
47 | 84 | }
|
48 | 85 |
|
49 | 86 | static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
|
|
0 commit comments