diff options
Diffstat (limited to 'fs/fat/inode.c')
| -rw-r--r-- | fs/fat/inode.c | 99 |
1 files changed, 72 insertions, 27 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7c35d582ec10..045738032a83 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/vfs.h> | 24 | #include <linux/vfs.h> |
| 25 | #include <linux/parser.h> | 25 | #include <linux/parser.h> |
| 26 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
| 27 | #include <linux/writeback.h> | ||
| 27 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
| 28 | 29 | ||
| 29 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET | 30 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET |
| @@ -50,14 +51,14 @@ static int fat_add_cluster(struct inode *inode) | |||
| 50 | return err; | 51 | return err; |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | static int __fat_get_blocks(struct inode *inode, sector_t iblock, | 54 | static inline int __fat_get_block(struct inode *inode, sector_t iblock, |
| 54 | unsigned long *max_blocks, | 55 | unsigned long *max_blocks, |
| 55 | struct buffer_head *bh_result, int create) | 56 | struct buffer_head *bh_result, int create) |
| 56 | { | 57 | { |
| 57 | struct super_block *sb = inode->i_sb; | 58 | struct super_block *sb = inode->i_sb; |
| 58 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 59 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
| 59 | sector_t phys; | ||
| 60 | unsigned long mapped_blocks; | 60 | unsigned long mapped_blocks; |
| 61 | sector_t phys; | ||
| 61 | int err, offset; | 62 | int err, offset; |
| 62 | 63 | ||
| 63 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 64 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); |
| @@ -73,7 +74,7 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock, | |||
| 73 | 74 | ||
| 74 | if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) { | 75 | if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) { |
| 75 | fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)", | 76 | fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)", |
| 76 | MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private); | 77 | MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private); |
| 77 | return -EIO; | 78 | return -EIO; |
| 78 | } | 79 | } |
| 79 | 80 | ||
| @@ -93,34 +94,29 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock, | |||
| 93 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 94 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); |
| 94 | if (err) | 95 | if (err) |
| 95 | return err; | 96 | return err; |
| 97 | |||
| 96 | BUG_ON(!phys); | 98 | BUG_ON(!phys); |
| 97 | BUG_ON(*max_blocks != mapped_blocks); | 99 | BUG_ON(*max_blocks != mapped_blocks); |
| 98 | set_buffer_new(bh_result); | 100 | set_buffer_new(bh_result); |
| 99 | map_bh(bh_result, sb, phys); | 101 | map_bh(bh_result, sb, phys); |
| 102 | |||
| 100 | return 0; | 103 | return 0; |
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | static int fat_get_blocks(struct inode *inode, sector_t iblock, | 106 | static int fat_get_block(struct inode *inode, sector_t iblock, |
| 104 | struct buffer_head *bh_result, int create) | 107 | struct buffer_head *bh_result, int create) |
| 105 | { | 108 | { |
| 106 | struct super_block *sb = inode->i_sb; | 109 | struct super_block *sb = inode->i_sb; |
| 107 | int err; | ||
| 108 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; | 110 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; |
| 111 | int err; | ||
| 109 | 112 | ||
| 110 | err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create); | 113 | err = __fat_get_block(inode, iblock, &max_blocks, bh_result, create); |
| 111 | if (err) | 114 | if (err) |
| 112 | return err; | 115 | return err; |
| 113 | bh_result->b_size = max_blocks << sb->s_blocksize_bits; | 116 | bh_result->b_size = max_blocks << sb->s_blocksize_bits; |
| 114 | return 0; | 117 | return 0; |
| 115 | } | 118 | } |
| 116 | 119 | ||
| 117 | static int fat_get_block(struct inode *inode, sector_t iblock, | ||
| 118 | struct buffer_head *bh_result, int create) | ||
| 119 | { | ||
| 120 | unsigned long max_blocks = 1; | ||
| 121 | return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create); | ||
| 122 | } | ||
| 123 | |||
| 124 | static int fat_writepage(struct page *page, struct writeback_control *wbc) | 120 | static int fat_writepage(struct page *page, struct writeback_control *wbc) |
| 125 | { | 121 | { |
| 126 | return block_write_full_page(page, fat_get_block, wbc); | 122 | return block_write_full_page(page, fat_get_block, wbc); |
| @@ -188,7 +184,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
| 188 | * condition of fat_get_block() and ->truncate(). | 184 | * condition of fat_get_block() and ->truncate(). |
| 189 | */ | 185 | */ |
| 190 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 186 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
| 191 | offset, nr_segs, fat_get_blocks, NULL); | 187 | offset, nr_segs, fat_get_block, NULL); |
| 192 | } | 188 | } |
| 193 | 189 | ||
| 194 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 190 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
| @@ -196,7 +192,7 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | |||
| 196 | return generic_block_bmap(mapping, block, fat_get_block); | 192 | return generic_block_bmap(mapping, block, fat_get_block); |
| 197 | } | 193 | } |
| 198 | 194 | ||
| 199 | static struct address_space_operations fat_aops = { | 195 | static const struct address_space_operations fat_aops = { |
| 200 | .readpage = fat_readpage, | 196 | .readpage = fat_readpage, |
| 201 | .readpages = fat_readpages, | 197 | .readpages = fat_readpages, |
| 202 | .writepage = fat_writepage, | 198 | .writepage = fat_writepage, |
| @@ -375,8 +371,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
| 375 | inode->i_flags |= S_IMMUTABLE; | 371 | inode->i_flags |= S_IMMUTABLE; |
| 376 | } | 372 | } |
| 377 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; | 373 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; |
| 378 | /* this is as close to the truth as we can get ... */ | ||
| 379 | inode->i_blksize = sbi->cluster_size; | ||
| 380 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 374 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
| 381 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 375 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
| 382 | inode->i_mtime.tv_sec = | 376 | inode->i_mtime.tv_sec = |
| @@ -528,8 +522,7 @@ static int __init fat_init_inodecache(void) | |||
| 528 | 522 | ||
| 529 | static void __exit fat_destroy_inodecache(void) | 523 | static void __exit fat_destroy_inodecache(void) |
| 530 | { | 524 | { |
| 531 | if (kmem_cache_destroy(fat_inode_cachep)) | 525 | kmem_cache_destroy(fat_inode_cachep); |
| 532 | printk(KERN_INFO "fat_inode_cache: not all structures were freed\n"); | ||
| 533 | } | 526 | } |
| 534 | 527 | ||
| 535 | static int fat_remount(struct super_block *sb, int *flags, char *data) | 528 | static int fat_remount(struct super_block *sb, int *flags, char *data) |
| @@ -861,7 +854,7 @@ enum { | |||
| 861 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 854 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
| 862 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 855 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
| 863 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 856 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
| 864 | Opt_obsolate, Opt_err, | 857 | Opt_obsolate, Opt_flush, Opt_err, |
| 865 | }; | 858 | }; |
| 866 | 859 | ||
| 867 | static match_table_t fat_tokens = { | 860 | static match_table_t fat_tokens = { |
| @@ -893,7 +886,8 @@ static match_table_t fat_tokens = { | |||
| 893 | {Opt_obsolate, "cvf_format=%20s"}, | 886 | {Opt_obsolate, "cvf_format=%20s"}, |
| 894 | {Opt_obsolate, "cvf_options=%100s"}, | 887 | {Opt_obsolate, "cvf_options=%100s"}, |
| 895 | {Opt_obsolate, "posix"}, | 888 | {Opt_obsolate, "posix"}, |
| 896 | {Opt_err, NULL} | 889 | {Opt_flush, "flush"}, |
| 890 | {Opt_err, NULL}, | ||
| 897 | }; | 891 | }; |
| 898 | static match_table_t msdos_tokens = { | 892 | static match_table_t msdos_tokens = { |
| 899 | {Opt_nodots, "nodots"}, | 893 | {Opt_nodots, "nodots"}, |
| @@ -1034,6 +1028,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
| 1034 | return 0; | 1028 | return 0; |
| 1035 | opts->codepage = option; | 1029 | opts->codepage = option; |
| 1036 | break; | 1030 | break; |
| 1031 | case Opt_flush: | ||
| 1032 | opts->flush = 1; | ||
| 1033 | break; | ||
| 1037 | 1034 | ||
| 1038 | /* msdos specific */ | 1035 | /* msdos specific */ |
| 1039 | case Opt_dots: | 1036 | case Opt_dots: |
| @@ -1137,7 +1134,6 @@ static int fat_read_root(struct inode *inode) | |||
| 1137 | MSDOS_I(inode)->i_start = 0; | 1134 | MSDOS_I(inode)->i_start = 0; |
| 1138 | inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry); | 1135 | inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry); |
| 1139 | } | 1136 | } |
| 1140 | inode->i_blksize = sbi->cluster_size; | ||
| 1141 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 1137 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
| 1142 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 1138 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
| 1143 | MSDOS_I(inode)->i_logstart = 0; | 1139 | MSDOS_I(inode)->i_logstart = 0; |
| @@ -1168,11 +1164,10 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, | |||
| 1168 | long error; | 1164 | long error; |
| 1169 | char buf[50]; | 1165 | char buf[50]; |
| 1170 | 1166 | ||
| 1171 | sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL); | 1167 | sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL); |
| 1172 | if (!sbi) | 1168 | if (!sbi) |
| 1173 | return -ENOMEM; | 1169 | return -ENOMEM; |
| 1174 | sb->s_fs_info = sbi; | 1170 | sb->s_fs_info = sbi; |
| 1175 | memset(sbi, 0, sizeof(struct msdos_sb_info)); | ||
| 1176 | 1171 | ||
| 1177 | sb->s_flags |= MS_NODIRATIME; | 1172 | sb->s_flags |= MS_NODIRATIME; |
| 1178 | sb->s_magic = MSDOS_SUPER_MAGIC; | 1173 | sb->s_magic = MSDOS_SUPER_MAGIC; |
| @@ -1435,6 +1430,56 @@ out_fail: | |||
| 1435 | 1430 | ||
| 1436 | EXPORT_SYMBOL_GPL(fat_fill_super); | 1431 | EXPORT_SYMBOL_GPL(fat_fill_super); |
| 1437 | 1432 | ||
| 1433 | /* | ||
| 1434 | * helper function for fat_flush_inodes. This writes both the inode | ||
| 1435 | * and the file data blocks, waiting for in flight data blocks before | ||
| 1436 | * the start of the call. It does not wait for any io started | ||
| 1437 | * during the call | ||
| 1438 | */ | ||
| 1439 | static int writeback_inode(struct inode *inode) | ||
| 1440 | { | ||
| 1441 | |||
| 1442 | int ret; | ||
| 1443 | struct address_space *mapping = inode->i_mapping; | ||
| 1444 | struct writeback_control wbc = { | ||
| 1445 | .sync_mode = WB_SYNC_NONE, | ||
| 1446 | .nr_to_write = 0, | ||
| 1447 | }; | ||
| 1448 | /* if we used WB_SYNC_ALL, sync_inode waits for the io for the | ||
| 1449 | * inode to finish. So WB_SYNC_NONE is sent down to sync_inode | ||
| 1450 | * and filemap_fdatawrite is used for the data blocks | ||
| 1451 | */ | ||
| 1452 | ret = sync_inode(inode, &wbc); | ||
| 1453 | if (!ret) | ||
| 1454 | ret = filemap_fdatawrite(mapping); | ||
| 1455 | return ret; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | /* | ||
| 1459 | * write data and metadata corresponding to i1 and i2. The io is | ||
| 1460 | * started but we do not wait for any of it to finish. | ||
| 1461 | * | ||
| 1462 | * filemap_flush is used for the block device, so if there is a dirty | ||
| 1463 | * page for a block already in flight, we will not wait and start the | ||
| 1464 | * io over again | ||
| 1465 | */ | ||
| 1466 | int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2) | ||
| 1467 | { | ||
| 1468 | int ret = 0; | ||
| 1469 | if (!MSDOS_SB(sb)->options.flush) | ||
| 1470 | return 0; | ||
| 1471 | if (i1) | ||
| 1472 | ret = writeback_inode(i1); | ||
| 1473 | if (!ret && i2) | ||
| 1474 | ret = writeback_inode(i2); | ||
| 1475 | if (!ret && sb) { | ||
| 1476 | struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; | ||
| 1477 | ret = filemap_flush(mapping); | ||
| 1478 | } | ||
| 1479 | return ret; | ||
| 1480 | } | ||
| 1481 | EXPORT_SYMBOL_GPL(fat_flush_inodes); | ||
| 1482 | |||
| 1438 | static int __init init_fat_fs(void) | 1483 | static int __init init_fat_fs(void) |
| 1439 | { | 1484 | { |
| 1440 | int err; | 1485 | int err; |
