--- R29/fs/fat/inode.c 2004-03-24 19:56:01.000000000 +0000 +++ R63/fs/fat/inode.c 2005-03-31 07:17:14.000000000 +0100 @@ -83,17 +83,17 @@ } } -static inline unsigned long fat_hash(struct super_block *sb, int i_pos) +static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) { unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); return tmp & FAT_HASH_MASK; } -void fat_attach(struct inode *inode, int i_pos) +void fat_attach(struct inode *inode, loff_t i_pos) { spin_lock(&fat_inode_lock); - MSDOS_I(inode)->i_location = i_pos; + MSDOS_I(inode)->i_pos = i_pos; list_add(&MSDOS_I(inode)->i_fat_hash, fat_inode_hashtable + fat_hash(inode->i_sb, i_pos)); spin_unlock(&fat_inode_lock); @@ -102,13 +102,13 @@ void fat_detach(struct inode *inode) { spin_lock(&fat_inode_lock); - MSDOS_I(inode)->i_location = 0; + MSDOS_I(inode)->i_pos = 0; list_del(&MSDOS_I(inode)->i_fat_hash); INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); spin_unlock(&fat_inode_lock); } -struct inode *fat_iget(struct super_block *sb, int i_pos) +struct inode *fat_iget(struct super_block *sb, loff_t i_pos) { struct list_head *p = fat_inode_hashtable + fat_hash(sb, i_pos); struct list_head *walk; @@ -120,7 +120,7 @@ i = list_entry(walk, struct msdos_inode_info, i_fat_hash); if (i->i_fat_inode->i_sb != sb) continue; - if (i->i_location != i_pos) + if (i->i_pos != i_pos) continue; inode = igrab(i->i_fat_inode); if (inode) @@ -133,11 +133,11 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de); struct inode *fat_build_inode(struct super_block *sb, - struct msdos_dir_entry *de, int ino, int *res) + struct msdos_dir_entry *de, loff_t i_pos, int *res) { struct inode *inode; *res = 0; - inode = fat_iget(sb, ino); + inode = fat_iget(sb, i_pos); if (inode) goto out; inode = new_inode(sb); @@ -147,7 +147,7 @@ *res = 0; inode->i_ino = iunique(sb, MSDOS_ROOT_INO); fat_fill_inode(inode, de); - fat_attach(inode, ino); + fat_attach(inode, i_pos); insert_inode_hash(inode); out: return inode; @@ -379,7 +379,7 @@ int nr; INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); - MSDOS_I(inode)->i_location = 0; + MSDOS_I(inode)->i_pos = 0; MSDOS_I(inode)->i_fat_inode = inode; inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; @@ -406,7 +406,7 @@ } inode->i_blksize = 1 << sbi->cluster_bits; inode->i_blocks = ((inode->i_size + inode->i_blksize - 1) - & ~(inode->i_blksize - 1)) >> 9; + & ~((loff_t)inode->i_blksize - 1)) >> 9; MSDOS_I(inode)->i_logstart = 0; MSDOS_I(inode)->mmu_private = inode->i_size; @@ -443,19 +443,25 @@ return ERR_PTR(-ESTALE); inode = iget(sb, fh[0]); - if (!inode || is_bad_inode(inode) || - inode->i_generation != fh[1]) { - if (inode) iput(inode); + if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { + if (inode) + iput(inode); inode = NULL; } if (!inode) { - /* try 2 - see if i_location is in F-d-c + loff_t i_pos; + int i_logstart = fh[3] & 0x0fffffff; + + i_pos = (loff_t)fh[2] << 8; + i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28); + + /* try 2 - see if i_pos is in F-d-c * require i_logstart to be the same * Will fail if you truncate and then re-write */ - inode = fat_iget(sb, fh[2]); - if (inode && MSDOS_I(inode)->i_logstart != fh[3]) { + inode = fat_iget(sb, i_pos); + if (inode && MSDOS_I(inode)->i_logstart != i_logstart) { iput(inode); inode = NULL; } @@ -505,23 +511,26 @@ result->d_op = sb->s_root->d_op; result->d_flags |= DCACHE_NFSD_DISCONNECTED; return result; - - } int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent) { int len = *lenp; struct inode *inode = de->d_inode; + u32 ipos_h, ipos_m, ipos_l; if (len < 5) return 255; /* no room */ + + ipos_h = MSDOS_I(inode)->i_pos >> 8; + ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24; + ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28; *lenp = 5; fh[0] = inode->i_ino; fh[1] = inode->i_generation; - fh[2] = MSDOS_I(inode)->i_location; - fh[3] = MSDOS_I(inode)->i_logstart; - fh[4] = MSDOS_I(de->d_parent->d_inode)->i_logstart; + fh[2] = ipos_h; + fh[3] = ipos_m | MSDOS_I(inode)->i_logstart; + fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart; return 3; } @@ -636,7 +645,7 @@ sbi->cluster_bits = ffs(logical_sector_size * sbi->cluster_size) - 1; sbi->fats = b->fats; - sbi->fat_start = CF_LE_W(b->reserved); + sbi->fat_start = CF_LE_W(b->reserved); sbi->prev_free = 0; if (!b->fat_length && b->fat32_length) { struct fat_boot_fsinfo *fsinfo; @@ -647,7 +656,8 @@ fat32 = 1; sbi->fat_length = CF_LE_L(b->fat32_length); sbi->root_cluster = CF_LE_L(b->root_cluster); - + sb->s_maxbytes = 0xffffffff; + sbi->fsinfo_sector = CF_LE_W(b->info_sector); /* MC - if info_sector is 0, don't multiply by 0 */ if (sbi->fsinfo_sector == 0) @@ -891,7 +901,7 @@ int nr; INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); - MSDOS_I(inode)->i_location = 0; + MSDOS_I(inode)->i_pos = 0; MSDOS_I(inode)->i_fat_inode = inode; inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; @@ -906,10 +916,9 @@ inode->i_fop = &fat_dir_operations; MSDOS_I(inode)->i_start = CF_LE_W(de->start); - if (sbi->fat_bits == 32) { - MSDOS_I(inode)->i_start |= - (CF_LE_W(de->starthi) << 16); - } + if (sbi->fat_bits == 32) + MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); + MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; inode->i_nlink = fat_subdirs(inode); /* includes .., compensating for "self" */ @@ -956,7 +965,7 @@ /* this is as close to the truth as we can get ... */ inode->i_blksize = 1 << sbi->cluster_bits; inode->i_blocks = ((inode->i_size + inode->i_blksize - 1) - & ~(inode->i_blksize - 1)) >> 9; + & ~((loff_t)inode->i_blksize - 1)) >> 9; inode->i_mtime = inode->i_atime = date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); inode->i_ctime = @@ -971,22 +980,22 @@ struct super_block *sb = inode->i_sb; struct buffer_head *bh; struct msdos_dir_entry *raw_entry; - unsigned int i_pos; + loff_t i_pos; retry: - i_pos = MSDOS_I(inode)->i_location; + i_pos = MSDOS_I(inode)->i_pos; if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) { return; } lock_kernel(); 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); + printk("dev = %s, i_pos = %llu\n", kdevname(inode->i_dev), i_pos); fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block"); unlock_kernel(); return; } spin_lock(&fat_inode_lock); - if (i_pos != MSDOS_I(inode)->i_location) { + if (i_pos != MSDOS_I(inode)->i_pos) { spin_unlock(&fat_inode_lock); fat_brelse(sb, bh); unlock_kernel();