Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=98283bb49c6c8c070ebde9f47489d3e9a83c1323
Commit:     98283bb49c6c8c070ebde9f47489d3e9a83c1323
Parent:     347e03df1696ab22963f6b8c4f2220c41ec17f82
Author:     OGAWA Hirofumi <[EMAIL PROTECTED]>
AuthorDate: Mon Jul 16 09:40:05 2007 +0900
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 10:31:01 2007 -0700

    fat: Fix the race of read/write the FAT12 entry
    
    FAT12 entry is 12bits, so it needs 2 phase to update the value.  And
    writer and reader access it without any lock, so reader can get the
    half updated value.
    
    This fixes the long standing race condition by adding a global
    spinlock to only FAT12 for avoiding any impact against FAT16/32.
    
    Signed-off-by: OGAWA Hirofumi <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/fat/fatent.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index ab171ea..2c1b73f 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -17,6 +17,8 @@ struct fatent_operations {
        int (*ent_next)(struct fat_entry *);
 };
 
+static DEFINE_SPINLOCK(fat12_entry_lock);
+
 static void fat12_ent_blocknr(struct super_block *sb, int entry,
                              int *offset, sector_t *blocknr)
 {
@@ -116,10 +118,13 @@ static int fat12_ent_get(struct fat_entry *fatent)
        u8 **ent12_p = fatent->u.ent12_p;
        int next;
 
+       spin_lock(&fat12_entry_lock);
        if (fatent->entry & 1)
                next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
        else
                next = (*ent12_p[1] << 8) | *ent12_p[0];
+       spin_unlock(&fat12_entry_lock);
+
        next &= 0x0fff;
        if (next >= BAD_FAT12)
                next = FAT_ENT_EOF;
@@ -151,6 +156,7 @@ static void fat12_ent_put(struct fat_entry *fatent, int new)
        if (new == FAT_ENT_EOF)
                new = EOF_FAT12;
 
+       spin_lock(&fat12_entry_lock);
        if (fatent->entry & 1) {
                *ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
                *ent12_p[1] = new >> 4;
@@ -158,6 +164,7 @@ static void fat12_ent_put(struct fat_entry *fatent, int new)
                *ent12_p[0] = new & 0xff;
                *ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
        }
+       spin_unlock(&fat12_entry_lock);
 
        mark_buffer_dirty(fatent->bhs[0]);
        if (fatent->nr_bhs == 2)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to