lkml.org 
[lkml]   [2001]   [May]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] big-sector support with FAT
    From
    Date
    Hi,

    I fixed it to dynamically change block size with logical_sector_size
    of FAT. The device of bigger sector-size than 512 can be handled by
    this change.

    There is the following:

    1) blocksize is fixed when a file system is created.
    2) logical_sector_size < sector-size of the device is not supported.

    But, Windows{95,2k} doesn't support 2) too.

    I think the 1) and 2) a no problem.

    Please apply.
    Thanks.
    --
    OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

    diff -urP linux-2.4.5-pre5/fs/fat/buffer.c linux-2.4.5-pre5-fat/fs/fat/buffer.c
    --- linux-2.4.5-pre5/fs/fat/buffer.c Sat Feb 10 04:29:44 2001
    +++ linux-2.4.5-pre5-fat/fs/fat/buffer.c Wed May 16 03:51:40 2001
    @@ -8,6 +8,7 @@
    #include <linux/slab.h>
    #include <linux/string.h>
    #include <linux/fs.h>
    +#include <linux/blkdev.h>
    #include <linux/msdos_fs.h>
    #include <linux/fat_cvf.h>

    @@ -58,22 +59,26 @@

    struct buffer_head *default_fat_bread(struct super_block *sb, int block)
    {
    - return bread (sb->s_dev,block,512);
    + return bread (sb->s_dev, block, sb->s_blocksize);
    }
    +
    struct buffer_head *default_fat_getblk(struct super_block *sb, int block)
    {
    - return getblk (sb->s_dev,block,512);
    + return getblk (sb->s_dev, block, sb->s_blocksize);
    }
    +
    void default_fat_brelse(struct super_block *sb, struct buffer_head *bh)
    {
    brelse (bh);
    }
    +
    void default_fat_mark_buffer_dirty (
    struct super_block *sb,
    struct buffer_head *bh)
    {
    mark_buffer_dirty (bh);
    }
    +
    void default_fat_set_uptodate (
    struct super_block *sb,
    struct buffer_head *bh,
    @@ -81,10 +86,12 @@
    {
    mark_buffer_uptodate(bh, val);
    }
    +
    int default_fat_is_uptodate (struct super_block *sb, struct buffer_head *bh)
    {
    return buffer_uptodate(bh);
    }
    +
    void default_fat_ll_rw_block (
    struct super_block *sb,
    int opr,
    @@ -94,109 +101,61 @@
    ll_rw_block(opr,nbreq,bh);
    }

    -struct buffer_head *bigblock_fat_bread (
    - struct super_block *sb,
    - int block)
    +struct buffer_head *bigblock_fat_bread(struct super_block *sb, int block)
    {
    - struct buffer_head *ret = NULL;
    - struct buffer_head *real;
    - if (sb->s_blocksize == 1024){
    - real = bread (sb->s_dev,block>>1,1024);
    - } else {
    - real = bread (sb->s_dev,block>>2,2048);
    - }
    -
    + unsigned int hardsect = get_hardsect_size(sb->s_dev);
    + int rblock, roffset;
    + struct buffer_head *real, *dummy;
    +
    + if (hardsect <= sb->s_blocksize)
    + BUG();
    +
    + dummy = NULL;
    + rblock = block / (hardsect / sb->s_blocksize);
    + roffset = (block % (hardsect / sb->s_blocksize)) * sb->s_blocksize;
    + real = bread(sb->s_dev, rblock, hardsect);
    if (real != NULL) {
    - ret = (struct buffer_head *)
    - kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
    - if (ret != NULL) {
    - /* #Specification: msdos / strategy / special device / dummy blocks
    - * Many special device (Scsi optical disk for one) use
    - * larger hardware sector size. This allows for higher
    - * capacity.
    -
    - * Most of the time, the MS-DOS filesystem that sits
    - * on this device is totally unaligned. It use logically
    - * 512 bytes sector size, with logical sector starting
    - * in the middle of a hardware block. The bad news is
    - * that a hardware sector may hold data own by two
    - * different files. This means that the hardware sector
    - * must be read, patch and written almost all the time.
    -
    - * Needless to say that it kills write performance
    - * on all OS.
    -
    - * Internally the linux msdos fs is using 512 bytes
    - * logical sector. When accessing such a device, we
    - * allocate dummy buffer cache blocks, that we stuff
    - * with the information of a real one (1k large).
    -
    - * This strategy is used to hide this difference to
    - * the core of the msdos fs. The slowdown is not
    - * hidden though!
    - */
    - /*
    - * The memset is there only to catch errors. The msdos
    - * fs is only using b_data
    - */
    - memset (ret,0,sizeof(*ret));
    - ret->b_data = real->b_data;
    - if (sb->s_blocksize == 2048) {
    - if (block & 3) ret->b_data += (block & 3) << 9;
    - }else{
    - if (block & 1) ret->b_data += 512;
    - }
    - ret->b_next = real;
    - }else{
    - brelse (real);
    - }
    + dummy = kmalloc(sizeof(struct buffer_head), GFP_KERNEL);
    + if (dummy != NULL) {
    + memset(dummy, 0, sizeof(*dummy));
    + dummy->b_data = real->b_data + roffset;
    + dummy->b_next = real;
    + } else
    + brelse(real);
    }
    - return ret;
    +
    + return dummy;
    }

    -void bigblock_fat_brelse (
    - struct super_block *sb,
    - struct buffer_head *bh)
    +void bigblock_fat_brelse(struct super_block *sb, struct buffer_head *bh)
    {
    - brelse (bh->b_next);
    - /*
    - * We can free the dummy because a new one is allocated at
    - * each fat_getblk() and fat_bread().
    - */
    - kfree (bh);
    + brelse(bh->b_next);
    + kfree(bh);
    }

    -void bigblock_fat_mark_buffer_dirty (
    - struct super_block *sb,
    - struct buffer_head *bh)
    +void bigblock_fat_mark_buffer_dirty(struct super_block *sb, struct buffer_head *bh)
    {
    - mark_buffer_dirty (bh->b_next);
    + mark_buffer_dirty(bh->b_next);
    }

    -void bigblock_fat_set_uptodate (
    - struct super_block *sb,
    - struct buffer_head *bh,
    - int val)
    +void bigblock_fat_set_uptodate(struct super_block *sb, struct buffer_head *bh,
    + int val)
    {
    mark_buffer_uptodate(bh->b_next, val);
    }

    -int bigblock_fat_is_uptodate (
    - struct super_block *sb,
    - struct buffer_head *bh)
    +int bigblock_fat_is_uptodate(struct super_block *sb, struct buffer_head *bh)
    {
    return buffer_uptodate(bh->b_next);
    }

    -void bigblock_fat_ll_rw_block (
    - struct super_block *sb,
    - int opr,
    - int nbreq,
    - struct buffer_head *bh[32])
    +void bigblock_fat_ll_rw_block (struct super_block *sb, int opr, int nbreq,
    + struct buffer_head *bh[32])
    {
    struct buffer_head *tmp[32];
    int i;
    - for (i=0; i<nbreq; i++)
    +
    + for (i = 0; i < nbreq; i++)
    tmp[i] = bh[i]->b_next;
    - ll_rw_block(opr,nbreq,tmp);
    + ll_rw_block(opr, nbreq, tmp);
    }
    diff -urP linux-2.4.5-pre5/fs/fat/cache.c linux-2.4.5-pre5-fat/fs/fat/cache.c
    --- linux-2.4.5-pre5/fs/fat/cache.c Tue Jan 16 11:58:04 2001
    +++ linux-2.4.5-pre5-fat/fs/fat/cache.c Tue May 15 02:37:47 2001
    @@ -41,9 +41,9 @@

    int default_fat_access(struct super_block *sb,int nr,int new_value)
    {
    - struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
    - unsigned char *p_first,*p_last;
    - int copy,first,last,next,b;
    + struct buffer_head *bh, *bh2, *c_bh, *c_bh2;
    + unsigned char *p_first, *p_last;
    + int copy, first, last, next, b;

    if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
    return 0;
    @@ -55,12 +55,12 @@
    first = nr*3/2;
    last = first+1;
    }
    - b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS);
    + b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits);
    if (!(bh = fat_bread(sb, b))) {
    printk("bread in fat_access failed\n");
    return 0;
    }
    - if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) {
    + if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) {
    bh2 = bh;
    } else {
    if (!(bh2 = fat_bread(sb, b+1))) {
    @@ -72,7 +72,7 @@
    if (MSDOS_SB(sb)->fat_bits == 32) {
    p_first = p_last = NULL; /* GCC needs that stuff */
    next = CF_LE_L(((__u32 *) bh->b_data)[(first &
    - (SECTOR_SIZE-1)) >> 2]);
    + (sb->s_blocksize - 1)) >> 2]);
    /* Fscking Microsoft marketing department. Their "32" is 28. */
    next &= 0xfffffff;
    if (next >= 0xffffff7) next = -1;
    @@ -81,23 +81,22 @@
    } else if (MSDOS_SB(sb)->fat_bits == 16) {
    p_first = p_last = NULL; /* GCC needs that stuff */
    next = CF_LE_W(((__u16 *) bh->b_data)[(first &
    - (SECTOR_SIZE-1)) >> 1]);
    + (sb->s_blocksize - 1)) >> 1]);
    if (next >= 0xfff7) next = -1;
    } else {
    - p_first = &((__u8 *) bh->b_data)[first & (SECTOR_SIZE-1)];
    - p_last = &((__u8 *) bh2->b_data)[(first+1) &
    - (SECTOR_SIZE-1)];
    + p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
    + p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)];
    if (nr & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
    else next = (*p_first+(*p_last << 8)) & 0xfff;
    if (next >= 0xff7) next = -1;
    }
    if (new_value != -1) {
    if (MSDOS_SB(sb)->fat_bits == 32) {
    - ((__u32 *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
    - 2] = CT_LE_L(new_value);
    + ((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
    + = CT_LE_L(new_value);
    } else if (MSDOS_SB(sb)->fat_bits == 16) {
    - ((__u16 *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
    - 1] = CT_LE_W(new_value);
    + ((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
    + = CT_LE_W(new_value);
    } else {
    if (nr & 1) {
    *p_first = (*p_first & 0xf) | (new_value << 4);
    @@ -111,20 +110,21 @@
    }
    fat_mark_buffer_dirty(sb, bh);
    for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
    - b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS) +
    - MSDOS_SB(sb)->fat_length * copy;
    + b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits)
    + + MSDOS_SB(sb)->fat_length * copy;
    if (!(c_bh = fat_bread(sb, b)))
    break;
    - memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE);
    - fat_mark_buffer_dirty(sb, c_bh);
    if (bh != bh2) {
    if (!(c_bh2 = fat_bread(sb, b+1))) {
    fat_brelse(sb, c_bh);
    break;
    }
    - memcpy(c_bh2->b_data,bh2->b_data,SECTOR_SIZE);
    + memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize);
    + fat_mark_buffer_dirty(sb, c_bh2);
    fat_brelse(sb, c_bh2);
    }
    + memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
    + fat_mark_buffer_dirty(sb, c_bh);
    fat_brelse(sb, c_bh);
    }
    }
    @@ -143,7 +143,7 @@
    if (initialized) {
    spin_unlock(&fat_cache_lock);
    return;
    - }
    + }
    fat_cache = &cache[0];
    for (count = 0; count < FAT_CACHE; count++) {
    cache[count].device = 0;
    @@ -294,22 +294,28 @@

    int default_fat_bmap(struct inode *inode,int sector)
    {
    - struct msdos_sb_info *sb=MSDOS_SB(inode->i_sb);
    - int cluster,offset;
    + struct super_block *sb = inode->i_sb;
    + struct msdos_sb_info *sbi = MSDOS_SB(sb);
    + int cluster, offset, last_block;

    - if ((sb->fat_bits != 32) &&
    + if ((sbi->fat_bits != 32) &&
    (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
    !MSDOS_I(inode)->i_start))) {
    - if (sector >= sb->dir_entries >> MSDOS_DPS_BITS)
    + if (sector >= sbi->dir_entries >> sbi->dir_per_block_bits)
    return 0;
    - return sector+sb->dir_start;
    + return sector + sbi->dir_start;
    }
    - if (sector >= (MSDOS_I(inode)->mmu_private+511)>>9)
    + last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
    + >> sb->s_blocksize_bits;
    + if (sector >= last_block)
    return 0;
    - cluster = sector/sb->cluster_size;
    - offset = sector % sb->cluster_size;
    - if (!(cluster = fat_get_cluster(inode,cluster))) return 0;
    - return (cluster-2)*sb->cluster_size+sb->data_start+offset;
    +
    + cluster = sector / sbi->cluster_size;
    + offset = sector % sbi->cluster_size;
    + if (!(cluster = fat_get_cluster(inode, cluster)))
    + return 0;
    +
    + return (cluster - 2) * sbi->cluster_size + sbi->data_start + offset;
    }


    @@ -351,7 +357,7 @@
    fat_clusters_flush(inode->i_sb);
    }
    }
    - inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
    + inode->i_blocks -= (1 << MSDOS_SB(inode->i_sb)->cluster_bits) / 512;
    }
    unlock_fat(inode->i_sb);
    return 0;
    diff -urP linux-2.4.5-pre5/fs/fat/file.c linux-2.4.5-pre5-fat/fs/fat/file.c
    --- linux-2.4.5-pre5/fs/fat/file.c Thu Apr 13 01:47:29 2000
    +++ linux-2.4.5-pre5-fat/fs/fat/file.c Tue May 15 02:37:47 2001
    @@ -54,8 +54,11 @@
    }


    -int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) {
    +int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
    +{
    + struct super_block *sb = inode->i_sb;
    unsigned long phys;
    +
    phys = fat_bmap(inode, iblock);
    if (phys) {
    bh_result->b_dev = inode->i_dev;
    @@ -65,7 +68,7 @@
    }
    if (!create)
    return 0;
    - if (iblock<<9 != MSDOS_I(inode)->mmu_private) {
    + if (iblock << sb->s_blocksize_bits != MSDOS_I(inode)->mmu_private) {
    BUG();
    return -EIO;
    }
    @@ -73,8 +76,8 @@
    if (fat_add_cluster(inode))
    return -ENOSPC;
    }
    - MSDOS_I(inode)->mmu_private += 512;
    - phys=fat_bmap(inode, iblock);
    + MSDOS_I(inode)->mmu_private += sb->s_blocksize;
    + phys = fat_bmap(inode, iblock);
    if (!phys)
    BUG();
    bh_result->b_dev = inode->i_dev;
    @@ -124,7 +127,7 @@
    return /* -EPERM */;
    if (IS_IMMUTABLE(inode))
    return /* -EPERM */;
    - cluster = SECTOR_SIZE*sbi->cluster_size;
    + cluster = 1 << sbi->cluster_bits;
    /*
    * This protects against truncating a file bigger than it was then
    * trying to write into the hole.
    @@ -132,7 +135,7 @@
    if (MSDOS_I(inode)->mmu_private > inode->i_size)
    MSDOS_I(inode)->mmu_private = inode->i_size;

    - fat_free(inode,(inode->i_size+(cluster-1))>>sbi->cluster_bits);
    + fat_free(inode, (inode->i_size + (cluster - 1)) >> sbi->cluster_bits);
    MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
    inode->i_ctime = inode->i_mtime = CURRENT_TIME;
    mark_inode_dirty(inode);
    diff -urP linux-2.4.5-pre5/fs/fat/inode.c linux-2.4.5-pre5-fat/fs/fat/inode.c
    --- linux-2.4.5-pre5/fs/fat/inode.c Thu Apr 19 03:49:12 2001
    +++ linux-2.4.5-pre5-fat/fs/fat/inode.c Wed May 23 03:13:07 2001
    @@ -201,7 +201,7 @@
    }


    -static int parse_options(char *options,int *fat, int *blksize, int *debug,
    +static int parse_options(char *options,int *fat, int *debug,
    struct fat_mount_options *opts,
    char *cvf_format, char *cvf_options)
    {
    @@ -310,13 +310,8 @@
    else opts->quiet = 1;
    }
    else if (!strcmp(this_char,"blocksize")) {
    - if (!value || !*value) ret = 0;
    - else {
    - *blksize = simple_strtoul(value,&value,0);
    - if (*value || (*blksize != 512 &&
    - *blksize != 1024 && *blksize != 2048))
    - ret = 0;
    - }
    + printk("FAT: blocksize option is obsolete, "
    + "not supported now\n");
    }
    else if (!strcmp(this_char,"sys_immutable")) {
    if (value) ret = 0;
    @@ -383,8 +378,8 @@
    MSDOS_I(inode)->i_start = sbi->root_cluster;
    if ((nr = MSDOS_I(inode)->i_start) != 0) {
    while (nr != -1) {
    - inode->i_size += SECTOR_SIZE*sbi->cluster_size;
    - if (!(nr = fat_access(sb,nr,-1))) {
    + inode->i_size += 1 << sbi->cluster_bits;
    + if (!(nr = fat_access(sb, nr, -1))) {
    printk("Directory %ld: bad FAT\n",
    inode->i_ino);
    break;
    @@ -393,13 +388,11 @@
    }
    } else {
    MSDOS_I(inode)->i_start = 0;
    - inode->i_size = sbi->dir_entries*
    - sizeof(struct msdos_dir_entry);
    + inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
    }
    - inode->i_blksize = sbi->cluster_size* SECTOR_SIZE;
    - inode->i_blocks =
    - ((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *
    - sbi->cluster_size;
    + inode->i_blksize = 1 << sbi->cluster_bits;
    + inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
    + & ~(inode->i_blksize - 1)) / 512;
    MSDOS_I(inode)->i_logstart = 0;
    MSDOS_I(inode)->mmu_private = inode->i_size;

    @@ -432,10 +425,9 @@
    struct fat_boot_sector *b;
    struct msdos_sb_info *sbi = MSDOS_SB(sb);
    char *p;
    - int data_sectors,logical_sector_size,sector_mult,fat_clusters=0;
    - int debug,error,fat,cp;
    - int blksize;
    - int fat32;
    + int logical_sector_size, hard_blksize, fat_clusters = 0;
    + unsigned int total_sectors, rootdir_sectors;
    + int fat32, debug, error, fat, cp;
    struct fat_mount_options opts;
    char buf[50];
    int i;
    @@ -451,35 +443,26 @@

    sb->s_maxbytes = MAX_NON_LFS;
    sb->s_op = &fat_sops;
    - blksize = get_hardsect_size(sb->s_dev);
    - if (!blksize)
    - blksize = 512;
    - if (blksize != 512)
    - printk ("MSDOS: Hardware sector size is %d\n",blksize);
    +
    + hard_blksize = get_hardsect_size(sb->s_dev);
    + if (!hard_blksize)
    + hard_blksize = 512;
    + if (hard_blksize != 512)
    + printk("MSDOS: Hardware sector size is %d\n", hard_blksize);

    opts.isvfat = sbi->options.isvfat;
    - if (!parse_options((char *) data, &fat, &blksize, &debug, &opts,
    - cvf_format, cvf_options)
    - || (blksize != 512 && blksize != 1024 && blksize != 2048))
    + if (!parse_options((char *) data, &fat, &debug, &opts,
    + cvf_format, cvf_options))
    goto out_fail;
    /* N.B. we should parse directly into the sb structure */
    memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options));

    fat_cache_init();
    - if( blksize > 1024 )
    - {
    - /* Force the superblock to a larger size here. */
    - sb->s_blocksize = blksize;
    - set_blocksize(sb->s_dev, blksize);
    - }
    - else
    - {
    - /* The first read is always 1024 bytes */
    - sb->s_blocksize = 1024;
    - set_blocksize(sb->s_dev, 1024);
    - }
    +
    + sb->s_blocksize = hard_blksize;
    + set_blocksize(sb->s_dev, hard_blksize);
    bh = bread(sb->s_dev, 0, sb->s_blocksize);
    - if (bh == NULL || !buffer_uptodate(bh)) {
    + if (bh == NULL) {
    brelse (bh);
    goto out_no_bread;
    }
    @@ -499,110 +482,122 @@
    * (by Drew Eckhardt)
    */

    -#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
    - /* don't divide by zero */

    b = (struct fat_boot_sector *) bh->b_data;
    logical_sector_size =
    CF_LE_W(get_unaligned((unsigned short *) &b->sector_size));
    - sector_mult = logical_sector_size >> SECTOR_BITS;
    - sbi->cluster_size = b->cluster_size*sector_mult;
    - if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size-1))) {
    - printk("fatfs: bogus cluster size\n");
    + if (!logical_sector_size
    + || (logical_sector_size & (logical_sector_size - 1))) {
    + printk("fatfs: bogus logical sector size %d\n",
    + logical_sector_size);
    + brelse(bh);
    + goto out_invalid;
    + }
    +
    + sbi->cluster_size = b->cluster_size;
    + if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size - 1))) {
    + printk("fatfs: bogus cluster size %d\n", sbi->cluster_size);
    brelse(bh);
    goto out_invalid;
    }
    - for (sbi->cluster_bits=0;
    - 1<<sbi->cluster_bits<sbi->cluster_size;
    - sbi->cluster_bits++)
    - ;
    - sbi->cluster_bits += SECTOR_BITS;
    +
    + sbi->cluster_bits = ffs(logical_sector_size * sbi->cluster_size) - 1;
    sbi->fats = b->fats;
    - sbi->fat_start = CF_LE_W(b->reserved)*sector_mult;
    + sbi->fat_start = CF_LE_W(b->reserved);
    if (!b->fat_length && b->fat32_length) {
    struct fat_boot_fsinfo *fsinfo;
    + struct buffer_head *fsinfo_bh;
    + int fsinfo_block, fsinfo_offset;

    /* Must be FAT32 */
    fat32 = 1;
    - sbi->fat_length= CF_LE_L(b->fat32_length)*sector_mult;
    + sbi->fat_length = CF_LE_L(b->fat32_length);
    sbi->root_cluster = CF_LE_L(b->root_cluster);

    + sbi->fsinfo_sector = CF_LE_W(b->info_sector);
    /* MC - if info_sector is 0, don't multiply by 0 */
    - if(CF_LE_W(b->info_sector) == 0) {
    - sbi->fsinfo_offset =
    - logical_sector_size + 0x1e0;
    - } else {
    - sbi->fsinfo_offset =
    - (CF_LE_W(b->info_sector) * logical_sector_size)
    - + 0x1e0;
    - }
    - if (sbi->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) {
    - printk("fat_read_super: Bad fsinfo_offset\n");
    - brelse(bh);
    - goto out_invalid;
    - }
    - fsinfo = (struct fat_boot_fsinfo *)
    - &bh->b_data[sbi->fsinfo_offset];
    - if (CF_LE_L(fsinfo->signature) != 0x61417272) {
    - printk("fat_read_super: Did not find valid FSINFO "
    - "signature. Found 0x%x\n",
    - CF_LE_L(fsinfo->signature));
    + if (sbi->fsinfo_sector == 0)
    + sbi->fsinfo_sector = 1;
    +
    + fsinfo_block =
    + (sbi->fsinfo_sector * logical_sector_size) / hard_blksize;
    + fsinfo_offset =
    + (sbi->fsinfo_sector * logical_sector_size) % hard_blksize;
    + fsinfo_bh = bh;
    + if (bh->b_blocknr != fsinfo_block) {
    + fsinfo_bh = bread(sb->s_dev, fsinfo_block, hard_blksize);
    + if (fsinfo_bh == NULL) {
    + printk("FAT: bread failed, fsinfo block %d\n",
    + fsinfo_block);
    + brelse(bh);
    + goto out_invalid;
    + }
    + }
    + fsinfo = (struct fat_boot_fsinfo *)&fsinfo_bh->b_data[fsinfo_offset];
    + if (!IS_FSINFO(fsinfo)) {
    + printk("FAT: Did not find valid FSINFO signature.\n"
    + "Found signature1 0x%x signature2 0x%x sector=%ld.\n",
    + CF_LE_L(fsinfo->signature1),
    + CF_LE_L(fsinfo->signature2),
    + sbi->fsinfo_sector);
    } else {
    sbi->free_clusters = CF_LE_L(fsinfo->free_clusters);
    }
    +
    + if (bh->b_blocknr != fsinfo_block)
    + brelse(fsinfo_bh);
    } else {
    fat32 = 0;
    - sbi->fat_length = CF_LE_W(b->fat_length)*sector_mult;
    + sbi->fat_length = CF_LE_W(b->fat_length);
    sbi->root_cluster = 0;
    sbi->free_clusters = -1; /* Don't know yet */
    }
    - sbi->dir_start= CF_LE_W(b->reserved)*sector_mult+
    - b->fats*sbi->fat_length;
    +
    + sbi->dir_per_block = logical_sector_size / sizeof(struct msdos_dir_entry);
    + sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
    +
    + sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
    sbi->dir_entries =
    - CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries));
    - sbi->data_start = sbi->dir_start+ROUND_TO_MULTIPLE((
    - sbi->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
    - sector_mult);
    - data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors));
    - if (!data_sectors) {
    - data_sectors = CF_LE_L(b->total_sect);
    - }
    - data_sectors = data_sectors * sector_mult - sbi->data_start;
    - error = !b->cluster_size || !sector_mult;
    + CF_LE_W(get_unaligned((unsigned short *)&b->dir_entries));
    + rootdir_sectors = sbi->dir_entries
    + * sizeof(struct msdos_dir_entry) / logical_sector_size;
    + sbi->data_start = sbi->dir_start + rootdir_sectors;
    + total_sectors = CF_LE_W(get_unaligned((unsigned short *)&b->sectors));
    + if (total_sectors == 0)
    + total_sectors = CF_LE_L(b->total_sect);
    + sbi->clusters = (total_sectors - sbi->data_start) / sbi->cluster_size;
    +
    + error = 0;
    if (!error) {
    - sbi->clusters = b->cluster_size ? data_sectors/
    - b->cluster_size/sector_mult : 0;
    sbi->fat_bits = fat32 ? 32 :
    (fat ? fat :
    (sbi->clusters > MSDOS_FAT12 ? 16 : 12));
    - fat_clusters = sbi->fat_length*SECTOR_SIZE*8/
    - sbi->fat_bits;
    - error = !sbi->fats || (sbi->dir_entries &
    - (MSDOS_DPS-1)) || sbi->clusters+2 > fat_clusters+
    - MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1))
    - || !b->secs_track || !b->heads;
    + fat_clusters =
    + sbi->fat_length * logical_sector_size * 8 / sbi->fat_bits;
    + error = !sbi->fats || (sbi->dir_entries & (sbi->dir_per_block - 1))
    + || sbi->clusters + 2 > fat_clusters + MSDOS_MAX_EXTRA
    + || logical_sector_size < 512
    + || PAGE_CACHE_SIZE < logical_sector_size
    + || !b->secs_track || !b->heads;
    }
    brelse(bh);
    - set_blocksize(sb->s_dev, blksize);
    - /*
    - This must be done after the brelse because the bh is a dummy
    - allocated by fat_bread (see buffer.c)
    - */
    - sb->s_blocksize = blksize; /* Using this small block size solves */
    - /* the misfit with buffer cache and cluster */
    - /* because clusters (DOS) are often aligned */
    - /* on odd sectors. */
    - sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11);
    +
    + sb->s_blocksize = logical_sector_size;
    + sb->s_blocksize_bits = ffs(logical_sector_size) - 1;
    + if (sb->s_blocksize >= hard_blksize) {
    + set_blocksize(sb->s_dev, sb->s_blocksize);
    + sbi->cvf_format = &default_cvf;
    + } else {
    + set_blocksize(sb->s_dev, hard_blksize);
    + sbi->cvf_format = &bigblock_cvf;
    + }
    +
    if (!strcmp(cvf_format,"none"))
    i = -1;
    else
    i = detect_cvf(sb,cvf_format);
    if (i >= 0)
    error = cvf_formats[i]->mount_cvf(sb,cvf_options);
    - else if (sb->s_blocksize == 512)
    - sbi->cvf_format = &default_cvf;
    - else
    - sbi->cvf_format = &bigblock_cvf;
    if (error || debug) {
    /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
    printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
    @@ -612,18 +607,19 @@
    MSDOS_CAN_BMAP(sbi) ? ",bmap" : "");
    printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%ld,ds=%ld,de=%d,data=%ld,"
    "se=%d,ts=%ld,ls=%d,rc=%ld,fc=%u]\n",
    - b->media,sbi->cluster_size,
    - sbi->fats,sbi->fat_start,
    - sbi->fat_length,
    + b->media,sbi->cluster_size,
    + sbi->fats,sbi->fat_start,
    + sbi->fat_length,
    sbi->dir_start,sbi->dir_entries,
    sbi->data_start,
    CF_LE_W(*(unsigned short *) &b->sectors),
    (unsigned long)b->total_sect,logical_sector_size,
    sbi->root_cluster,sbi->free_clusters);
    - printk ("Transaction block size = %d\n",blksize);
    + printk ("Transaction block size = %d\n", hard_blksize);
    }
    - if (i<0) if (sbi->clusters+2 > fat_clusters)
    - sbi->clusters = fat_clusters-2;
    + if (i < 0)
    + if (sbi->clusters + 2 > fat_clusters)
    + sbi->clusters = fat_clusters - 2;
    if (error)
    goto out_invalid;

    @@ -692,7 +688,7 @@
    }
    if(sbi->private_data)
    kfree(sbi->private_data);
    - sbi->private_data=NULL;
    + sbi->private_data = NULL;

    return NULL;
    }
    @@ -717,7 +713,7 @@
    }
    unlock_fat(sb);
    buf->f_type = sb->s_magic;
    - buf->f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
    + buf->f_bsize = 1 << MSDOS_SB(sb)->cluster_bits;
    buf->f_blocks = MSDOS_SB(sb)->clusters;
    buf->f_bfree = free;
    buf->f_bavail = free;
    @@ -796,8 +792,8 @@
    #endif
    if ((nr = MSDOS_I(inode)->i_start) != 0)
    while (nr != -1) {
    - inode->i_size += SECTOR_SIZE*sbi->cluster_size;
    - if (!(nr = fat_access(sb,nr,-1))) {
    + inode->i_size += 1 << sbi->cluster_bits;
    + if (!(nr = fat_access(sb, nr, -1))) {
    printk("Directory %ld: bad FAT\n",
    inode->i_ino);
    break;
    @@ -828,12 +824,11 @@
    inode->i_flags |= S_IMMUTABLE;
    MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
    /* this is as close to the truth as we can get ... */
    - inode->i_blksize = sbi->cluster_size*SECTOR_SIZE;
    - inode->i_blocks =
    - ((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *
    - sbi->cluster_size;
    + inode->i_blksize = 1 << sbi->cluster_bits;
    + inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
    + & ~(inode->i_blksize - 1)) / 512;
    inode->i_mtime = inode->i_atime =
    - date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
    + date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
    inode->i_ctime =
    MSDOS_SB(sb)->options.isvfat
    ? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate))
    @@ -854,7 +849,7 @@
    return;
    }
    lock_kernel();
    - if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) {
    + if (!(bh = fat_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {
    printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
    fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
    unlock_kernel();
    @@ -869,7 +864,7 @@
    }

    raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
    - [i_pos & (MSDOS_DPB-1)];
    + [i_pos & (MSDOS_SB(sb)->dir_per_block - 1)];
    if (S_ISDIR(inode->i_mode)) {
    raw_entry->attr = ATTR_DIR;
    raw_entry->size = 0;
    diff -urP linux-2.4.5-pre5/fs/fat/misc.c linux-2.4.5-pre5-fat/fs/fat/misc.c
    --- linux-2.4.5-pre5/fs/fat/misc.c Wed Sep 6 06:07:29 2000
    +++ linux-2.4.5-pre5-fat/fs/fat/misc.c Wed May 16 02:52:48 2001
    @@ -108,24 +108,22 @@
    /* XXX: Need to write one per FSINFO block. Currently only writes 1 */
    void fat_clusters_flush(struct super_block *sb)
    {
    - int offset;
    struct buffer_head *bh;
    struct fat_boot_fsinfo *fsinfo;

    - /* The fat32 boot fs info is at offset 0x3e0 by observation */
    - offset = MSDOS_SB(sb)->fsinfo_offset;
    - bh = fat_bread(sb, (offset >> SECTOR_BITS));
    + bh = fat_bread(sb, MSDOS_SB(sb)->fsinfo_sector);
    if (bh == NULL) {
    printk("FAT bread failed in fat_clusters_flush\n");
    return;
    }
    - fsinfo = (struct fat_boot_fsinfo *)
    - &bh->b_data[offset & (SECTOR_SIZE-1)];

    + fsinfo = (struct fat_boot_fsinfo *)bh->b_data;
    /* Sanity check */
    - if (CF_LE_L(fsinfo->signature) != 0x61417272) {
    - printk("fat_clusters_flush: Did not find valid FSINFO signature. Found 0x%x. offset=0x%x\n", CF_LE_L(fsinfo->signature), offset);
    - fat_brelse(sb, bh);
    + if (!IS_FSINFO(fsinfo)) {
    + printk("FAT: Did not find valid FSINFO signature.\n"
    + "Found signature1 0x%x signature2 0x%x sector=%ld.\n",
    + CF_LE_L(fsinfo->signature1), CF_LE_L(fsinfo->signature2),
    + MSDOS_SB(sb)->fsinfo_sector);
    return;
    }
    fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters);
    @@ -145,7 +143,6 @@
    struct super_block *sb = inode->i_sb;
    int count,nr,limit,last,curr,file_cluster;
    int res = -ENOSPC;
    - int cluster_size = MSDOS_SB(sb)->cluster_size;

    if (!MSDOS_SB(sb)->free_clusters) return res;
    lock_fat(sb);
    @@ -167,7 +164,7 @@
    if (MSDOS_SB(sb)->fat_bits == 32)
    fat_clusters_flush(sb);
    unlock_fat(sb);
    - last = 0;
    +
    /* We must locate the last cluster of the file to add this
    new one (nr) to the end of the link list (the FAT).

    @@ -178,7 +175,7 @@
    use last to plug the nr cluster. We will use file_cluster to
    update the cache.
    */
    - file_cluster = 0;
    + last = file_cluster = 0;
    if ((curr = MSDOS_I(inode)->i_start) != 0) {
    fat_cache_lookup(inode,INT_MAX,&last,&curr);
    file_cluster = last;
    @@ -190,14 +187,15 @@
    }
    }
    }
    - if (last) fat_access(sb,last,nr);
    - else {
    + if (last) {
    + fat_access(sb, last, nr);
    + fat_cache_add(inode, file_cluster, nr);
    + } else {
    MSDOS_I(inode)->i_start = nr;
    MSDOS_I(inode)->i_logstart = nr;
    mark_inode_dirty(inode);
    }
    - fat_cache_add(inode,file_cluster,nr);
    - inode->i_blocks += cluster_size;
    + inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
    return 0;
    }

    @@ -209,36 +207,44 @@
    int cluster_size = MSDOS_SB(sb)->cluster_size;

    if (MSDOS_SB(sb)->fat_bits != 32) {
    - if (inode->i_ino == MSDOS_ROOT_INO) return res;
    + if (inode->i_ino == MSDOS_ROOT_INO)
    + return res;
    }
    - if (!MSDOS_SB(sb)->free_clusters) return res;
    + if (!MSDOS_SB(sb)->free_clusters)
    + return res;
    +
    lock_fat(sb);
    +
    limit = MSDOS_SB(sb)->clusters;
    nr = limit; /* to keep GCC happy */
    for (count = 0; count < limit; count++) {
    - nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2;
    - if (fat_access(sb,nr,-1) == 0) break;
    + nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2;
    + if (fat_access(sb, nr, -1) == 0)
    + break;
    }
    - PRINTK (("cnt = %d --",count));
    + PRINTK (("cnt = %d --", count));
    #ifdef DEBUG
    -printk("free cluster: %d\n",nr);
    + printk("free cluster: %d\n", nr);
    #endif
    - MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit;
    if (count >= limit) {
    MSDOS_SB(sb)->free_clusters = 0;
    unlock_fat(sb);
    return res;
    }
    - fat_access(sb,nr,EOF_FAT(sb));
    +
    + MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit;
    + fat_access(sb, nr, EOF_FAT(sb));
    if (MSDOS_SB(sb)->free_clusters != -1)
    MSDOS_SB(sb)->free_clusters--;
    if (MSDOS_SB(sb)->fat_bits == 32)
    fat_clusters_flush(sb);
    +
    unlock_fat(sb);
    +
    #ifdef DEBUG
    -printk("set to %x\n",fat_access(sb,nr,-1));
    + printk("set to %x\n", fat_access(sb, nr, -1));
    #endif
    - last = 0;
    +
    /* We must locate the last cluster of the file to add this
    new one (nr) to the end of the link list (the FAT).

    @@ -249,15 +255,14 @@
    use last to plug the nr cluster. We will use file_cluster to
    update the cache.
    */
    - file_cluster = 0;
    + last = file_cluster = 0;
    if ((curr = MSDOS_I(inode)->i_start) != 0) {
    - fat_cache_lookup(inode,INT_MAX,&last,&curr);
    + fat_cache_lookup(inode, INT_MAX, &last, &curr);
    file_cluster = last;
    while (curr && curr != -1){
    PRINTK (("."));
    file_cluster++;
    - if (!(curr = fat_access(sb,
    - last = curr,-1))) {
    + if (!(curr = fat_access(sb, last = curr, -1))) {
    fat_fs_panic(sb,"File without EOF");
    return res;
    }
    @@ -265,53 +270,57 @@
    PRINTK ((" -- "));
    }
    #ifdef DEBUG
    -printk("last = %d\n",last);
    + printk("last = %d\n", last);
    #endif
    - if (last) fat_access(sb,last,nr);
    + if (last)
    + fat_access(sb, last, nr);
    else {
    MSDOS_I(inode)->i_start = nr;
    MSDOS_I(inode)->i_logstart = nr;
    mark_inode_dirty(inode);
    }
    #ifdef DEBUG
    -if (last) printk("next set to %d\n",fat_access(sb,last,-1));
    + if (last)
    + printk("next set to %d\n",fat_access(sb, last, -1));
    #endif
    - sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
    + sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size;
    last_sector = sector + cluster_size;
    - if (MSDOS_SB(sb)->cvf_format &&
    - MSDOS_SB(sb)->cvf_format->zero_out_cluster)
    - MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
    - else
    - for ( ; sector < last_sector; sector++) {
    - #ifdef DEBUG
    - printk("zeroing sector %d\n",sector);
    - #endif
    - if (!(bh = fat_getblk(sb, sector)))
    - printk("getblk failed\n");
    - else {
    - memset(bh->b_data,0,SECTOR_SIZE);
    - fat_set_uptodate(sb, bh, 1);
    - fat_mark_buffer_dirty(sb, bh);
    - if (!res)
    - res=bh;
    - else
    - fat_brelse(sb, bh);
    + if (MSDOS_SB(sb)->cvf_format && MSDOS_SB(sb)->cvf_format->zero_out_cluster)
    + MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode, nr);
    + else {
    + for ( ; sector < last_sector; sector++) {
    +#ifdef DEBUG
    + printk("zeroing sector %d\n", sector);
    +#endif
    + if (!(bh = fat_getblk(sb, sector)))
    + printk("getblk failed\n");
    + else {
    + memset(bh->b_data, 0, sb->s_blocksize);
    + fat_set_uptodate(sb, bh, 1);
    + fat_mark_buffer_dirty(sb, bh);
    + if (!res)
    + res = bh;
    + else
    + fat_brelse(sb, bh);
    + }
    }
    }
    - if (file_cluster != inode->i_blocks/cluster_size){
    - printk ("file_cluster badly computed!!! %d <> %ld\n"
    - ,file_cluster,inode->i_blocks/cluster_size);
    + if (file_cluster
    + != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) {
    + printk ("file_cluster badly computed!!! %d <> %ld\n",
    + file_cluster,
    + inode->i_blocks / cluster_size / (sb->s_blocksize / 512));
    }else{
    - fat_cache_add(inode,file_cluster,nr);
    + fat_cache_add(inode, file_cluster, nr);
    }
    - inode->i_blocks += cluster_size;
    - if (inode->i_size & (SECTOR_SIZE-1)) {
    - fat_fs_panic(sb,"Odd directory size");
    - inode->i_size = (inode->i_size+SECTOR_SIZE) &
    - ~(SECTOR_SIZE-1);
    + inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
    + if (inode->i_size & (sb->s_blocksize - 1)) {
    + fat_fs_panic(sb, "Odd directory size");
    + inode->i_size = (inode->i_size + sb->s_blocksize) &
    + ~(sb->s_blocksize - 1);
    }
    - inode->i_size += SECTOR_SIZE*cluster_size;
    - MSDOS_I(inode)->mmu_private += SECTOR_SIZE*cluster_size;
    + inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits;
    + MSDOS_I(inode)->mmu_private += 1 << MSDOS_SB(sb)->cluster_bits;
    mark_inode_dirty(inode);
    return res;
    }
    @@ -386,6 +395,7 @@
    struct msdos_dir_entry **de, int *ino)
    {
    struct super_block *sb = dir->i_sb;
    + struct msdos_sb_info *sbi = MSDOS_SB(sb);
    int sector, offset;

    while (1) {
    @@ -394,7 +404,7 @@
    if (*bh)
    fat_brelse(sb, *bh);
    *bh = NULL;
    - if ((sector = fat_bmap(dir,offset >> SECTOR_BITS)) == -1)
    + if ((sector = fat_bmap(dir,offset >> sb->s_blocksize_bits)) == -1)
    return -1;
    PRINTK (("get_entry sector %d %p\n",sector,*bh));
    PRINTK (("get_entry sector apres brelse\n"));
    @@ -406,10 +416,11 @@
    continue;
    }
    PRINTK (("get_entry apres sread\n"));
    - *de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset &
    - (SECTOR_SIZE-1)));
    - *ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
    - MSDOS_DIR_BITS);
    +
    + offset &= sb->s_blocksize - 1;
    + *de = (struct msdos_dir_entry *) ((*bh)->b_data + offset);
    + *ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
    +
    return 0;
    }
    }
    @@ -476,7 +487,7 @@
    if (!(bh = fat_bread(sb,sector)))
    return -EIO;
    data = (struct msdos_dir_entry *) bh->b_data;
    - for (entry = 0; entry < MSDOS_DPS; entry++) {
    + for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) {
    /* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */
    if (name) {
    RSS_NAME
    @@ -488,7 +499,8 @@
    }
    }
    if (done) {
    - if (ino) *ino = sector*MSDOS_DPS+entry;
    + if (ino)
    + *ino = sector * MSDOS_SB(sb)->dir_per_block + entry;
    start = CF_LE_W(data[entry].start);
    if (MSDOS_SB(sb)->fat_bits == 32) {
    start |= (CF_LE_W(data[entry].starthi) << 16);
    @@ -517,9 +529,12 @@
    {
    int count,cluster;

    - for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
    + for (count = 0;
    + count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block;
    + count++) {
    if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
    - name,number,ino,res_bh,res_de)) >= 0) return cluster;
    + name,number,ino,res_bh,res_de)) >= 0)
    + return cluster;
    }
    return -ENOENT;
    }
    @@ -570,13 +585,12 @@
    int *number, int *ino, struct buffer_head **res_bh,
    struct msdos_dir_entry **res_de)
    {
    - if (start) return raw_scan_nonroot
    - (sb,start,name,number,ino,res_bh,res_de);
    - else return raw_scan_root
    - (sb,name,number,ino,res_bh,res_de);
    + if (start)
    + return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de);
    + else
    + return raw_scan_root(sb,name,number,ino,res_bh,res_de);
    }

    -
    /*
    * fat_parent_ino returns the inode number of the parent directory of dir.
    * File creation has to be deferred while fat_parent_ino is running to
    @@ -627,7 +641,6 @@
    if (!locked) fat_unlock_creation();
    return nr;
    }
    -

    /*
    * fat_subdirs counts the number of sub-directories of dir. It can be run
    diff -urP linux-2.4.5-pre5/include/linux/msdos_fs.h linux-2.4.5-pre5-fat/include/linux/msdos_fs.h
    --- linux-2.4.5-pre5/include/linux/msdos_fs.h Thu May 24 03:35:25 2001
    +++ linux-2.4.5-pre5-fat/include/linux/msdos_fs.h Mon May 21 00:27:46 2001
    @@ -76,6 +76,11 @@
    #define EOF_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
    MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12)

    +#define FAT_FSINFO_SIG1 0x41615252
    +#define FAT_FSINFO_SIG2 0x61417272
    +#define IS_FSINFO(x) (CF_LE_L((x)->signature1) == FAT_FSINFO_SIG1 \
    + && CF_LE_L((x)->signature2) == FAT_FSINFO_SIG2)
    +
    /*
    * Inode flags
    */
    @@ -127,8 +132,9 @@
    };

    struct fat_boot_fsinfo {
    - __u32 reserved1; /* Nothing as far as I can tell */
    - __u32 signature; /* 0x61417272L */
    + __u32 signature1; /* 0x61417272L */
    + __u32 reserved1[120]; /* Nothing as far as I can tell */
    + __u32 signature2; /* 0x61417272L */
    __u32 free_clusters; /* Free cluster count. -1 if unknown */
    __u32 next_cluster; /* Most recently allocated cluster.
    * Unused under Linux. */
    @@ -208,7 +214,7 @@
    {
    /* Fast stuff first */
    if (*bh && *de &&
    - (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_DPB-1) {
    + (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
    *pos += sizeof(struct msdos_dir_entry);
    (*de)++;
    (*ino)++;
    diff -urP linux-2.4.5-pre5/include/linux/msdos_fs_sb.h linux-2.4.5-pre5-fat/include/linux/msdos_fs_sb.h
    --- linux-2.4.5-pre5/include/linux/msdos_fs_sb.h Wed Sep 6 06:53:04 2000
    +++ linux-2.4.5-pre5-fat/include/linux/msdos_fs_sb.h Tue May 15 02:37:47 2001
    @@ -44,7 +44,7 @@
    unsigned long data_start; /* first data sector */
    unsigned long clusters; /* number of clusters */
    unsigned long root_cluster; /* first cluster of the root directory */
    - unsigned long fsinfo_offset; /* FAT32 fsinfo offset from start of disk */
    + unsigned long fsinfo_sector; /* FAT32 fsinfo offset from start of disk */
    wait_queue_head_t fat_wait;
    struct semaphore fat_lock;
    int prev_free; /* previously returned free cluster number */
    @@ -54,7 +54,9 @@
    struct nls_table *nls_io; /* Charset used for input and display */
    struct cvf_format* cvf_format;
    void *dir_ops; /* Opaque; default directory operations */
    - void *private_data;
    + void *private_data;
    + int dir_per_block; /* dir entries per block */
    + int dir_per_block_bits; /* log2(dir_per_block) */
    };

    #endif
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 12:53    [W:0.086 / U:61.736 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site