aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fat/inode.c
diff options
context:
space:
mode:
authorOleksij Rempel <bug-track@fisher-privat.net>2013-02-27 20:03:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-27 22:10:11 -0500
commitb88a105802e9aeb6e234e8106659f5d1271081bb (patch)
tree589342d16e494deeb20da933fe409088e59b04d8 /fs/fat/inode.c
parent6b46419b0462ae565880f02e9cd0baf9b25ea71f (diff)
fat: mark fs as dirty on mount and clean on umount
There is no documented methods to mark FAT as dirty. Unofficially MS started to use reserved Byte in boot sector for this purpose, at least since Win 2000. With Win 7 user is warned if fs is dirty and asked to clean it. Different versions of Win, handle it in different ways, but always have same meaning: - Win 2000 and XP, set it on write operations and remove it after operation was finnished - Win 7, set dirty flag on first write and remove it on umount. We will do it as follows: - set dirty flag on mount. If fs was initially dirty, warn user, remember it and do not do any changes to boot sector. - clean it on umount. If fs was initially dirty, leave it dirty. - do not do any thing if fs mounted read-only. - TODO: leave fs dirty if we found some error after mount. Signed-off-by: Oleksij Rempel <bug-track@fisher-privat.net> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fat/inode.c')
-rw-r--r--fs/fat/inode.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 4b4d4ef910f3..780e20806346 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -488,10 +488,59 @@ static void fat_evict_inode(struct inode *inode)
488 fat_detach(inode); 488 fat_detach(inode);
489} 489}
490 490
491static void fat_set_state(struct super_block *sb,
492 unsigned int set, unsigned int force)
493{
494 struct buffer_head *bh;
495 struct fat_boot_sector *b;
496 struct msdos_sb_info *sbi = sb->s_fs_info;
497
498 /* do not change any thing if mounted read only */
499 if ((sb->s_flags & MS_RDONLY) && !force)
500 return;
501
502 /* do not change state if fs was dirty */
503 if (sbi->dirty) {
504 /* warn only on set (mount). */
505 if (set)
506 fat_msg(sb, KERN_WARNING, "Volume was not properly "
507 "unmounted. Some data may be corrupt. "
508 "Please run fsck.");
509 return;
510 }
511
512 bh = sb_bread(sb, 0);
513 if (bh == NULL) {
514 fat_msg(sb, KERN_ERR, "unable to read boot sector "
515 "to mark fs as dirty");
516 return;
517 }
518
519 b = (struct fat_boot_sector *) bh->b_data;
520
521 if (sbi->fat_bits == 32) {
522 if (set)
523 b->fat32.state |= FAT_STATE_DIRTY;
524 else
525 b->fat32.state &= ~FAT_STATE_DIRTY;
526 } else /* fat 16 and 12 */ {
527 if (set)
528 b->fat16.state |= FAT_STATE_DIRTY;
529 else
530 b->fat16.state &= ~FAT_STATE_DIRTY;
531 }
532
533 mark_buffer_dirty(bh);
534 sync_dirty_buffer(bh);
535 brelse(bh);
536}
537
491static void fat_put_super(struct super_block *sb) 538static void fat_put_super(struct super_block *sb)
492{ 539{
493 struct msdos_sb_info *sbi = MSDOS_SB(sb); 540 struct msdos_sb_info *sbi = MSDOS_SB(sb);
494 541
542 fat_set_state(sb, 0, 0);
543
495 iput(sbi->fsinfo_inode); 544 iput(sbi->fsinfo_inode);
496 iput(sbi->fat_inode); 545 iput(sbi->fat_inode);
497 546
@@ -566,8 +615,18 @@ static void __exit fat_destroy_inodecache(void)
566 615
567static int fat_remount(struct super_block *sb, int *flags, char *data) 616static int fat_remount(struct super_block *sb, int *flags, char *data)
568{ 617{
618 int new_rdonly;
569 struct msdos_sb_info *sbi = MSDOS_SB(sb); 619 struct msdos_sb_info *sbi = MSDOS_SB(sb);
570 *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME); 620 *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);
621
622 /* make sure we update state on remount. */
623 new_rdonly = *flags & MS_RDONLY;
624 if (new_rdonly != (sb->s_flags & MS_RDONLY)) {
625 if (new_rdonly)
626 fat_set_state(sb, 0, 0);
627 else
628 fat_set_state(sb, 1, 1);
629 }
571 return 0; 630 return 0;
572} 631}
573 632
@@ -1362,6 +1421,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
1362 if (sbi->fat_bits != 32) 1421 if (sbi->fat_bits != 32)
1363 sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; 1422 sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
1364 1423
1424 /* some OSes set FAT_STATE_DIRTY and clean it on unmount. */
1425 if (sbi->fat_bits == 32)
1426 sbi->dirty = b->fat32.state & FAT_STATE_DIRTY;
1427 else /* fat 16 or 12 */
1428 sbi->dirty = b->fat16.state & FAT_STATE_DIRTY;
1429
1365 /* check that FAT table does not overflow */ 1430 /* check that FAT table does not overflow */
1366 fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; 1431 fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
1367 total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); 1432 total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT);
@@ -1456,6 +1521,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
1456 "the device does not support discard"); 1521 "the device does not support discard");
1457 } 1522 }
1458 1523
1524 fat_set_state(sb, 1, 0);
1459 return 0; 1525 return 0;
1460 1526
1461out_invalid: 1527out_invalid: