diff options
Diffstat (limited to 'fs/fat')
-rw-r--r-- | fs/fat/dir.c | 4 | ||||
-rw-r--r-- | fs/fat/fat.h | 6 | ||||
-rw-r--r-- | fs/fat/fatent.c | 21 | ||||
-rw-r--r-- | fs/fat/inode.c | 54 |
4 files changed, 48 insertions, 37 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index aca191bd5f8f..6eaa28c98ad1 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -98,8 +98,8 @@ next: | |||
98 | 98 | ||
99 | *bh = sb_bread(sb, phys); | 99 | *bh = sb_bread(sb, phys); |
100 | if (*bh == NULL) { | 100 | if (*bh == NULL) { |
101 | fat_msg(sb, KERN_ERR, "Directory bread(block %llu) failed", | 101 | fat_msg_ratelimit(sb, KERN_ERR, |
102 | (llu)phys); | 102 | "Directory bread(block %llu) failed", (llu)phys); |
103 | /* skip this block */ | 103 | /* skip this block */ |
104 | *pos = (iblock + 1) << sb->s_blocksize_bits; | 104 | *pos = (iblock + 1) << sb->s_blocksize_bits; |
105 | goto next; | 105 | goto next; |
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 66994f316e18..fc35c5c69136 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
@@ -82,6 +82,7 @@ struct msdos_sb_info { | |||
82 | int fatent_shift; | 82 | int fatent_shift; |
83 | struct fatent_operations *fatent_ops; | 83 | struct fatent_operations *fatent_ops; |
84 | struct inode *fat_inode; | 84 | struct inode *fat_inode; |
85 | struct inode *fsinfo_inode; | ||
85 | 86 | ||
86 | struct ratelimit_state ratelimit; | 87 | struct ratelimit_state ratelimit; |
87 | 88 | ||
@@ -334,6 +335,11 @@ void __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...); | |||
334 | __fat_fs_error(sb, __ratelimit(&MSDOS_SB(sb)->ratelimit), fmt , ## args) | 335 | __fat_fs_error(sb, __ratelimit(&MSDOS_SB(sb)->ratelimit), fmt , ## args) |
335 | __printf(3, 4) __cold | 336 | __printf(3, 4) __cold |
336 | void fat_msg(struct super_block *sb, const char *level, const char *fmt, ...); | 337 | void fat_msg(struct super_block *sb, const char *level, const char *fmt, ...); |
338 | #define fat_msg_ratelimit(sb, level, fmt, args...) \ | ||
339 | do { \ | ||
340 | if (__ratelimit(&MSDOS_SB(sb)->ratelimit)) \ | ||
341 | fat_msg(sb, level, fmt, ## args); \ | ||
342 | } while (0) | ||
337 | extern int fat_clusters_flush(struct super_block *sb); | 343 | extern int fat_clusters_flush(struct super_block *sb); |
338 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | 344 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); |
339 | extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, | 345 | extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, |
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index 2e81ac0df7e2..31f08ab62c56 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c | |||
@@ -308,6 +308,16 @@ void fat_ent_access_init(struct super_block *sb) | |||
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | static void mark_fsinfo_dirty(struct super_block *sb) | ||
312 | { | ||
313 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | ||
314 | |||
315 | if (sb->s_flags & MS_RDONLY || sbi->fat_bits != 32) | ||
316 | return; | ||
317 | |||
318 | __mark_inode_dirty(sbi->fsinfo_inode, I_DIRTY_SYNC); | ||
319 | } | ||
320 | |||
311 | static inline int fat_ent_update_ptr(struct super_block *sb, | 321 | static inline int fat_ent_update_ptr(struct super_block *sb, |
312 | struct fat_entry *fatent, | 322 | struct fat_entry *fatent, |
313 | int offset, sector_t blocknr) | 323 | int offset, sector_t blocknr) |
@@ -498,7 +508,6 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) | |||
498 | sbi->prev_free = entry; | 508 | sbi->prev_free = entry; |
499 | if (sbi->free_clusters != -1) | 509 | if (sbi->free_clusters != -1) |
500 | sbi->free_clusters--; | 510 | sbi->free_clusters--; |
501 | sb->s_dirt = 1; | ||
502 | 511 | ||
503 | cluster[idx_clus] = entry; | 512 | cluster[idx_clus] = entry; |
504 | idx_clus++; | 513 | idx_clus++; |
@@ -520,11 +529,11 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) | |||
520 | /* Couldn't allocate the free entries */ | 529 | /* Couldn't allocate the free entries */ |
521 | sbi->free_clusters = 0; | 530 | sbi->free_clusters = 0; |
522 | sbi->free_clus_valid = 1; | 531 | sbi->free_clus_valid = 1; |
523 | sb->s_dirt = 1; | ||
524 | err = -ENOSPC; | 532 | err = -ENOSPC; |
525 | 533 | ||
526 | out: | 534 | out: |
527 | unlock_fat(sbi); | 535 | unlock_fat(sbi); |
536 | mark_fsinfo_dirty(sb); | ||
528 | fatent_brelse(&fatent); | 537 | fatent_brelse(&fatent); |
529 | if (!err) { | 538 | if (!err) { |
530 | if (inode_needs_sync(inode)) | 539 | if (inode_needs_sync(inode)) |
@@ -549,7 +558,7 @@ int fat_free_clusters(struct inode *inode, int cluster) | |||
549 | struct fat_entry fatent; | 558 | struct fat_entry fatent; |
550 | struct buffer_head *bhs[MAX_BUF_PER_PAGE]; | 559 | struct buffer_head *bhs[MAX_BUF_PER_PAGE]; |
551 | int i, err, nr_bhs; | 560 | int i, err, nr_bhs; |
552 | int first_cl = cluster; | 561 | int first_cl = cluster, dirty_fsinfo = 0; |
553 | 562 | ||
554 | nr_bhs = 0; | 563 | nr_bhs = 0; |
555 | fatent_init(&fatent); | 564 | fatent_init(&fatent); |
@@ -587,7 +596,7 @@ int fat_free_clusters(struct inode *inode, int cluster) | |||
587 | ops->ent_put(&fatent, FAT_ENT_FREE); | 596 | ops->ent_put(&fatent, FAT_ENT_FREE); |
588 | if (sbi->free_clusters != -1) { | 597 | if (sbi->free_clusters != -1) { |
589 | sbi->free_clusters++; | 598 | sbi->free_clusters++; |
590 | sb->s_dirt = 1; | 599 | dirty_fsinfo = 1; |
591 | } | 600 | } |
592 | 601 | ||
593 | if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) { | 602 | if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) { |
@@ -617,6 +626,8 @@ error: | |||
617 | for (i = 0; i < nr_bhs; i++) | 626 | for (i = 0; i < nr_bhs; i++) |
618 | brelse(bhs[i]); | 627 | brelse(bhs[i]); |
619 | unlock_fat(sbi); | 628 | unlock_fat(sbi); |
629 | if (dirty_fsinfo) | ||
630 | mark_fsinfo_dirty(sb); | ||
620 | 631 | ||
621 | return err; | 632 | return err; |
622 | } | 633 | } |
@@ -677,7 +688,7 @@ int fat_count_free_clusters(struct super_block *sb) | |||
677 | } | 688 | } |
678 | sbi->free_clusters = free; | 689 | sbi->free_clusters = free; |
679 | sbi->free_clus_valid = 1; | 690 | sbi->free_clus_valid = 1; |
680 | sb->s_dirt = 1; | 691 | mark_fsinfo_dirty(sb); |
681 | fatent_brelse(&fatent); | 692 | fatent_brelse(&fatent); |
682 | out: | 693 | out: |
683 | unlock_fat(sbi); | 694 | unlock_fat(sbi); |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7edfaadc0787..a3d81ebf6d86 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -459,37 +459,11 @@ static void fat_evict_inode(struct inode *inode) | |||
459 | fat_detach(inode); | 459 | fat_detach(inode); |
460 | } | 460 | } |
461 | 461 | ||
462 | static void fat_write_super(struct super_block *sb) | ||
463 | { | ||
464 | lock_super(sb); | ||
465 | sb->s_dirt = 0; | ||
466 | |||
467 | if (!(sb->s_flags & MS_RDONLY)) | ||
468 | fat_clusters_flush(sb); | ||
469 | unlock_super(sb); | ||
470 | } | ||
471 | |||
472 | static int fat_sync_fs(struct super_block *sb, int wait) | ||
473 | { | ||
474 | int err = 0; | ||
475 | |||
476 | if (sb->s_dirt) { | ||
477 | lock_super(sb); | ||
478 | sb->s_dirt = 0; | ||
479 | err = fat_clusters_flush(sb); | ||
480 | unlock_super(sb); | ||
481 | } | ||
482 | |||
483 | return err; | ||
484 | } | ||
485 | |||
486 | static void fat_put_super(struct super_block *sb) | 462 | static void fat_put_super(struct super_block *sb) |
487 | { | 463 | { |
488 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 464 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
489 | 465 | ||
490 | if (sb->s_dirt) | 466 | iput(sbi->fsinfo_inode); |
491 | fat_write_super(sb); | ||
492 | |||
493 | iput(sbi->fat_inode); | 467 | iput(sbi->fat_inode); |
494 | 468 | ||
495 | unload_nls(sbi->nls_disk); | 469 | unload_nls(sbi->nls_disk); |
@@ -661,7 +635,18 @@ retry: | |||
661 | 635 | ||
662 | static int fat_write_inode(struct inode *inode, struct writeback_control *wbc) | 636 | static int fat_write_inode(struct inode *inode, struct writeback_control *wbc) |
663 | { | 637 | { |
664 | return __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); | 638 | int err; |
639 | |||
640 | if (inode->i_ino == MSDOS_FSINFO_INO) { | ||
641 | struct super_block *sb = inode->i_sb; | ||
642 | |||
643 | lock_super(sb); | ||
644 | err = fat_clusters_flush(sb); | ||
645 | unlock_super(sb); | ||
646 | } else | ||
647 | err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); | ||
648 | |||
649 | return err; | ||
665 | } | 650 | } |
666 | 651 | ||
667 | int fat_sync_inode(struct inode *inode) | 652 | int fat_sync_inode(struct inode *inode) |
@@ -678,8 +663,6 @@ static const struct super_operations fat_sops = { | |||
678 | .write_inode = fat_write_inode, | 663 | .write_inode = fat_write_inode, |
679 | .evict_inode = fat_evict_inode, | 664 | .evict_inode = fat_evict_inode, |
680 | .put_super = fat_put_super, | 665 | .put_super = fat_put_super, |
681 | .write_super = fat_write_super, | ||
682 | .sync_fs = fat_sync_fs, | ||
683 | .statfs = fat_statfs, | 666 | .statfs = fat_statfs, |
684 | .remount_fs = fat_remount, | 667 | .remount_fs = fat_remount, |
685 | 668 | ||
@@ -1243,6 +1226,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1243 | void (*setup)(struct super_block *)) | 1226 | void (*setup)(struct super_block *)) |
1244 | { | 1227 | { |
1245 | struct inode *root_inode = NULL, *fat_inode = NULL; | 1228 | struct inode *root_inode = NULL, *fat_inode = NULL; |
1229 | struct inode *fsinfo_inode = NULL; | ||
1246 | struct buffer_head *bh; | 1230 | struct buffer_head *bh; |
1247 | struct fat_boot_sector *b; | 1231 | struct fat_boot_sector *b; |
1248 | struct msdos_sb_info *sbi; | 1232 | struct msdos_sb_info *sbi; |
@@ -1489,6 +1473,14 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1489 | goto out_fail; | 1473 | goto out_fail; |
1490 | MSDOS_I(fat_inode)->i_pos = 0; | 1474 | MSDOS_I(fat_inode)->i_pos = 0; |
1491 | sbi->fat_inode = fat_inode; | 1475 | sbi->fat_inode = fat_inode; |
1476 | |||
1477 | fsinfo_inode = new_inode(sb); | ||
1478 | if (!fsinfo_inode) | ||
1479 | goto out_fail; | ||
1480 | fsinfo_inode->i_ino = MSDOS_FSINFO_INO; | ||
1481 | sbi->fsinfo_inode = fsinfo_inode; | ||
1482 | insert_inode_hash(fsinfo_inode); | ||
1483 | |||
1492 | root_inode = new_inode(sb); | 1484 | root_inode = new_inode(sb); |
1493 | if (!root_inode) | 1485 | if (!root_inode) |
1494 | goto out_fail; | 1486 | goto out_fail; |
@@ -1515,6 +1507,8 @@ out_invalid: | |||
1515 | fat_msg(sb, KERN_INFO, "Can't find a valid FAT filesystem"); | 1507 | fat_msg(sb, KERN_INFO, "Can't find a valid FAT filesystem"); |
1516 | 1508 | ||
1517 | out_fail: | 1509 | out_fail: |
1510 | if (fsinfo_inode) | ||
1511 | iput(fsinfo_inode); | ||
1518 | if (fat_inode) | 1512 | if (fat_inode) |
1519 | iput(fat_inode); | 1513 | iput(fat_inode); |
1520 | unload_nls(sbi->nls_io); | 1514 | unload_nls(sbi->nls_io); |