Messages in this thread Patch in this message | | | Date | Fri, 5 Nov 1999 19:03:36 -0500 (EST) | From | Alexander Viro <> | Subject | Re: 2.3.26pre2 compile error |
| |
On 5 Nov 1999, Linus Torvalds wrote:
> In article <14370.43581.360384.276661@wire.cadcamlab.org>, > Peter Samuelson <peter@wire.cadcamlab.org> wrote: > >[Tonglu Yi] > >> fs/filesystems.a(fat.o): In function `fat_truncate': > >> fat.o(.text+0x22ad): undefined reference to `__divdi3' > > > >Does this help? > > Don't do this. Ys, it will probably fix the problem, but I really don't > want to have 64-bit division in the kernel. It's probably a divide by a > power of 2 that should really be a shift anyway.
Looks so. I've added cluster_bits to msdos_sb_info and initialization into fat_read_super(). If you give it a filesystem with bogus cluster size (not a power of 2) it will warn and refuse to mount (DOS will do the same, so...) I've also made some cleanup in fs/fat/inode.c (trivial - replaced tons of MSDOS_SB(sb) with local variable).
Patch follows: diff -urN linux-2.3.26-pre2/fs/fat/file.c linux-bird.FAT/fs/fat/file.c --- linux-2.3.26-pre2/fs/fat/file.c Sat Oct 30 12:48:48 1999 +++ linux-bird.FAT/fs/fat/file.c Fri Nov 5 17:03:44 1999 @@ -182,6 +182,7 @@ void fat_truncate(struct inode *inode) { + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); int cluster; /* Why no return value? Surely the disk could fail... */ @@ -189,9 +190,9 @@ return /* -EPERM */; if (IS_IMMUTABLE(inode)) return /* -EPERM */; - cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size; + cluster = SECTOR_SIZE*sbi->cluster_size; MSDOS_I(inode)->i_realsize = ((inode->i_size-1) | (SECTOR_SIZE-1)) + 1; - (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster); + 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 -urN linux-2.3.26-pre2/fs/fat/inode.c linux-bird.FAT/fs/fat/inode.c --- linux-2.3.26-pre2/fs/fat/inode.c Thu Nov 4 20:36:49 1999 +++ linux-bird.FAT/fs/fat/inode.c Fri Nov 5 17:58:34 1999 @@ -364,21 +364,22 @@ static void fat_read_root(struct inode *inode) { struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); int nr; INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); MSDOS_I(inode)->i_location = 0; MSDOS_I(inode)->i_fat_inode = inode; - inode->i_uid = MSDOS_SB(sb)->options.fs_uid; - inode->i_gid = MSDOS_SB(sb)->options.fs_gid; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; inode->i_version = ++event; - inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR; - inode->i_op = MSDOS_SB(sb)->dir_ops; - if (MSDOS_SB(sb)->fat_bits == 32) { - MSDOS_I(inode)->i_start = MSDOS_SB(sb)->root_cluster; + inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_umask) | S_IFDIR; + inode->i_op = sbi->dir_ops; + if (sbi->fat_bits == 32) { + MSDOS_I(inode)->i_start = sbi->root_cluster; if ((nr = MSDOS_I(inode)->i_start) != 0) { while (nr != -1) { - inode->i_size += SECTOR_SIZE*MSDOS_SB(sb)->cluster_size; + inode->i_size += SECTOR_SIZE*sbi->cluster_size; if (!(nr = fat_access(sb,nr,-1))) { printk("Directory %ld: bad FAT\n", inode->i_ino); @@ -388,12 +389,13 @@ } } else { MSDOS_I(inode)->i_start = 0; - inode->i_size = MSDOS_SB(sb)->dir_entries* + inode->i_size = sbi->dir_entries* sizeof(struct msdos_dir_entry); } - inode->i_blksize = MSDOS_SB(sb)->cluster_size* SECTOR_SIZE; - inode->i_blocks = (inode->i_size+inode->i_blksize-1)/ - inode->i_blksize*MSDOS_SB(sb)->cluster_size; + inode->i_blksize = sbi->cluster_size* SECTOR_SIZE; + inode->i_blocks = + ((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) * + sbi->cluster_size; MSDOS_I(inode)->i_logstart = 0; MSDOS_I(inode)->i_realsize = inode->i_size; @@ -429,6 +431,7 @@ struct inode *root_inode; struct buffer_head *bh; 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; @@ -442,12 +445,12 @@ cvf_format[0] = '\0'; cvf_options[0] = '\0'; - MSDOS_SB(sb)->cvf_format = NULL; - MSDOS_SB(sb)->private_data = NULL; + sbi->cvf_format = NULL; + sbi->private_data = NULL; MOD_INC_USE_COUNT; - MSDOS_SB(sb)->dir_ops = fs_dir_inode_ops; - MSDOS_SB(sb)->put_super_callback = NULL; + sbi->dir_ops = fs_dir_inode_ops; + sbi->put_super_callback = NULL; sb->s_op = &fat_sops; if (hardsect_size[MAJOR(sb->s_dev)] != NULL){ blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]; @@ -457,13 +460,13 @@ } - opts.isvfat = MSDOS_SB(sb)->options.isvfat; + opts.isvfat = sbi->options.isvfat; if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, cvf_format, cvf_options) || (blksize != 512 && blksize != 1024 && blksize != 2048)) goto out_fail; /* N.B. we should parse directly into the sb structure */ - memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options)); + memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options)); fat_cache_init(); lock_super(sb); @@ -508,69 +511,79 @@ logical_sector_size = CF_LE_W(get_unaligned((unsigned short *) &b->sector_size)); sector_mult = logical_sector_size >> SECTOR_BITS; - MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult; - MSDOS_SB(sb)->fats = b->fats; - MSDOS_SB(sb)->fat_start = CF_LE_W(b->reserved)*sector_mult; + 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"); + 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->fats = b->fats; + sbi->fat_start = CF_LE_W(b->reserved)*sector_mult; if (!b->fat_length && b->fat32_length) { struct fat_boot_fsinfo *fsinfo; /* Must be FAT32 */ fat32 = 1; - MSDOS_SB(sb)->fat_length= CF_LE_L(b->fat32_length)*sector_mult; - MSDOS_SB(sb)->root_cluster = CF_LE_L(b->root_cluster); + sbi->fat_length= CF_LE_L(b->fat32_length)*sector_mult; + sbi->root_cluster = CF_LE_L(b->root_cluster); /* MC - if info_sector is 0, don't multiply by 0 */ if(CF_LE_W(b->info_sector) == 0) { - MSDOS_SB(sb)->fsinfo_offset = + sbi->fsinfo_offset = logical_sector_size + 0x1e0; } else { - MSDOS_SB(sb)->fsinfo_offset = + sbi->fsinfo_offset = (CF_LE_W(b->info_sector) * logical_sector_size) + 0x1e0; } - if (MSDOS_SB(sb)->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) { + 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[MSDOS_SB(sb)->fsinfo_offset]; + &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)); } else { - MSDOS_SB(sb)->free_clusters = CF_LE_L(fsinfo->free_clusters); + sbi->free_clusters = CF_LE_L(fsinfo->free_clusters); } } else { fat32 = 0; - MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult; - MSDOS_SB(sb)->root_cluster = 0; - MSDOS_SB(sb)->free_clusters = -1; /* Don't know yet */ - } - MSDOS_SB(sb)->dir_start= CF_LE_W(b->reserved)*sector_mult+ - b->fats*MSDOS_SB(sb)->fat_length; - MSDOS_SB(sb)->dir_entries = + sbi->fat_length = CF_LE_W(b->fat_length)*sector_mult; + 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_entries = CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries)); - MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE(( - MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, + 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 - MSDOS_SB(sb)->data_start; + data_sectors = data_sectors * sector_mult - sbi->data_start; error = !b->cluster_size || !sector_mult; if (!error) { - MSDOS_SB(sb)->clusters = b->cluster_size ? data_sectors/ + sbi->clusters = b->cluster_size ? data_sectors/ b->cluster_size/sector_mult : 0; - MSDOS_SB(sb)->fat_bits = fat32 ? 32 : + sbi->fat_bits = fat32 ? 32 : (fat ? fat : - (MSDOS_SB(sb)->clusters > MSDOS_FAT12 ? 16 : 12)); - fat_clusters = MSDOS_SB(sb)->fat_length*SECTOR_SIZE*8/ - MSDOS_SB(sb)->fat_bits; - error = !MSDOS_SB(sb)->fats || (MSDOS_SB(sb)->dir_entries & - (MSDOS_DPS-1)) || MSDOS_SB(sb)->clusters+2 > fat_clusters+ + (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; } @@ -592,59 +605,59 @@ if (i >= 0) error = cvf_formats[i]->mount_cvf(sb,cvf_options); else if (sb->s_blocksize == 512) - MSDOS_SB(sb)->cvf_format = &default_cvf; + sbi->cvf_format = &default_cvf; else - MSDOS_SB(sb)->cvf_format = &bigblock_cvf; + 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," "uid=%d,gid=%d,umask=%03o%s]\n", - MSDOS_SB(sb)->fat_bits,opts.name_check, + sbi->fat_bits,opts.name_check, opts.conversion,opts.fs_uid,opts.fs_gid,opts.fs_umask, - MSDOS_CAN_BMAP(MSDOS_SB(sb)) ? ",bmap" : ""); + 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,MSDOS_SB(sb)->cluster_size, - MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start, - MSDOS_SB(sb)->fat_length, - MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries, - MSDOS_SB(sb)->data_start, + 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, - MSDOS_SB(sb)->root_cluster,MSDOS_SB(sb)->free_clusters); + sbi->root_cluster,sbi->free_clusters); printk ("Transaction block size = %d\n",blksize); } - if (i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters) - MSDOS_SB(sb)->clusters = fat_clusters-2; + if (i<0) if (sbi->clusters+2 > fat_clusters) + sbi->clusters = fat_clusters-2; if (error) goto out_invalid; sb->s_magic = MSDOS_SUPER_MAGIC; /* set up enough so that it can read an inode */ - init_waitqueue_head(&MSDOS_SB(sb)->fat_wait); - init_MUTEX(&MSDOS_SB(sb)->fat_lock); - MSDOS_SB(sb)->prev_free = 0; + init_waitqueue_head(&sbi->fat_wait); + init_MUTEX(&sbi->fat_lock); + sbi->prev_free = 0; cp = opts.codepage ? opts.codepage : 437; sprintf(buf, "cp%d", cp); - MSDOS_SB(sb)->nls_disk = load_nls(buf); - if (! MSDOS_SB(sb)->nls_disk) { + sbi->nls_disk = load_nls(buf); + if (! sbi->nls_disk) { /* Fail only if explicit charset specified */ if (opts.codepage != 0) goto out_fail; - MSDOS_SB(sb)->options.codepage = 0; /* already 0?? */ - MSDOS_SB(sb)->nls_disk = load_nls_default(); + sbi->options.codepage = 0; /* already 0?? */ + sbi->nls_disk = load_nls_default(); } - MSDOS_SB(sb)->nls_io = NULL; - if (MSDOS_SB(sb)->options.isvfat && !opts.utf8) { + sbi->nls_io = NULL; + if (sbi->options.isvfat && !opts.utf8) { p = opts.iocharset ? opts.iocharset : "iso8859-1"; - MSDOS_SB(sb)->nls_io = load_nls(p); - if (! MSDOS_SB(sb)->nls_io) { + sbi->nls_io = load_nls(p); + if (! sbi->nls_io) { /* Fail only if explicit charset specified */ if (opts.iocharset) goto out_unload_nls; - MSDOS_SB(sb)->nls_io = load_nls_default(); + sbi->nls_io = load_nls_default(); } } @@ -660,7 +673,7 @@ if (!sb->s_root) goto out_no_root; if(i>=0) { - MSDOS_SB(sb)->cvf_format = cvf_formats[i]; + sbi->cvf_format = cvf_formats[i]; ++cvf_format_use_count[i]; } return sb; @@ -668,10 +681,10 @@ out_no_root: printk("get root inode failed\n"); iput(root_inode); - if (MSDOS_SB(sb)->nls_io) - unload_nls(MSDOS_SB(sb)->nls_io); + if (sbi->nls_io) + unload_nls(sbi->nls_io); out_unload_nls: - unload_nls(MSDOS_SB(sb)->nls_disk); + unload_nls(sbi->nls_disk); goto out_fail; out_invalid: if (!silent) @@ -686,8 +699,9 @@ kfree(opts.iocharset); } sb->s_dev = 0; - if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); - MSDOS_SB(sb)->private_data=NULL; + if(sbi->private_data) + kfree(sbi->private_data); + sbi->private_data=NULL; MOD_DEC_USE_COUNT; return NULL; @@ -737,21 +751,22 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) { struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); int nr; INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); MSDOS_I(inode)->i_location = 0; MSDOS_I(inode)->i_fat_inode = inode; - inode->i_uid = MSDOS_SB(sb)->options.fs_uid; - inode->i_gid = MSDOS_SB(sb)->options.fs_gid; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; inode->i_version = ++event; if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { inode->i_mode = MSDOS_MKMODE(de->attr,S_IRWXUGO & - ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR; - inode->i_op = MSDOS_SB(inode->i_sb)->dir_ops; + ~sbi->options.fs_umask) | S_IFDIR; + inode->i_op = sbi->dir_ops; MSDOS_I(inode)->i_start = CF_LE_W(de->start); - if (MSDOS_SB(sb)->fat_bits == 32) { + if (sbi->fat_bits == 32) { MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); } @@ -767,8 +782,7 @@ inode->i_size = 0; if ((nr = MSDOS_I(inode)->i_start) != 0) while (nr != -1) { - inode->i_size += SECTOR_SIZE*MSDOS_SB(inode-> - i_sb)->cluster_size; + inode->i_size += SECTOR_SIZE*sbi->cluster_size; if (!(nr = fat_access(sb,nr,-1))) { printk("Directory %ld: bad FAT\n", inode->i_ino); @@ -779,13 +793,13 @@ } else { /* not a directory */ inode->i_mode = MSDOS_MKMODE(de->attr, ((IS_NOEXEC(inode) || - (MSDOS_SB(sb)->options.showexec && + (sbi->options.showexec && !is_exec(de->ext))) ? S_IRUGO|S_IWUGO : S_IRWXUGO) - & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG; + & ~sbi->options.fs_umask) | S_IFREG; inode->i_op = &fat_file_inode_operations; MSDOS_I(inode)->i_start = CF_LE_W(de->start); - if (MSDOS_SB(sb)->fat_bits == 32) { + if (sbi->fat_bits == 32) { MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); } @@ -795,13 +809,14 @@ MSDOS_I(inode)->i_realsize = ((inode->i_size-1)|(SECTOR_SIZE-1))+1; } if(de->attr & ATTR_SYS) - if (MSDOS_SB(sb)->options.sys_immutable) + if (sbi->options.sys_immutable) 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 = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE; - inode->i_blocks = (inode->i_size+inode->i_blksize-1)/ - inode->i_blksize*MSDOS_SB(sb)->cluster_size; + 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_mtime = inode->i_atime = date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); inode->i_ctime = diff -urN linux-2.3.26-pre2/include/linux/msdos_fs_sb.h linux-bird.FAT/include/linux/msdos_fs_sb.h --- linux-2.3.26-pre2/include/linux/msdos_fs_sb.h Sun Sep 12 21:22:57 1999 +++ linux-bird.FAT/include/linux/msdos_fs_sb.h Fri Nov 5 17:07:44 1999 @@ -34,6 +34,7 @@ struct msdos_sb_info { unsigned short cluster_size; /* sectors/cluster */ + unsigned short cluster_bits; /* sectors/cluster */ unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ unsigned short fat_start; unsigned long fat_length; /* FAT start & length (sec.) */
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |