patch-2.4.5 linux/fs/fat/inode.c
Next file: linux/fs/fat/misc.c
Previous file: linux/fs/fat/file.c
Back to the patch index
Back to the overall index
- Lines: 396
- Date:
Thu May 24 15:36:34 2001
- Orig file:
v2.4.4/linux/fs/fat/inode.c
- Orig date:
Wed Apr 18 11:49:12 2001
diff -u --recursive --new-file v2.4.4/linux/fs/fat/inode.c linux/fs/fat/inode.c
@@ -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;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)