Patch creation date: Mon Apr 7 10:40:50 CEST 1997 diff -urN linux-2.1.26-2k/fs/isofs/dir.c.~1~ linux-2.1.26-2k/fs/isofs/dir.c --- linux-2.1.26-2k/fs/isofs/dir.c.~1~ Sun Jan 26 11:07:44 1997 +++ linux-2.1.26-2k/fs/isofs/dir.c Thu Mar 27 22:56:43 1997 @@ -131,28 +131,12 @@ return 0; while (filp->f_pos < inode->i_size) { - int de_len, next_offset; + int de_len; #ifdef DEBUG printk("Block, offset, f_pos: %x %x %x\n", block, offset, filp->f_pos); printk("inode->i_size = %x\n",inode->i_size); #endif - /* Next directory_record on next CDROM sector */ - if (offset >= bufsize) { -#ifdef DEBUG - printk("offset >= bufsize\n"); -#endif - brelse(bh); - offset = 0; - block = isofs_bmap(inode, (filp->f_pos) >> bufbits); - if (!block) - return 0; - bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size); - if (!bh) - return 0; - continue; - } - de = (struct iso_directory_record *) (bh->b_data + offset); inode_number = (block << bufbits) + (offset & (bufsize - 1)); @@ -166,7 +150,7 @@ CDROM sector. If we are at the end of the directory, we kick out of the while loop. */ - if (de_len == 0) { + if ((de_len == 0) || (offset == bufsize) ) { brelse(bh); filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE); @@ -180,40 +164,18 @@ continue; } - /* Make sure that the entire directory record is in the - current bh block. - If not, put the two halves together in "tmpde" */ - next_offset = offset + de_len; - if (next_offset > bufsize) { -#ifdef DEBUG - printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize); -#endif - next_offset &= (bufsize - 1); - memcpy(tmpde, de, bufsize - offset); - brelse(bh); - block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits); - if (!block) - { - return 0; - } - - bh = breada(inode->i_dev, block, bufsize, - filp->f_pos, - inode->i_size); - if (!bh) - { -#ifdef DEBUG - printk("!bh block=%ld, bufsize=%ld\n",block,bufsize); - printk("filp->f_pos = %ld\n",filp->f_pos); - printk("inode->i_size = %ld\n", inode->i_size); -#endif - return 0; - } - - memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset); - de = tmpde; + offset += de_len; + if (offset > bufsize) { + /* + * This would only normally happen if we had + * a buggy cdrom image. All directory + * entries should terminate with a null size + * or end exactly at the end of the sector. + */ + printk("next_offset (%x) > bufsize (%x)\n", + offset,bufsize); + break; } - offset = next_offset; /* Handle the case of the '.' directory */ if (de->name_len[0] == 1 && de->name[0] == 0) { diff -urN linux-2.1.26-2k/fs/isofs/inode.c.~1~ linux-2.1.26-2k/fs/isofs/inode.c --- linux-2.1.26-2k/fs/isofs/inode.c.~1~ Fri Jan 3 10:33:26 1997 +++ linux-2.1.26-2k/fs/isofs/inode.c Sun Mar 30 10:56:45 1997 @@ -86,7 +86,10 @@ popt->check = 's'; /* default: strict */ popt->conversion = 'b'; /* default: no conversion */ popt->blocksize = 1024; - popt->mode = S_IRUGO; + popt->mode = S_IRUGO | S_IXUGO; /* r-x for all. The disc could + be shared with DOS machines so + virtually anything could be + a valid executable. */ popt->gid = 0; popt->uid = 0; if (!options) return 1; @@ -227,23 +230,22 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, int silent) { - struct buffer_head *bh=NULL; - int iso_blknum; - unsigned int blocksize_bits; - int high_sierra; - kdev_t dev = s->s_dev; - unsigned int vol_desc_start; - int orig_zonesize; - - struct iso_volume_descriptor *vdp; - struct hs_volume_descriptor *hdp; - - struct iso_primary_descriptor *pri = NULL; - struct hs_primary_descriptor *h_pri = NULL; + struct buffer_head * bh = NULL; + unsigned int blocksize; + unsigned int blocksize_bits; + kdev_t dev = s->s_dev; + struct hs_volume_descriptor * hdp; + struct hs_primary_descriptor * h_pri = NULL; + int high_sierra; + int iso_blknum; + struct iso9660_options opt; + int orig_zonesize; + struct iso_primary_descriptor * pri = NULL; + struct iso_directory_record * rootp; + struct iso_volume_descriptor * vdp; + unsigned int vol_desc_start; - struct iso_directory_record *rootp; - struct iso9660_options opt; MOD_INC_USE_COUNT; @@ -265,6 +267,23 @@ printk("uid = %d\n", opt.uid); #endif + /* + * First of all, get the hardware blocksize for this device. + * If we don't know what it is, or the hardware blocksize is + * larger than the blocksize the user specified, then use + * that value. + */ + blocksize = get_hardblocksize(dev); + if( (blocksize != 0) + && (blocksize > opt.blocksize) ) + { + /* + * Force the blocksize we are going to use to be the + * hardware blocksize. + */ + opt.blocksize = blocksize; + } + blocksize_bits = 0; { int i = opt.blocksize; @@ -273,6 +292,7 @@ i >>=1; } } + set_blocksize(dev, opt.blocksize); lock_super(s); @@ -362,6 +382,24 @@ /* RDE: convert log zone size to bit shift */ orig_zonesize = s -> u.isofs_sb.s_log_zone_size; + + /* + * If the zone size is smaller than the hardware sector size, + * this is a fatal error. This would occur if the + * disc drive had sectors that were 2048 bytes, but the filesystem + * had blocks that were 512 bytes (which should only very rarely + * happen. + */ + if( (blocksize != 0) + && (orig_zonesize < blocksize) ) + { + printk("Logical zone size(%ld) < hardware blocksize(%ld)\n", + orig_zonesize, blocksize); + goto out; + + } + + switch (s -> u.isofs_sb.s_log_zone_size) { case 512: s -> u.isofs_sb.s_log_zone_size = 9; break; case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break; @@ -403,8 +441,20 @@ * Force the blocksize to 512 for 512 byte sectors. The file * read primitives really get it wrong in a bad way if we don't * do this. + * + * Note - we should never be setting the blocksize to something + * less than the hardware sector size for the device. If we + * do, we would end up having to read larger buffers and split + * out portions to satisfy requests. + * + * Note2- the idea here is that we want to deal with the optimal + * zonesize in the filesystem. If we have it set to something less, + * then we have horrible problems with trying to piece together + * bits of adjacent blocks in order to properly read directory + * entries. By forcing the blocksize in this way, we ensure + * that we will never be required to do this. */ - if( orig_zonesize < opt.blocksize ) + if( orig_zonesize != opt.blocksize ) { opt.blocksize = orig_zonesize; blocksize_bits = 0; @@ -502,7 +552,6 @@ struct buffer_head * bh; struct iso_directory_record * raw_inode; unsigned char *pnt = NULL; - void *cpnt = NULL; int high_sierra; int block; int volume_seq_no ; @@ -519,30 +568,6 @@ raw_inode = ((struct iso_directory_record *) pnt); high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; - if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){ - int frag1, offset; - - offset = (inode->i_ino & (bufsize - 1)); - frag1 = bufsize - offset; - cpnt = kmalloc(*pnt,GFP_KERNEL); - if (cpnt == NULL) { - printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino); - brelse(bh); - goto fail; - } - memcpy(cpnt, bh->b_data + offset, frag1); - brelse(bh); - if (!(bh = bread(inode->i_dev,++block, bufsize))) { - kfree(cpnt); - printk("unable to read i-node block"); - goto fail; - } - offset += *pnt - bufsize; - memcpy((char *)cpnt+frag1, bh->b_data, offset); - pnt = ((unsigned char *) cpnt); - raw_inode = ((struct iso_directory_record *) pnt); - } - if (raw_inode->flags[-high_sierra] & 2) { inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; inode->i_nlink = 1; /* Set to 1. We know there are 2, but @@ -682,10 +707,6 @@ else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); } - if (cpnt) { - kfree (cpnt); - cpnt = NULL; - } return; fail: /* With a data error we return this information */ @@ -725,8 +746,6 @@ unsigned char bufbits = ISOFS_BUFFER_BITS(parent); unsigned int block,offset; int parent_dir, inode_number; - int old_offset; - void * cpnt = NULL; int result; int directory_size; struct buffer_head * bh; @@ -786,7 +805,7 @@ CDROM sector. If we are at the end of the directory, we kick out of the while loop. */ - if (*((unsigned char *) de) == 0) + if ((*((unsigned char *) de) == 0) || (offset == bufsize) ) { brelse(bh); offset = 0; @@ -813,52 +832,24 @@ bh block. If not, we malloc a buffer, and put the two halves together, so that we can cleanly read the block. */ - old_offset = offset; offset += *((unsigned char *) de); - if (offset >= bufsize) + if (offset > bufsize) { - unsigned int frag1; - frag1 = bufsize - old_offset; - cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL); - if (!cpnt) return -1; - memcpy(cpnt, bh->b_data + old_offset, frag1); - de = (struct iso_directory_record *) ((char *)cpnt); - brelse(bh); - offset -= bufsize; - directory_size -= bufsize; - if(directory_size < 0) - { - printk("Directory size < 0\n"); - return -1; - } - block++; - if(!(bh = bread(parent->i_dev,block,bufsize))) { - kfree(cpnt); - return -1; - } - memcpy((char *)cpnt+frag1, bh->b_data, offset); + printk("Directory overrun\n"); + goto out; } if (find_rock_ridge_relocation(de, parent) == extent){ result = inode_number; goto out; } - - if (cpnt) { - kfree(cpnt); - cpnt = NULL; - } } /* We go here for any condition we cannot handle. We also drop through to here at the end of the directory. */ out: - if (cpnt) { - kfree(cpnt); - cpnt = NULL; - } brelse(bh); #ifdef DEBUG printk("Resultant Inode %d\n",result); diff -urN linux-2.1.26-2k/fs/isofs/rock.c.~1~ linux-2.1.26-2k/fs/isofs/rock.c --- linux-2.1.26-2k/fs/isofs/rock.c.~1~ Thu Jan 2 11:11:30 1997 +++ linux-2.1.26-2k/fs/isofs/rock.c Thu Mar 27 22:56:43 1997 @@ -203,6 +203,17 @@ break; case SIG('N','M'): if (truncate) break; + /* + * If the flags are 2 or 4, this indicates '.' or '..'. + * We don't want to do anything with this, because it + * screws up the code that calls us. We don't really + * care anyways, since we can just use the non-RR + * name. + */ + if (rr->u.NM.flags & 6) { + break; + } + if (rr->u.NM.flags & ~1) { printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags); break; diff -urN linux-2.1.26-2k/fs/ext2/super.c.~1~ linux-2.1.26-2k/fs/ext2/super.c --- linux-2.1.26-2k/fs/ext2/super.c.~1~ Fri Dec 27 11:03:25 1996 +++ linux-2.1.26-2k/fs/ext2/super.c Thu Mar 27 22:56:43 1997 @@ -32,6 +32,7 @@ #include #include #include +#include static char error_buf[1024]; @@ -377,10 +378,26 @@ unsigned short resuid = EXT2_DEF_RESUID; unsigned short resgid = EXT2_DEF_RESGID; unsigned long logic_sb_block = 1; + unsigned long offset = 0; kdev_t dev = sb->s_dev; + int blocksize = BLOCK_SIZE; + int hblock; int db_count; int i, j; + /* + * See what the current blocksize for the device is, and + * use that as the blocksize. Otherwise (or if the blocksize + * is smaller than the default) use the default. + * This is important for devices that have a hardware + * sectorsize that is larger than the default. + */ + blocksize = get_hardblocksize(dev); + if( blocksize == 0 || blocksize < BLOCK_SIZE ) + { + blocksize = BLOCK_SIZE; + } + sb->u.ext2_sb.s_mount_opt = 0; set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL); if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, @@ -391,8 +408,19 @@ MOD_INC_USE_COUNT; lock_super (sb); - set_blocksize (dev, BLOCK_SIZE); - if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) { + set_blocksize (dev, blocksize); + + /* + * If the superblock doesn't start on a sector boundary, + * calculate the offset. FIXME(eric) this doesn't make sense + * that we would have to do this. + */ + if (blocksize != BLOCK_SIZE) { + logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; + offset = (sb_block*BLOCK_SIZE) % blocksize; + } + + if (!(bh = bread (dev, logic_sb_block, blocksize))) { sb->s_dev = 0; unlock_super (sb); printk ("EXT2-fs: unable to read superblock\n"); @@ -403,7 +431,7 @@ * Note: s_es must be initialized s_es as soon as possible because * some ext2 macro-instructions depend on its value */ - es = (struct ext2_super_block *) bh->b_data; + es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sb->u.ext2_sb.s_es = es; sb->s_magic = le16_to_cpu(es->s_magic); if (sb->s_magic != EXT2_SUPER_MAGIC) { @@ -438,7 +466,17 @@ if (sb->s_blocksize != BLOCK_SIZE && (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 || sb->s_blocksize == 4096)) { - unsigned long offset; + /* + * Make sure the blocksize for the filesystem is larger + * than the hardware sectorsize for the machine. + */ + hblock = get_hardblocksize(dev); + if( (hblock != 0) + && (sb->s_blocksize < hblock) ) + { + printk("EXT2-fs: blocksize too small for device.\n"); + goto failed_mount; + } brelse (bh); set_blocksize (dev, sb->s_blocksize); diff -urN linux-2.1.26-2k/fs/fat/buffer.c.~1~ linux-2.1.26-2k/fs/fat/buffer.c --- linux-2.1.26-2k/fs/fat/buffer.c.~1~ Fri May 10 06:54:52 1996 +++ linux-2.1.26-2k/fs/fat/buffer.c Thu Mar 27 22:56:43 1997 @@ -16,13 +16,18 @@ { struct buffer_head *ret = NULL; - /* Note that the blocksize is 512 or 1024, but the first read - is always of size 1024. Doing readahead may be counterproductive + /* Note that the blocksize is 512, 1024 or 2048, but the first read + is always of size 1024 (or 2048). Doing readahead may be counterproductive or just plain wrong. */ if (sb->s_blocksize == 512) { ret = bread (sb->s_dev,block,512); } else { - struct buffer_head *real = bread (sb->s_dev,block>>1,1024); + 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); + } if (real != NULL){ ret = (struct buffer_head *) @@ -59,7 +64,11 @@ */ memset (ret,0,sizeof(*ret)); ret->b_data = real->b_data; - if (block & 1) ret->b_data += 512; + 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); diff -urN linux-2.1.26-2k/fs/fat/inode.c.~1~ linux-2.1.26-2k/fs/fat/inode.c --- linux-2.1.26-2k/fs/fat/inode.c.~1~ Mon Dec 30 15:45:36 1996 +++ linux-2.1.26-2k/fs/fat/inode.c Thu Mar 27 22:56:43 1997 @@ -172,8 +172,8 @@ *blksize = simple_strtoul(value,&value,0); if (*value) return 0; - if (*blksize != 512 && *blksize != 1024){ - printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n"); + if (*blksize != 512 && *blksize != 1024 && *blksize != 2048){ + printk ("MSDOS FS: Invalid blocksize (512, 1024 or 2048)\n"); } } else if (!strcmp(this_char,"sys_immutable")) { @@ -205,16 +205,25 @@ } } if (!parse_options((char *) data, &fat, &blksize, &debug, &opts) - || (blksize != 512 && blksize != 1024)) { + || (blksize != 512 && blksize != 1024 && blksize != 2048)) { sb->s_dev = 0; MOD_DEC_USE_COUNT; return NULL; } cache_init(); lock_super(sb); - /* The first read is always 1024 bytes */ - sb->s_blocksize = 1024; - set_blocksize(sb->s_dev, 1024); + 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); + } bh = fat_bread(sb, 0); unlock_super(sb); if (bh == NULL || !fat_is_uptodate(sb,bh)) { @@ -226,6 +235,7 @@ } b = (struct msdos_boot_sector *) bh->b_data; set_blocksize(sb->s_dev, blksize); + /* * The DOS3 partition size limit is *not* 32M as many people think. * Instead, it is 64K sectors (with the usual sector size being @@ -285,7 +295,7 @@ /* the misfit with buffer cache and cluster */ /* because clusters (DOS) are often aligned */ /* on odd sectors. */ - sb->s_blocksize_bits = blksize == 512 ? 9 : 10; + sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11); 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," @@ -451,7 +461,7 @@ !is_exec(raw_entry->ext))) ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG; - inode->i_op = (sb->s_blocksize == 1024) + inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048) ? &fat_file_inode_operations_1024 : &fat_file_inode_operations; MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); diff -urN linux-2.1.26-2k/fs/buffer.c.~1~ linux-2.1.26-2k/fs/buffer.c --- linux-2.1.26-2k/fs/buffer.c.~1~ Sun Jan 26 11:07:30 1997 +++ linux-2.1.26-2k/fs/buffer.c Thu Mar 27 22:56:43 1997 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -468,8 +469,9 @@ if (tmp->b_size == size) return tmp; else { - printk("VFS: Wrong blocksize on device %s\n", - kdevname(dev)); + printk("VFS: Wrong blocksize on device %s (%ld +!= %d)\n", + kdevname(dev), tmp->b_size, size); return NULL; } return NULL; @@ -496,6 +498,31 @@ return bh; bh->b_count--; } +} + +unsigned int get_hardblocksize(kdev_t dev) +{ + int blksize = 0; + + /* + * Get the hard sector size for the given device. If we don't know + * what it is, return 0. + */ + + if (hardsect_size[MAJOR(dev)] != NULL) + { + blksize = hardsect_size[MAJOR(dev)][MINOR(dev)]; + if (blksize != 0) + { + return blksize; + } + } + + /* + * We don't know what the hardware sector size for this device is. + * Return 0 indicating that we don't know. + */ + return 0; } void set_blocksize(kdev_t dev, int size) diff -urN linux-2.1.26-2k/kernel/ksyms.c.~1~ linux-2.1.26-2k/kernel/ksyms.c --- linux-2.1.26-2k/kernel/ksyms.c.~1~ Fri Feb 7 14:54:55 1997 +++ linux-2.1.26-2k/kernel/ksyms.c Sun Mar 30 10:45:52 1997 @@ -148,6 +148,7 @@ EXPORT_SYMBOL(permission); EXPORT_SYMBOL(inode_setattr); EXPORT_SYMBOL(inode_change_ok); +EXPORT_SYMBOL(get_hardblocksize); EXPORT_SYMBOL(set_blocksize); EXPORT_SYMBOL(getblk); EXPORT_SYMBOL(bread); diff -urN linux-2.1.26-2k/include/linux/fs.h.~1~ linux-2.1.26-2k/include/linux/fs.h --- linux-2.1.26-2k/include/linux/fs.h.~1~ Thu Feb 6 11:53:33 1997 +++ linux-2.1.26-2k/include/linux/fs.h Mon Mar 31 23:39:45 1997 @@ -116,6 +116,7 @@ #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ #define BLKRASET _IO(0x12,98) /* Set read ahead for block device */ #define BLKRAGET _IO(0x12,99) /* get current read ahead setting */ +#define BLKHARDSIZE _IO(0x12,100) /* get hardware block size */ #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */ @@ -649,6 +650,7 @@ __bforget(buf); } extern void set_blocksize(kdev_t dev, int size); +extern unsigned int get_hardblocksize(kdev_t dev); extern struct buffer_head * bread(kdev_t dev, int block, int size); extern struct buffer_head * breada(kdev_t dev,int block, int size, unsigned int pos, unsigned int filesize); diff -urN linux-2.1.26-2k/drivers/block/genhd.c.~1~ linux-2.1.26-2k/drivers/block/genhd.c --- linux-2.1.26-2k/drivers/block/genhd.c.~1~ Mon Dec 30 11:06:22 1996 +++ linux-2.1.26-2k/drivers/block/genhd.c Thu Mar 27 22:56:43 1997 @@ -24,9 +24,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD #include -#endif #include @@ -98,9 +96,20 @@ static void add_partition (struct gendisk *hd, int minor, int start, int size) { char buf[8]; +#if 1 + int hwsecsize = hardsect_size [hd->major][minor]; +#endif + hd->part[minor].start_sect = start; hd->part[minor].nr_sects = size; +#if 1 + printk(" %s (%ld - %ld [%d])\n", disk_name(hd, minor, buf), + hd->part[minor].start_sect, + hd->part[minor].nr_sects, + hwsecsize); +#else printk(" %s", disk_name(hd, minor, buf)); +#endif } static inline int is_extended_partition(struct partition *p) @@ -109,6 +118,53 @@ SYS_IND(p) == LINUX_EXTENDED_PARTITION); } +static unsigned int get_ptable_blocksize(kdev_t dev) +{ + int ret = 1024; + + /* + * See whether the low-level driver has given us a minumum blocksize. + * If so, check to see whether it is larger than the default of 1024. + */ + if (!blksize_size[MAJOR(dev)]) + { + return ret; + } + + /* + * Check for certain special power of two sizes that we allow. + * With anything larger than 1024, we must force the blocksize up to + * the natural blocksize for the device so that we don't have to try + * and read partial sectors. Anything smaller should be just fine. + */ + + switch( blksize_size[MAJOR(dev)][MINOR(dev)] ) + { + case 2048: + ret = 2048; + break; + case 4096: + ret = 4096; + break; + case 8192: + ret = 8192; + break; + case 1024: + case 512: + case 256: + case 0: + /* + * These are all OK. + */ + break; + default: + panic("Strange blocksize for partition table\n"); + } + + return ret; + +} + #ifdef CONFIG_MSDOS_PARTITION /* * Create devices for each logical partition in an extended partition. @@ -130,6 +186,7 @@ unsigned long first_sector, first_size, this_sector, this_size; int mask = (1 << hd->minor_shift) - 1; int i; + int hwsecsizeadj = 1; first_sector = hd->part[MINOR(dev)].start_sect; first_size = hd->part[MINOR(dev)].nr_sects; @@ -138,7 +195,7 @@ while (1) { if ((current_minor & mask) == 0) return; - if (!(bh = bread(dev,0,1024))) + if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) return; /* * This block is from a device that we're about to stomp on. @@ -169,8 +226,12 @@ if (!NR_SECTS(p) || is_extended_partition(p)) continue; + hwsecsizeadj = hardsect_size [hd->major][MINOR(dev)] >> 9; /* Check the 3rd and 4th entries - these sometimes contain random garbage */ + /* !!! Take care of this for BIG hardware sector + * sizes later + */ if (i >= 2 && START_SECT(p) + NR_SECTS(p) > this_size && (this_sector + START_SECT(p) < first_sector || @@ -178,7 +239,17 @@ first_sector + first_size)) continue; - add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p)); + if (hwsecsizeadj > 1) + { + printk (" !!! sectors adjusted! Good Luck !!!\n"); + add_partition(hd, current_minor, + this_sector+START_SECT(p) * hwsecsizeadj, + NR_SECTS(p) * hwsecsizeadj); + } + else + add_partition(hd, current_minor, + this_sector+START_SECT(p) * hwsecsizeadj, + NR_SECTS(p) * hwsecsizeadj); current_minor++; if ((current_minor & mask) == 0) goto done; @@ -200,9 +271,22 @@ if (i == 4) goto done; /* nothing left to do */ - hd->part[current_minor].nr_sects = NR_SECTS(p); - hd->part[current_minor].start_sect = first_sector + START_SECT(p); - this_sector = first_sector + START_SECT(p); + if (hwsecsizeadj > 1) + { + printk (" ! temporary now resized !\n"); + hd->part[current_minor].nr_sects = NR_SECTS(p) * + hwsecsizeadj; + hd->part[current_minor].start_sect = first_sector + + START_SECT(p) * hwsecsizeadj; + this_sector = first_sector + START_SECT(p) * hwsecsizeadj; + } + else + { + hd->part[current_minor].nr_sects = NR_SECTS(p); + hd->part[current_minor].start_sect = first_sector + + START_SECT(p); + this_sector = first_sector + START_SECT(p); + } dev = MKDEV(hd->major, current_minor); brelse(bh); } @@ -222,7 +306,7 @@ struct bsd_partition *p; int mask = (1 << hd->minor_shift) - 1; - if (!(bh = bread(dev,0,1024))) + if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) return; bh->b_state = 0; l = (struct bsd_disklabel *) (bh->b_data+512); @@ -254,12 +338,13 @@ struct partition *p; unsigned char *data; int mask = (1 << hd->minor_shift) - 1; + int hwsecsizeadj = 1; #ifdef CONFIG_BLK_DEV_IDE int tested_for_xlate = 0; read_mbr: #endif - if (!(bh = bread(dev,0,1024))) { + if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) { printk(" unable to read partition table\n"); return -1; } @@ -346,11 +431,24 @@ } #endif /* CONFIG_BLK_DEV_IDE */ - current_minor += 4; /* first "extra" minor (for extended partitions) */ + current_minor += 4; /* first "extra" minor (for extended partitions) + */ for (i=1 ; i<=4 ; minor++,i++,p++) { + hwsecsizeadj = hardsect_size [hd->major][minor] >> 9; if (!NR_SECTS(p)) continue; - add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p)); + if (hwsecsizeadj > 1) + { + printk (" !!! sectors adjusted! Good Luck !!!\n"); + add_partition(hd, minor, + first_sector+START_SECT(p) * hwsecsizeadj, + NR_SECTS(p) * hwsecsizeadj); + } + else + { + add_partition(hd, minor, first_sector+START_SECT(p), + NR_SECTS(p)); + } if (is_extended_partition(p)) { printk(" <"); /* @@ -365,8 +463,23 @@ printk(" >"); /* prevent someone doing mkfs or mkswap on an extended partition, but leave room for LILO */ - if (hd->part[minor].nr_sects > 2) - hd->part[minor].nr_sects = 2; + + /* !!! This needed work to support BIG hardware + * sector sizes. + * It seems to be rather dangerous this way + * but otherwise, access seems to be impossible + */ + if (hardsect_size [hd->major][minor] > 1024) + { + if (hd->part[minor].nr_sects > 4) + hd->part[minor].nr_sects = + (hardsect_size [hd->major][minor] >> 9); + } + else + { + if (hd->part[minor].nr_sects > 2) + hd->part[minor].nr_sects = 2; + } } #ifdef CONFIG_BSD_DISKLABEL if (SYS_IND(p) == BSD_PARTITION) { @@ -438,7 +551,7 @@ struct d_partition * partition; #define DISKLABELMAGIC (0x82564557UL) - if (!(bh = bread(dev,0,1024))) { + if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) { printk("unable to read partition table\n"); return -1; } @@ -501,7 +614,7 @@ unsigned long spc; #define SUN_LABEL_MAGIC 0xDABE - if(!(bh = bread(dev, 0, 1024))) { + if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read partition table\n", kdevname(dev)); return -1; diff -urN linux-2.1.26-2k/drivers/scsi/scsicam.c.~1~ linux-2.1.26-2k/drivers/scsi/scsicam.c --- linux-2.1.26-2k/drivers/scsi/scsicam.c.~1~ Thu Nov 7 10:25:56 1996 +++ linux-2.1.26-2k/drivers/scsi/scsicam.c Thu Mar 27 22:56:43 1997 @@ -50,9 +50,19 @@ struct buffer_head *bh; int ret_code; int size = disk->capacity; + unsigned secsize = disk->sector_size; - if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024))) + if ( secsize > 1024 ) { +#if 1 + printk ("scsicam_bios_param : sectorsize %u, capacity %u\n", + secsize, size); +#endif + if ( ! (bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, secsize))) return -1; + } else { + if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024))) + return -1; + } /* try to infer mapping from partition table */ ret_code = partsize (bh, (unsigned long) size, (unsigned int *) ip + 2, diff -urN linux-2.1.26-2k/drivers/scsi/sd.c.~1~ linux-2.1.26-2k/drivers/scsi/sd.c --- linux-2.1.26-2k/drivers/scsi/sd.c.~1~ Sun Jan 26 11:07:20 1997 +++ linux-2.1.26-2k/drivers/scsi/sd.c Sun Mar 30 10:26:08 1997 @@ -60,7 +60,7 @@ */ #define SD_TIMEOUT (15 * HZ) -#define SD_MOD_TIMEOUT (15 * HZ) +#define SD_MOD_TIMEOUT (75 * HZ) #define CLUSTERABLE_DEVICE(SC) (SC->host->use_clustering && \ SC->device->type != TYPE_MOD) @@ -253,6 +253,11 @@ error_sector <<= 1; if (block_sectors < 2) block_sectors = 2; } + else if (sector_size == 2048) + { + error_sector <<= 2; + if (block_sectors < 4) block_sectors = 4; + } else if (sector_size == 256) error_sector >>= 1; error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect; @@ -628,7 +633,14 @@ */ if (rscsi_disks[dev].sector_size == 1024) if((block & 1) || (SCpnt->request.nr_sectors & 1)) { - printk("sd.c:Bad block number requested"); + printk("sd.c:Bad block number requested. "); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + goto repeat; + } + + if (rscsi_disks[dev].sector_size == 2048) + if((block & 3) || (SCpnt->request.nr_sectors & 3)) { + printk("sd.c:Bad block number requested. "); SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; } @@ -899,6 +911,13 @@ cmd[1] = (SCpnt->lun << 5) & 0xe0; + if (rscsi_disks[dev].sector_size == 2048){ + if(block & 3) panic("sd.c:Bad block number requested"); + if(this_count & 3) panic("sd.c:Bad block number requested"); + block = block >> 2; + this_count = this_count >> 2; + } + if (rscsi_disks[dev].sector_size == 1024){ if(block & 1) panic("sd.c:Bad block number requested"); if(this_count & 1) panic("sd.c:Bad block number requested"); @@ -1200,6 +1219,7 @@ if (rscsi_disks[i].sector_size != 512 && rscsi_disks[i].sector_size != 1024 && + rscsi_disks[i].sector_size != 2048 && rscsi_disks[i].sector_size != 256) { printk ("sd%c : unsupported sector size %d.\n", @@ -1213,6 +1233,22 @@ return i; } } + + if( rscsi_disks[i].sector_size == 2048 ) + { + int m; + + /* + * We must fix the sd_blocksizes and sd_hardsizes + * to allow us to read the partition tables. + * The disk reading code does not allow for reading + * of partial sectors. + */ + for (m=i<<4; m<((i+1)<<4); m++) + { + sd_blocksizes[m] = 2048; + } + } { /* * The msdos fs needs to know the hardware sector size @@ -1236,6 +1272,8 @@ i+'a', hard_sector, rscsi_disks[i].capacity, mb, sz_quot, sz_rem); } + if(rscsi_disks[i].sector_size == 2048) + rscsi_disks[i].capacity <<= 2; /* Change into 512 byte sectors */ if(rscsi_disks[i].sector_size == 1024) rscsi_disks[i].capacity <<= 1; /* Change into 512 byte sectors */ if(rscsi_disks[i].sector_size == 256) @@ -1475,9 +1513,15 @@ gdev->part[minor].nr_sects = 0; /* * Reset the blocksize for everything so that we can read - * the partition table. + * the partition table. Technically we will determine the + * correct block size when we revalidate, but we do this just + * to make sure that everything remains consistent. */ blksize_size[MAJOR_NR][minor] = 1024; + if( rscsi_disks[target].sector_size == 2048 ) + blksize_size[MAJOR_NR][minor] = 2048; + else + blksize_size[MAJOR_NR][minor] = 1024; } #ifdef MAYBE_REINIT diff -urN linux-2.1.26-2k/drivers/scsi/sr.c.~1~ linux-2.1.26-2k/drivers/scsi/sr.c --- linux-2.1.26-2k/drivers/scsi/sr.c.~1~ Sun Jan 26 11:07:21 1997 +++ linux-2.1.26-2k/drivers/scsi/sr.c Sun Mar 30 22:42:18 1997 @@ -60,9 +60,10 @@ sr_finish, sr_attach, sr_detach}; Scsi_CD * scsi_CDs = NULL; -static int * sr_sizes; +static int * sr_sizes = NULL; -static int * sr_blocksizes; +static int * sr_blocksizes = NULL; +static int * sr_hardsizes = NULL; /* Hardware sector size */ static int sr_open(struct cdrom_device_info*, int); void get_sectorsize(int); @@ -130,17 +131,24 @@ scsi_CDs[MINOR(cdi->dev)].device->changed = 1; return 1; /* This will force a flush, if called from * check_disk_change */ - }; + } retval = scsi_CDs[MINOR(cdi->dev)].device->changed; scsi_CDs[MINOR(cdi->dev)].device->changed = 0; - /* If the disk changed, the capacity will now be different, - * so we force a re-read of this information */ + /* + * If the disk changed, the capacity will now be different, + * so we force a re-read of this information + * Force 2048 for the sector size so that filesystems won't + * be trying to use something that is too small if the disc + * has changed. + */ if (retval) { #ifdef CONFIG_BLK_DEV_SR_VENDOR sr_cd_check(cdi); #endif scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1; + scsi_CDs[MINOR(cdi->dev)].sector_size = + sr_hardsizes[MINOR(cdi->dev)] = 2048; } return retval; } @@ -894,6 +902,12 @@ scsi_CDs[i].capacity = 0; scsi_CDs[i].needs_sector_size = 1; } + + /* + * Add this so that we have the ability to correctly gauge + * what the device is capable of. + */ + sr_hardsizes[i] = scsi_CDs[i].sector_size; scsi_CDs[i].needs_sector_size = 0; sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9); }; @@ -928,8 +942,16 @@ sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); + sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max * + sizeof(int), GFP_ATOMIC); + + /* + * These are good guesses for the time being. + */ for(i=0;irequest; req->errors = 0; if (!uptodate) { - printk(DEVICE_NAME " I/O error: dev %s, sector %lu\n", - kdevname(req->rq_dev), req->sector); + printk(DEVICE_NAME " I/O error: dev %s, sector %lu [%lu]\n", + kdevname(req->rq_dev), req->sector, req->nr_sectors); } do { diff -urN linux-2.1.26-2k/drivers/scsi/sd_ioctl.c.~1~ linux-2.1.26-2k/drivers/scsi/sd_ioctl.c --- linux-2.1.26-2k/drivers/scsi/sd_ioctl.c.~1~ Fri Nov 29 10:20:08 1996 +++ linux-2.1.26-2k/drivers/scsi/sd_ioctl.c Thu Mar 27 22:56:44 1997 @@ -65,6 +65,15 @@ (long *) arg); return 0; + case BLKHARDSIZE: /* return size of hardware sectors */ + if (!arg) return -EINVAL; + error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); + if (error) + return error; + put_user(rscsi_disks[MINOR(dev) >> 4].sector_size, + (unsigned int *) arg); + return 0; + case BLKRASET: if (!suser()) return -EACCES;