* [PATCH 1/2] fat: add extended fileds to struct fat_boot_sector @ 2012-12-27 17:19 OGAWA Hirofumi 2012-12-27 17:20 ` [PATCH 2/2] fat: mark fs as dirty on mount and clean on umount OGAWA Hirofumi 0 siblings, 1 reply; 4+ messages in thread From: OGAWA Hirofumi @ 2012-12-27 17:19 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, linux-fsdevel, bug-track From: Oleksij Rempel <bug-track@fisher-privat.net> later we will need "state" field to check if volume was cleanly unmounted. Signed-off-by: Oleksij Rempel <bug-track@fisher-privat.net> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> --- fs/fat/inode.c | 8 ++++---- include/uapi/linux/msdos_fs.h | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 12 deletions(-) diff -puN fs/fat/inode.c~fat-check-dirty-1 fs/fat/inode.c --- linux/fs/fat/inode.c~fat-check-dirty-1 2012-12-28 02:17:39.000000000 +0900 +++ linux-hirofumi/fs/fat/inode.c 2012-12-28 02:17:39.000000000 +0900 @@ -1298,17 +1298,17 @@ int fat_fill_super(struct super_block *s sbi->prev_free = FAT_START_ENT; sb->s_maxbytes = 0xffffffff; - if (!sbi->fat_length && b->fat32_length) { + if (!sbi->fat_length && b->fat32.length) { struct fat_boot_fsinfo *fsinfo; struct buffer_head *fsinfo_bh; /* Must be FAT32 */ sbi->fat_bits = 32; - sbi->fat_length = le32_to_cpu(b->fat32_length); - sbi->root_cluster = le32_to_cpu(b->root_cluster); + sbi->fat_length = le32_to_cpu(b->fat32.length); + sbi->root_cluster = le32_to_cpu(b->fat32.root_cluster); /* MC - if info_sector is 0, don't multiply by 0 */ - sbi->fsinfo_sector = le16_to_cpu(b->info_sector); + sbi->fsinfo_sector = le16_to_cpu(b->fat32.info_sector); if (sbi->fsinfo_sector == 0) sbi->fsinfo_sector = 1; diff -puN include/uapi/linux/msdos_fs.h~fat-check-dirty-1 include/uapi/linux/msdos_fs.h --- linux/include/uapi/linux/msdos_fs.h~fat-check-dirty-1 2012-12-28 02:17:39.000000000 +0900 +++ linux-hirofumi/include/uapi/linux/msdos_fs.h 2012-12-28 02:17:39.000000000 +0900 @@ -120,14 +120,34 @@ struct fat_boot_sector { __le32 hidden; /* hidden sectors (unused) */ __le32 total_sect; /* number of sectors (if sectors == 0) */ - /* The following fields are only used by FAT32 */ - __le32 fat32_length; /* sectors/FAT */ - __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ - __u8 version[2]; /* major, minor filesystem version */ - __le32 root_cluster; /* first cluster in root directory */ - __le16 info_sector; /* filesystem info sector */ - __le16 backup_boot; /* backup boot sector */ - __le16 reserved2[6]; /* Unused */ + union { + struct { + /* Extended BPB Fields for FAT16 */ + __u8 drive_number; /* Physical drive number */ + __u8 state; /* undocumented, but used + for mount state. */ + /* other fiealds are not added here */ + } fat16; + + struct { + /* only used by FAT32 */ + __le32 length; /* sectors/FAT */ + __le16 flags; /* bit 8: fat mirroring, + low 4: active fat */ + __u8 version[2]; /* major, minor filesystem + version */ + __le32 root_cluster; /* first cluster in + root directory */ + __le16 info_sector; /* filesystem info sector */ + __le16 backup_boot; /* backup boot sector */ + __le16 reserved2[6]; /* Unused */ + /* Extended BPB Fields for FAT32 */ + __u8 drive_number; /* Physical drive number */ + __u8 state; /* undocumented, but used + for mount state. */ + /* other fiealds are not added here */ + } fat32; + }; }; struct fat_boot_fsinfo { _ -- OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/2] fat: mark fs as dirty on mount and clean on umount 2012-12-27 17:19 [PATCH 1/2] fat: add extended fileds to struct fat_boot_sector OGAWA Hirofumi @ 2012-12-27 17:20 ` OGAWA Hirofumi 2013-01-02 23:44 ` Andrew Morton 0 siblings, 1 reply; 4+ messages in thread From: OGAWA Hirofumi @ 2012-12-27 17:20 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, linux-fsdevel, bug-track From: Oleksij Rempel <bug-track@fisher-privat.net> 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 fallow: - 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. patch history: - v2. do not warn on read-only. Some style fixes. - v3. make fat_set_state static. - v4. add "force" variable to fat_set_state and use it on remount ro to rw. Signed-off-by: Oleksij Rempel <bug-track@fisher-privat.net> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> --- fs/fat/fat.h | 2 + fs/fat/inode.c | 66 +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/msdos_fs.h | 2 + 3 files changed, 70 insertions(+) diff -puN fs/fat/fat.h~fat-check-dirty-2 fs/fat/fat.h --- linux/fs/fat/fat.h~fat-check-dirty-2 2012-12-28 02:17:42.000000000 +0900 +++ linux-hirofumi/fs/fat/fat.h 2012-12-28 02:17:42.000000000 +0900 @@ -95,6 +95,8 @@ struct msdos_sb_info { spinlock_t dir_hash_lock; struct hlist_head dir_hashtable[FAT_HASH_SIZE]; + + unsigned int dirty; /* fs state before mount */ }; #define FAT_CACHE_VALID 0 /* special case for valid cache */ diff -puN fs/fat/inode.c~fat-check-dirty-2 fs/fat/inode.c --- linux/fs/fat/inode.c~fat-check-dirty-2 2012-12-28 02:17:42.000000000 +0900 +++ linux-hirofumi/fs/fat/inode.c 2012-12-28 02:17:42.000000000 +0900 @@ -488,10 +488,59 @@ static void fat_evict_inode(struct inode fat_detach(inode); } +static void fat_set_state(struct super_block *sb, + unsigned int set, unsigned int force) +{ + struct buffer_head *bh; + struct fat_boot_sector *b; + struct msdos_sb_info *sbi = sb->s_fs_info; + + /* do not change any thing if mounted read only */ + if ((sb->s_flags & MS_RDONLY) && !force) + return; + + /* do not change state if fs was dirty */ + if (sbi->dirty) { + /* warn only on set (mount). */ + if (set) + fat_msg(sb, KERN_WARNING, "Volume was not properly " + "unmounted. Some data may be corrupt. " + "Please run fsck."); + return; + } + + bh = sb_bread(sb, 0); + if (bh == NULL) { + fat_msg(sb, KERN_ERR, "unable to read boot sector " + "to mark fs as dirty"); + return; + } + + b = (struct fat_boot_sector *) bh->b_data; + + if (sbi->fat_bits == 32) { + if (set) + b->fat32.state |= FAT_STATE_DIRTY; + else + b->fat32.state &= ~FAT_STATE_DIRTY; + } else /* fat 16 and 12 */ { + if (set) + b->fat16.state |= FAT_STATE_DIRTY; + else + b->fat16.state &= ~FAT_STATE_DIRTY; + } + + mark_buffer_dirty(bh); + sync_dirty_buffer(bh); + brelse(bh); +} + static void fat_put_super(struct super_block *sb) { struct msdos_sb_info *sbi = MSDOS_SB(sb); + fat_set_state(sb, 0, 0); + iput(sbi->fsinfo_inode); iput(sbi->fat_inode); @@ -566,8 +615,18 @@ static void __exit fat_destroy_inodecach static int fat_remount(struct super_block *sb, int *flags, char *data) { + int new_rdonly; struct msdos_sb_info *sbi = MSDOS_SB(sb); *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME); + + /* make sure we update state on remount. */ + new_rdonly = *flags & MS_RDONLY; + if (new_rdonly != (sb->s_flags & MS_RDONLY)) { + if (new_rdonly) + fat_set_state(sb, 0, 0); + else + fat_set_state(sb, 1, 1); + } return 0; } @@ -1362,6 +1421,12 @@ int fat_fill_super(struct super_block *s if (sbi->fat_bits != 32) sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; + /* some OSes set FAT_STATE_DIRTY and clean it on unmount. */ + if (sbi->fat_bits == 32) + sbi->dirty = b->fat32.state & FAT_STATE_DIRTY; + else /* fat 16 or 12 */ + sbi->dirty = b->fat16.state & FAT_STATE_DIRTY; + /* check that FAT table does not overflow */ fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); @@ -1456,6 +1521,7 @@ int fat_fill_super(struct super_block *s "the device does not support discard"); } + fat_set_state(sb, 1, 0); return 0; out_invalid: diff -puN include/uapi/linux/msdos_fs.h~fat-check-dirty-2 include/uapi/linux/msdos_fs.h --- linux/include/uapi/linux/msdos_fs.h~fat-check-dirty-2 2012-12-28 02:17:42.000000000 +0900 +++ linux-hirofumi/include/uapi/linux/msdos_fs.h 2012-12-28 02:17:42.000000000 +0900 @@ -87,6 +87,8 @@ #define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) +#define FAT_STATE_DIRTY 0x01 + struct __fat_dirent { long d_ino; __kernel_off_t d_off; _ -- OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] fat: mark fs as dirty on mount and clean on umount 2012-12-27 17:20 ` [PATCH 2/2] fat: mark fs as dirty on mount and clean on umount OGAWA Hirofumi @ 2013-01-02 23:44 ` Andrew Morton 2013-01-03 8:46 ` Oleksij Rempel 0 siblings, 1 reply; 4+ messages in thread From: Andrew Morton @ 2013-01-02 23:44 UTC (permalink / raw) To: OGAWA Hirofumi; +Cc: linux-kernel, linux-fsdevel, bug-track On Fri, 28 Dec 2012 02:20:20 +0900 OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> wrote: > 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 fallow: > - 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. The changelog doesn't describe why we're making this change. Nor does it describe the user-visible effects of this change. AFAICT the effect is to issue a warning at mount-time to tell the user that the fs wasn't cleanly unmounted and that the user should fsck the volume, correct? If so, why is this considered a desirable feature? (I can guess, but would prefer to hear it spelled out by the experts, please). ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] fat: mark fs as dirty on mount and clean on umount 2013-01-02 23:44 ` Andrew Morton @ 2013-01-03 8:46 ` Oleksij Rempel 0 siblings, 0 replies; 4+ messages in thread From: Oleksij Rempel @ 2013-01-03 8:46 UTC (permalink / raw) To: Andrew Morton; +Cc: OGAWA Hirofumi, linux-kernel, linux-fsdevel Am 03.01.2013 00:44, schrieb Andrew Morton: > On Fri, 28 Dec 2012 02:20:20 +0900 > OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> wrote: > >> 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 fallow: >> - 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. > > The changelog doesn't describe why we're making this change. Nor does > it describe the user-visible effects of this change. > > AFAICT the effect is to issue a warning at mount-time to tell the > user that the fs wasn't cleanly unmounted and that the user should fsck > the volume, correct? > > If so, why is this considered a desirable feature? (I can guess, but > would prefer to hear it spelled out by the experts, please). > FAT is old and still intensively used file system with high number of data lost. This patch set is a try to reduce this numbers. To make this work complete, we need some changes in user space too. But even stand alone, this patchset can warn M$ Windows 7 about probably damaged FS. In this case Win 7 will inform user and give option to start checkdisk. -- Regards, Oleksij ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-01-03 8:46 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-12-27 17:19 [PATCH 1/2] fat: add extended fileds to struct fat_boot_sector OGAWA Hirofumi 2012-12-27 17:20 ` [PATCH 2/2] fat: mark fs as dirty on mount and clean on umount OGAWA Hirofumi 2013-01-02 23:44 ` Andrew Morton 2013-01-03 8:46 ` Oleksij Rempel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).