diff -ru pure/linux-2.4.24/drivers/block/loop.c linux-2.4.24/drivers/block/loop.c --- pure/linux-2.4.24/drivers/block/loop.c 2003-08-25 07:44:41.000000000 -0400 +++ linux-2.4.24/drivers/block/loop.c 2004-02-16 20:31:50.000000000 -0500 @@ -39,6 +39,23 @@ * Support up to 256 loop devices * Heinz Mauelshagen , Feb 2002 * + * Partition enhancement Scyld Computing Corporation + * -geometry get/set ioctls + * -integration of genhd routines + * -read-only support + * + * Scyld partition enhancement port from Linux SGI XFS 0.10.1 -> stock 2.4.5 + * Port work done by: + * - Headquarters National Aeronautics and Space Administration (NASA) + * Office of the Inspector General, Computer Crimes Division + * Jason T. Luttgens + * - Department of Defense Computer Forensics Laboratory (DCFL) + * Engineering Branch + * Nicholas J. Harbour + * With assistance from: + * - Scyld Computing Corporation + * Rick Niles + * * Still To Fix: * - Advisory locking is ignored here. * - Should use an own CAP_* category instead of CAP_SYS_ADMIN @@ -54,6 +71,15 @@ * number. */ +#ifndef __KERNEL__ +#define __KERNEL__ +#endif +#if !defined(__OPTIMIZE__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + #include #include @@ -84,6 +110,60 @@ static int *loop_blksizes; static devfs_handle_t devfs_handle; /* For the directory */ +static int read_only = 0; +MODULE_PARM(read_only, "i"); + + +/* Generalized loopback device only. */ +#include +#include +#ifndef HDIO_GETGEO +#define HDIO_GETGEO 0x0301 /* get device geometry */ +#endif +#ifndef HDIO_SETGEO +#define HDIO_SETGEO 0x0328 /* set device geometry */ +#endif + +/* Geometry information for the generalized loopback device. */ +#ifndef LOG2_NR_PARTITION +#define LOG2_NR_PARTITION 4 /* 6 means up to 64 partitions, 4->16. */ +#endif + +#define SECTOR_SIZE 512 +/* Get the drive index from the device minor number. */ +#define DEVICE_NR(device) (MINOR(device) >> LOG2_NR_PARTITION) + +static struct hd_struct *loop; +static struct hd_geometry *loop_geom; + +static int lo_open(struct inode *inode, struct file *file); +static int lo_release(struct inode *inode, struct file *file); +static int lo_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg); + +static struct block_device_operations lo_fops = { + owner: THIS_MODULE, + open: lo_open, + release: lo_release, + ioctl: lo_ioctl, +}; + +static struct gendisk loop_gendisk = { + MAJOR_NR, /* major number */ + "loop", /* major name */ + LOG2_NR_PARTITION, /* bits to shift to get real from partition */ + 1 << LOG2_NR_PARTITION, /* number of partitions per real */ + NULL, /* hd struct */ + NULL, /* loop_sizes */ /* block sizes */ + 0, /* number */ + NULL, /* internal */ + NULL, /* next */ + &lo_fops, /* block_device_operations */ + NULL, /* devfs_handle de_arr */ + NULL /* flags */ +}; + + /* * Transfer functions */ @@ -221,7 +301,7 @@ len -= size; offset = 0; index++; - pos += size; + pos += (loff_t)size; UnlockPage(page); page_cache_release(page); } @@ -309,6 +389,16 @@ IV = sector / (bs >> 9) + lo->lo_offset / bs; offset = ((sector % (bs >> 9)) << 9) + lo->lo_offset % bs; + + /* added in the partition stuff here. */ + if (lo->lo_key_owner) { + long sect = loop_gendisk.part[lo->lo_key_owner].start_sect + - loop_gendisk.part[lo->lo_key_owner & 0xf0].start_sect; + IV += (sect*SECTOR_SIZE) / bs; + offset += (sect*SECTOR_SIZE) % bs; + } + + if (offset >= bs) IV++; @@ -320,7 +410,14 @@ loff_t pos; int ret; - pos = ((loff_t) bh->b_rsector << 9) + lo->lo_offset; + pos = (loff_t)((loff_t) bh->b_rsector << 9) + (loff_t)lo->lo_offset; + + /* added in the partition stuff here. */ + if (lo->lo_key_owner & 0xf) { + long sect = loop_gendisk.part[lo->lo_key_owner].start_sect + - loop_gendisk.part[(lo->lo_key_owner & 0xf0)].start_sect; + pos += ((loff_t)sect*(loff_t)SECTOR_SIZE); + } if (rw == WRITE) ret = lo_send(lo, bh, loop_get_bs(lo), pos); @@ -388,7 +485,7 @@ */ static void loop_end_io_transfer(struct buffer_head *bh, int uptodate) { - struct loop_device *lo = &loop_dev[MINOR(bh->b_dev)]; + struct loop_device *lo = &loop_dev[DEVICE_NR(bh->b_dev)]; if (!uptodate || test_bit(BH_Dirty, &bh->b_state)) { struct buffer_head *rbh = bh->b_private; @@ -447,6 +544,14 @@ bh->b_data = page_address(bh->b_page); bh->b_end_io = loop_end_io_transfer; bh->b_private = rbh; + + /* added in the partition stuff here. */ + if (lo->lo_key_owner & 0xf) { + long sect = loop_gendisk.part[lo->lo_key_owner].start_sect + - loop_gendisk.part[lo->lo_key_owner & 0xf0].start_sect; + bh->b_rsector += (sect*SECTOR_SIZE); + } + init_waitqueue_head(&bh->b_wait); out_bh: @@ -467,10 +572,13 @@ if (!buffer_locked(rbh)) BUG(); - if (MINOR(rbh->b_rdev) >= max_loop) + if (DEVICE_NR(rbh->b_rdev) >= max_loop) goto out; - lo = &loop_dev[MINOR(rbh->b_rdev)]; + lo = &loop_dev[DEVICE_NR(rbh->b_rdev)]; + + lo->lo_key_owner = MINOR(rbh->b_rdev); + spin_lock_irq(&lo->lo_lock); if (lo->lo_state != Lo_bound) goto inactive; @@ -478,7 +586,7 @@ spin_unlock_irq(&lo->lo_lock); if (rw == WRITE) { - if (lo->lo_flags & LO_FLAGS_READ_ONLY) + if (((lo->lo_flags & LO_FLAGS_READ_ONLY)) || read_only) goto err; } else if (rw == READA) { rw = READ; @@ -628,6 +736,11 @@ MOD_INC_USE_COUNT; + error = -EINVAL; + /* We only accept this for the whole "drive". */ + if (MINOR(dev) & ((1 << LOG2_NR_PARTITION) - 1)) + goto out; + error = -EBUSY; if (lo->lo_state != Lo_unbound) goto out; @@ -670,7 +783,7 @@ get_file(file); if (IS_RDONLY (inode) || is_read_only(lo_device) - || !(lo_file->f_mode & FMODE_WRITE)) + || !(lo_file->f_mode & FMODE_WRITE) || read_only) lo_flags |= LO_FLAGS_READ_ONLY; set_device_ro(dev, (lo_flags & LO_FLAGS_READ_ONLY) != 0); @@ -736,11 +849,15 @@ return err; } -static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) +static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev, kdev_t dev) { struct file *filp = lo->lo_backing_file; int gfp = lo->old_gfp_mask; + /* We only accept this for the whole "drive". */ + if (MINOR(dev) & ((1 << LOG2_NR_PARTITION) - 1)) + return -EINVAL; + if (lo->lo_state != Lo_bound) return -ENXIO; if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ @@ -768,16 +885,29 @@ lo->lo_flags = 0; memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_name, 0, LO_NAME_SIZE); - loop_sizes[lo->lo_number] = 0; + memset(loop_sizes + (lo->lo_number >> LOG2_NR_PARTITION), 0, + sizeof(loop_sizes[0]) << LOG2_NR_PARTITION); invalidate_bdev(bdev, 0); filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; lo->lo_state = Lo_unbound; fput(filp); + { + int p = DEVICE_NR(dev) << LOG2_NR_PARTITION; + for ( ; p < (DEVICE_NR(dev) + 1) << LOG2_NR_PARTITION; p++) { + if (loop_gendisk.part[p].nr_sects > 0) { + kdev_t devp = MKDEV(LOOP_MAJOR, p); + invalidate_buffers(devp); + } + loop_gendisk.part[p].start_sect = 0; + loop_gendisk.part[p].nr_sects = 0; + } + } + MOD_DEC_USE_COUNT; return 0; } -static int loop_set_status(struct loop_device *lo, struct loop_info *arg) +static int loop_set_status(struct loop_device *lo, kdev_t dev, struct loop_info *arg) { struct loop_info info; int err; @@ -817,6 +947,36 @@ lo->lo_key_owner = current->uid; } figure_loop_size(lo); + { + int tmp_size = loop_sizes[lo->lo_number]; + int target = DEVICE_NR(dev); + int uneven_i_size = 0; + loop_gendisk.sizes = loop_sizes; + loop_gendisk.real_devices = loop_dev; + loop_gendisk.part = loop; + if ( lo->lo_backing_file->f_dentry->d_inode->i_size % 512) { + printk(KERN_DEBUG "File size not divisible by 512, adding an extra sector to the device size.\n"); + uneven_i_size = 1; + } + register_disk(&loop_gendisk, MKDEV(MAJOR_NR, MINOR(dev)), + 1 << LOG2_NR_PARTITION, &lo_fops, + (long)(lo->lo_backing_file->f_dentry->d_inode->i_size / 512) + uneven_i_size ); + printk(KERN_DEBUG "Registering a loopback device of %llu sectors.\n", + (lo->lo_backing_file->f_dentry->d_inode->i_size / 512) + uneven_i_size ); + { + int i; + int start = target<> 1; + printk (KERN_DEBUG "start %ld, nr_sects = %ld\n", + loop_gendisk.part[i].start_sect, + loop_gendisk.part[i].nr_sects); + } + } + blk_size[LOOP_MAJOR][MINOR(dev)] = tmp_size; + } + return 0; } @@ -850,7 +1010,7 @@ unsigned int cmd, unsigned long arg) { struct loop_device *lo; - int dev, err; + int dev, err = 0; if (!inode) return -EINVAL; @@ -859,9 +1019,9 @@ MAJOR_NR); return -ENODEV; } - dev = MINOR(inode->i_rdev); - if (dev >= max_loop) - return -ENODEV; + dev = DEVICE_NR(inode->i_rdev); + if (dev >= max_loop) + return -ENODEV; lo = &loop_dev[dev]; down(&lo->lo_ctl_mutex); switch (cmd) { @@ -869,10 +1029,10 @@ err = loop_set_fd(lo, file, inode->i_rdev, arg); break; case LOOP_CLR_FD: - err = loop_clr_fd(lo, inode->i_bdev); + err = loop_clr_fd(lo, inode->i_bdev, inode->i_rdev); break; case LOOP_SET_STATUS: - err = loop_set_status(lo, (struct loop_info *) arg); + err = loop_set_status(lo, inode->i_rdev, (struct loop_info *) arg); break; case LOOP_GET_STATUS: err = loop_get_status(lo, (struct loop_info *) arg); @@ -882,20 +1042,57 @@ err = -ENXIO; break; } - err = put_user((unsigned long)loop_sizes[lo->lo_number] << 1, (unsigned long *) arg); - break; + err = put_user((unsigned long)loop_sizes[MINOR(inode->i_rdev)] << 1, (unsigned long *) arg); + break; case BLKGETSIZE64: if (lo->lo_state != Lo_bound) { err = -ENXIO; break; } - err = put_user((u64)loop_sizes[lo->lo_number] << 10, (u64*)arg); + err = put_user((u64)loop_sizes[MINOR(inode->i_rdev)] << 10, (u64*)arg); break; case BLKBSZGET: case BLKBSZSET: case BLKSSZGET: err = blk_ioctl(inode->i_rdev, cmd, arg); break; + case HDIO_GETGEO: + if (arg) { + struct hd_geometry *geom_out = (struct hd_geometry *) arg; + struct hd_geometry *drive_geom = &loop_geom[dev]; + struct hd_geometry geom = *drive_geom; + + if ((!geom_out) || (geom.heads == 0) ) { + err = -EINVAL; + break; + } + + /* The starting sector comes from the partition info, not the + whole-drive info. */ + geom.start = loop_gendisk.part[MINOR(inode->i_rdev)].start_sect; + err = copy_to_user(geom_out, &geom, sizeof geom) ? -EFAULT : 0; + break; + } + break; + case HDIO_SETGEO: + if (arg) { + struct hd_geometry *geometry = (struct hd_geometry *) arg; + struct hd_geometry *drive_geom = &loop_geom[dev]; + int err; + int num_sectors; + + if ((err = verify_area(VERIFY_READ,geometry,sizeof(*geometry)))) + break; + get_user(drive_geom->heads, &geometry->heads); + get_user(drive_geom->sectors, &geometry->sectors); + get_user(drive_geom->cylinders, &geometry->cylinders); + + num_sectors = loop_geom[dev].heads * loop_geom[dev].sectors + * loop_geom[dev].cylinders; + printk("loop: added a geometry addressing %d sectors!\n", + num_sectors); + } + break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } @@ -942,7 +1139,7 @@ MAJOR_NR); return 0; } - dev = MINOR(inode->i_rdev); + dev = DEVICE_NR(inode->i_rdev); if (dev >= max_loop) return 0; @@ -958,12 +1155,7 @@ return 0; } -static struct block_device_operations lo_fops = { - owner: THIS_MODULE, - open: lo_open, - release: lo_release, - ioctl: lo_ioctl, -}; + /* * And now the modules code and kernel interface. @@ -1017,18 +1209,47 @@ return -EIO; } + loop_gendisk.next = gendisk_head; + gendisk_head = &loop_gendisk; + loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); if (!loop_dev) return -ENOMEM; - loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL); + loop_sizes = kmalloc((max_loop << LOG2_NR_PARTITION) * sizeof(int), + GFP_KERNEL); if (!loop_sizes) goto out_sizes; - loop_blksizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL); + memset (loop_sizes, 0, (max_loop << LOG2_NR_PARTITION) * sizeof(int)); + memset (loop_dev, 0, max_loop * sizeof(struct loop_device)); + + loop_blksizes = kmalloc((max_loop << LOG2_NR_PARTITION) * sizeof(int), + GFP_KERNEL); + if (!loop_blksizes) goto out_blksizes; + memset (loop_blksizes, 0, (max_loop << LOG2_NR_PARTITION) * sizeof(int)); + + loop = kmalloc ( (max_loop << LOG2_NR_PARTITION) + * sizeof(struct hd_struct), GFP_KERNEL); + if (!loop) + goto out_loop; + + memset (loop, 0, (max_loop << LOG2_NR_PARTITION) + * sizeof(struct hd_struct)); + + loop_geom = kmalloc ((max_loop << LOG2_NR_PARTITION) + * sizeof(struct hd_geometry), + GFP_KERNEL); + + if (!loop_geom) + goto out_geom; + + memset (loop_geom, 0, (max_loop << LOG2_NR_PARTITION) + * sizeof(struct hd_geometry)); + blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), loop_make_request); @@ -1057,7 +1278,11 @@ printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); return 0; - + +out_geom: + kfree(loop); +out_loop: + kfree(loop_blksizes); out_blksizes: kfree(loop_sizes); out_sizes: @@ -1073,6 +1298,27 @@ devfs_unregister(devfs_handle); if (devfs_unregister_blkdev(MAJOR_NR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); + { + struct gendisk *prev_gd,*gd; + gd=gendisk_head; + prev_gd=NULL; + while(gd != &loop_gendisk) + { + prev_gd = gd; + gd = gd->next; + } + + if(gd != &loop_gendisk) + printk(KERN_ERR "lo: loop_gendisk not in disk chain.\n"); + else { + if(prev_gd != NULL) + prev_gd->next = gd->next; + else + gendisk_head = gd->next; + } + } + + kfree(loop_dev); kfree(loop_sizes); kfree(loop_blksizes); diff -ru pure/linux-2.4.24/drivers/ieee1394/sbp2.c linux-2.4.24/drivers/ieee1394/sbp2.c --- pure/linux-2.4.24/drivers/ieee1394/sbp2.c 2003-11-28 13:26:20.000000000 -0500 +++ linux-2.4.24/drivers/ieee1394/sbp2.c 2004-02-16 16:46:09.000000000 -0500 @@ -231,7 +231,7 @@ * enable this define to make use of it. This provides better hotplug * support. The mentioned patch is not part of the kernel proper though, * because it is considered somewhat of a hack. */ -//#define SBP2_USE_SCSI_ADDREM_HACK +#define SBP2_USE_SCSI_ADDREM_HACK /* Only in linux-2.4.24/drivers/input: .depend Only in linux-2.4.24/drivers/isdn/act2000: .depend Only in linux-2.4.24/drivers/isdn/avmb1: .depend Only in linux-2.4.24/drivers/isdn: .depend Only in linux-2.4.24/drivers/isdn/divert: .depend Only in linux-2.4.24/drivers/isdn/eicon: .depend Only in linux-2.4.24/drivers/isdn/hisax: .depend Only in linux-2.4.24/drivers/isdn/hysdn: .depend Only in linux-2.4.24/drivers/isdn/icn: .depend Only in linux-2.4.24/drivers/isdn/isdnloop: .depend Only in linux-2.4.24/drivers/isdn/pcbit: .depend Only in linux-2.4.24/drivers/isdn/sc: .depend Only in linux-2.4.24/drivers/isdn/tpam: .depend Only in linux-2.4.24/drivers/macintosh: .depend Only in linux-2.4.24/drivers/md: .depend Only in linux-2.4.24/drivers/media: .depend Only in linux-2.4.24/drivers/media/radio: .depend Only in linux-2.4.24/drivers/media/video: .depend Only in linux-2.4.24/drivers/message/fusion: .depend Only in linux-2.4.24/drivers/message/i2o: .depend Only in linux-2.4.24/drivers/misc: .depend Only in linux-2.4.24/drivers/mtd/chips: .depend Only in linux-2.4.24/drivers/mtd: .depend Only in linux-2.4.24/drivers/mtd/devices: .depend Only in linux-2.4.24/drivers/mtd/maps: .depend Only in linux-2.4.24/drivers/mtd/nand: .depend Only in linux-2.4.24/drivers/net/appletalk: .depend Only in linux-2.4.24/drivers/net/arcnet: .depend Only in linux-2.4.24/drivers/net/bonding: .depend Only in linux-2.4.24/drivers/net: .depend Only in linux-2.4.24/drivers/net/e100: .depend Only in linux-2.4.24/drivers/net/e1000: .depend Only in linux-2.4.24/drivers/net/fc: .depend Only in linux-2.4.24/drivers/net/hamradio: .depend Only in linux-2.4.24/drivers/net/hamradio/soundmodem: .depend Only in linux-2.4.24/drivers/net/hamradio/soundmodem: gentbl Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_afsk1200.h Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_afsk2400_7.h Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_afsk2400_8.h Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_afsk2666.h Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_fsk9600.h Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_hapn4800.h Only in linux-2.4.24/drivers/net/hamradio/soundmodem: sm_tbl_psk4800.h Only in linux-2.4.24/drivers/net/ibm_emac: .depend Only in linux-2.4.24/drivers/net/irda: .depend Only in linux-2.4.24/drivers/net/pcmcia: .depend Only in linux-2.4.24/drivers/net/sk98lin: .depend Only in linux-2.4.24/drivers/net/skfp: .depend Only in linux-2.4.24/drivers/net/tokenring: .depend Only in linux-2.4.24/drivers/net/tulip: .depend Only in linux-2.4.24/drivers/net/wan/8253x: .depend Only in linux-2.4.24/drivers/net/wan: .depend Only in linux-2.4.24/drivers/net/wan/lmc: .depend Only in linux-2.4.24/drivers/net/wireless: .depend Only in linux-2.4.24/drivers/nubus: .depend Only in linux-2.4.24/drivers/parport: .depend Only in linux-2.4.24/drivers/pci: .depend Only in linux-2.4.24/drivers/pcmcia: .depend Only in linux-2.4.24/drivers/pnp: .depend Only in linux-2.4.24/drivers/sbus/audio: .depend Only in linux-2.4.24/drivers/sbus/char: .depend Only in linux-2.4.24/drivers/sbus: .depend Only in linux-2.4.24/drivers/scsi/aacraid: .depend Only in linux-2.4.24/drivers/scsi/aic7xxx: .depend Only in linux-2.4.24/drivers/scsi: .depend diff -ru pure/linux-2.4.24/drivers/scsi/hosts.h linux-2.4.24/drivers/scsi/hosts.h --- pure/linux-2.4.24/drivers/scsi/hosts.h 2003-06-13 10:51:36.000000000 -0400 +++ linux-2.4.24/drivers/scsi/hosts.h 2004-02-16 15:53:19.000000000 -0500 @@ -535,6 +535,13 @@ int scsi_register_device(struct Scsi_Device_Template * sdpnt); void scsi_deregister_device(struct Scsi_Device_Template * tpnt); +/* Support for hot plugging and unplugging devices -- safe for + * ieee1394 or USB devices, but probably not for normal SCSI... */ +extern int scsi_add_single_device(struct Scsi_Host *shpnt, + int channel, int id, int lun); +extern int scsi_remove_single_device(struct Scsi_Host *shpnt, + int channel, int id, int lun); + /* These are used by loadable modules */ extern int scsi_register_module(int, void *); extern int scsi_unregister_module(int, void *); Only in linux-2.4.24/drivers/scsi/pcmcia: .depend diff -ru pure/linux-2.4.24/drivers/scsi/scsi.c linux-2.4.24/drivers/scsi/scsi.c --- pure/linux-2.4.24/drivers/scsi/scsi.c 2003-08-25 07:44:42.000000000 -0400 +++ linux-2.4.24/drivers/scsi/scsi.c 2004-02-16 15:53:19.000000000 -0500 @@ -1554,6 +1554,96 @@ } } +/* Support for plugging/unplugging SCSI devices. This feature is + * probably unsafe for standard SCSI devices, but is perfectly + * normal for things like ieee1394 or USB drives since these + * busses are designed for hotplugging. Use at your own risk.... */ +int scsi_add_single_device(struct Scsi_Host *shpnt, + int channel, int id, int lun) +{ + Scsi_Device *scd; + + /* Do a bit of sanity checking */ + if (shpnt==NULL) { + return -ENXIO; + } + + /* Check if they asked us to add an already existing device. + * If so, ignore their misguided efforts. */ + for (scd = shpnt->host_queue; scd; scd = scd->next) { + if ((scd->channel == channel && scd->id == id && scd->lun == lun)) { + break; + } + } + if (scd) { + return -ENOSYS; + } + + scan_scsis(shpnt, 1, channel, id, lun); + return 0; +} + +/* Support for plugging/unplugging SCSI devices. This feature is + * probably unsafe for standard SCSI devices, but is perfectly + * normal for things like ieee1394 or USB drives since these + * busses are designed for hotplugging. Use at your own risk.... */ +int scsi_remove_single_device(struct Scsi_Host *shpnt, + int channel, int id, int lun) +{ + Scsi_Device *scd; + struct Scsi_Device_Template *SDTpnt; + + /* Do a bit of sanity checking */ + if (shpnt==NULL) { + return -ENODEV; + } + + /* Make sure the specified device is in fact present */ + for (scd = shpnt->host_queue; scd; scd = scd->next) { + if ((scd->channel == channel && scd->id == id && scd->lun == lun)) { + break; + } + } + if (scd==NULL) { + return -ENODEV; + } + + /* See if the specified device is busy */ + if (scd->access_count) + return -EBUSY; + + SDTpnt = scsi_devicelist; + while (SDTpnt != NULL) { + if (SDTpnt->detach) + (*SDTpnt->detach) (scd); + SDTpnt = SDTpnt->next; + } + + if (scd->attached == 0) { + /* Nobody is using this device, so we + * can now free all command structures. */ + if (shpnt->hostt->revoke) + shpnt->hostt->revoke(scd); + devfs_unregister (scd->de); + scsi_release_commandblocks(scd); + + /* Now we can remove the device structure */ + if (scd->next != NULL) + scd->next->prev = scd->prev; + + if (scd->prev != NULL) + scd->prev->next = scd->next; + + if (shpnt->host_queue == scd) { + shpnt->host_queue = scd->next; + } + blk_cleanup_queue(&scd->request_queue); + kfree((char *) scd); + } + + return 0; +} + #ifdef CONFIG_PROC_FS static int scsi_proc_info(char *buffer, char **start, off_t offset, int length) { @@ -1606,8 +1696,6 @@ static int proc_scsi_gen_write(struct file * file, const char * buf, unsigned long length, void *data) { - struct Scsi_Device_Template *SDTpnt; - Scsi_Device *scd; struct Scsi_Host *HBA_ptr; char *p; int host, channel, id, lun; @@ -1746,33 +1834,11 @@ break; } } - err = -ENXIO; - if (!HBA_ptr) - goto out; - - for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { - if ((scd->channel == channel - && scd->id == id - && scd->lun == lun)) { - break; - } - } - - err = -ENOSYS; - if (scd) - goto out; /* We do not yet support unplugging */ - - scan_scsis(HBA_ptr, 1, channel, id, lun); - - /* FIXME (DB) This assumes that the queue_depth routines can be used - in this context as well, while they were all designed to be - called only once after the detect routine. (DB) */ - /* queue_depth routine moved to inside scan_scsis(,1,,,) so - it is called before build_commandblocks() */ - - err = length; + if ((err=scsi_add_single_device(HBA_ptr, channel, id, lun))==0) + err = length; goto out; } + /* * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi * with "0 1 2 3" replaced by your "Host Channel Id Lun". @@ -1798,58 +1864,8 @@ break; } } - err = -ENODEV; - if (!HBA_ptr) - goto out; - - for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { - if ((scd->channel == channel - && scd->id == id - && scd->lun == lun)) { - break; - } - } - - if (scd == NULL) - goto out; /* there is no such device attached */ - - err = -EBUSY; - if (scd->access_count) - goto out; - - SDTpnt = scsi_devicelist; - while (SDTpnt != NULL) { - if (SDTpnt->detach) - (*SDTpnt->detach) (scd); - SDTpnt = SDTpnt->next; - } - - if (scd->attached == 0) { - /* - * Nobody is using this device any more. - * Free all of the command structures. - */ - if (HBA_ptr->hostt->revoke) - HBA_ptr->hostt->revoke(scd); - devfs_unregister (scd->de); - scsi_release_commandblocks(scd); - - /* Now we can remove the device structure */ - if (scd->next != NULL) - scd->next->prev = scd->prev; - - if (scd->prev != NULL) - scd->prev->next = scd->next; - - if (HBA_ptr->host_queue == scd) { - HBA_ptr->host_queue = scd->next; - } - blk_cleanup_queue(&scd->request_queue); - kfree((char *) scd); - } else { - goto out; - } - err = 0; + err=scsi_remove_single_device(HBA_ptr, channel, id, lun); + goto out; } out: Only in linux-2.4.24/drivers/scsi: scsi.c.orig diff -ru pure/linux-2.4.24/drivers/scsi/scsi_syms.c linux-2.4.24/drivers/scsi/scsi_syms.c --- pure/linux-2.4.24/drivers/scsi/scsi_syms.c 2002-08-02 20:39:44.000000000 -0400 +++ linux-2.4.24/drivers/scsi/scsi_syms.c 2004-02-16 15:53:19.000000000 -0500 @@ -103,3 +103,9 @@ extern int scsi_delete_timer(Scsi_Cmnd *); EXPORT_SYMBOL(scsi_add_timer); EXPORT_SYMBOL(scsi_delete_timer); + +/* Support for hot plugging and unplugging devices -- safe for + * ieee1394 or USB devices, but probably not for normal SCSI... */ +EXPORT_SYMBOL(scsi_add_single_device); +EXPORT_SYMBOL(scsi_remove_single_device); + Only in linux-2.4.24/drivers/scsi/sym53c8xx_2: .depend Only in linux-2.4.24/drivers/sound/cs4281: .depend Only in linux-2.4.24/drivers/sound: .depend Only in linux-2.4.24/drivers/sound/dmasound: .depend Only in linux-2.4.24/drivers/sound/emu10k1: .depend Only in linux-2.4.24/drivers/tc: .depend Only in linux-2.4.24/drivers/telephony: .depend Only in linux-2.4.24/drivers/usb: .depend Only in linux-2.4.24/drivers/usb/gadget: .depend Only in linux-2.4.24/drivers/usb/host: .depend Only in linux-2.4.24/drivers/usb/serial: .depend Only in linux-2.4.24/drivers/usb/storage: .depend Only in linux-2.4.24/drivers/video/aty: .depend Only in linux-2.4.24/drivers/video: .depend Only in linux-2.4.24/drivers/video/intel: .depend Only in linux-2.4.24/drivers/video/matrox: .depend Only in linux-2.4.24/drivers/video/riva: .depend Only in linux-2.4.24/drivers/video/sis: .depend Only in linux-2.4.24/drivers/video/sti: .depend Only in linux-2.4.24/drivers/zorro: .depend Only in linux-2.4.24/fs/adfs: .depend Only in linux-2.4.24/fs/affs: .depend Only in linux-2.4.24/fs/autofs: .depend Only in linux-2.4.24/fs/autofs4: .depend Only in linux-2.4.24/fs/befs: .depend Only in linux-2.4.24/fs/bfs: .depend Only in linux-2.4.24/fs/coda: .depend Only in linux-2.4.24/fs/cramfs: .depend Only in linux-2.4.24/fs: .depend Only in linux-2.4.24/fs/devfs: .depend Only in linux-2.4.24/fs/devpts: .depend Only in linux-2.4.24/fs/efs: .depend Only in linux-2.4.24/fs/ext2: .depend Only in linux-2.4.24/fs/ext3: .depend Only in linux-2.4.24/fs/fat: .depend Only in linux-2.4.24/fs/freevxfs: .depend Only in linux-2.4.24/fs/hfs: .depend Only in linux-2.4.24/fs/hfsplus: .depend Only in linux-2.4.24/fs/hpfs: .depend Only in linux-2.4.24/fs/intermezzo: .depend Only in linux-2.4.24/fs/isofs: .depend Only in linux-2.4.24/fs/jbd: .depend Only in linux-2.4.24/fs/jffs: .depend Only in linux-2.4.24/fs/jffs2: .depend Only in linux-2.4.24/fs/jfs: .depend Only in linux-2.4.24/fs/lockd: .depend Only in linux-2.4.24/fs/minix: .depend Only in linux-2.4.24/fs/msdos: .depend Only in linux-2.4.24/fs/ncpfs: .depend Only in linux-2.4.24/fs/nfs: .depend Only in linux-2.4.24/fs/nfsd: .depend Only in linux-2.4.24/fs/nls: .depend Only in linux-2.4.24/fs/ntfs: .depend Only in linux-2.4.24/fs/openpromfs: .depend Only in linux-2.4.24/fs/partitions: .depend Only in linux-2.4.24/fs/proc: .depend Only in linux-2.4.24/fs/qnx4: .depend Only in linux-2.4.24/fs/ramfs: .depend Only in linux-2.4.24/fs/reiserfs: .depend Only in linux-2.4.24/fs/romfs: .depend Only in linux-2.4.24/fs/smbfs: .depend Only in linux-2.4.24/fs/sysv: .depend Only in linux-2.4.24/fs/udf: .depend Only in linux-2.4.24/fs/ufs: .depend Only in linux-2.4.24/fs/umsdos: .depend Only in linux-2.4.24/fs/vfat: .depend Only in linux-2.4.24: .hdepend Only in linux-2.4.24/include: asm Only in linux-2.4.24/include: config Only in linux-2.4.24/include/linux: autoconf.h Only in linux-2.4.24/include/linux: modules Only in linux-2.4.24/include/linux: modversions.h Only in linux-2.4.24/include/linux: version.h Only in linux-2.4.24/ipc: .depend Only in linux-2.4.24/kernel: .depend Only in linux-2.4.24/lib: crc32table.h Only in linux-2.4.24/lib: .depend Only in linux-2.4.24/lib: gen_crc32table Only in linux-2.4.24/lib/zlib_deflate: .depend Only in linux-2.4.24/lib/zlib_inflate: .depend diff -ru pure/linux-2.4.24/Makefile linux-2.4.24/Makefile --- pure/linux-2.4.24/Makefile 2004-01-05 08:53:56.000000000 -0500 +++ linux-2.4.24/Makefile 2004-02-16 20:32:31.000000000 -0500 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 24 -EXTRAVERSION = +EXTRAVERSION =-forensic0-1394hp-eloop-1 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Only in linux-2.4.24/mm: .depend Only in linux-2.4.24/net/802: .depend Only in linux-2.4.24/net/8021q: .depend Only in linux-2.4.24/net/appletalk: .depend Only in linux-2.4.24/net/atm: .depend Only in linux-2.4.24/net/ax25: .depend Only in linux-2.4.24/net/bluetooth/bnep: .depend Only in linux-2.4.24/net/bluetooth/cmtp: .depend Only in linux-2.4.24/net/bluetooth: .depend Only in linux-2.4.24/net/bluetooth/rfcomm: .depend Only in linux-2.4.24/net/bridge: .depend Only in linux-2.4.24/net/core: .depend Only in linux-2.4.24/net/decnet: .depend Only in linux-2.4.24/net: .depend Only in linux-2.4.24/net/econet: .depend Only in linux-2.4.24/net/ethernet: .depend Only in linux-2.4.24/net/ipv4: .depend Only in linux-2.4.24/net/ipv4/netfilter: .depend Only in linux-2.4.24/net/ipv6: .depend Only in linux-2.4.24/net/ipx: .depend Only in linux-2.4.24/net/irda: .depend Only in linux-2.4.24/net/irda/ircomm: .depend Only in linux-2.4.24/net/irda/irlan: .depend Only in linux-2.4.24/net/irda/irnet: .depend Only in linux-2.4.24/net/khttpd: .depend Only in linux-2.4.24/net/lapb: .depend Only in linux-2.4.24/net/netlink: .depend Only in linux-2.4.24/net/netrom: .depend Only in linux-2.4.24/net/packet: .depend Only in linux-2.4.24/net/rose: .depend Only in linux-2.4.24/net/sched: .depend Only in linux-2.4.24/net/sctp: .depend Only in linux-2.4.24/net/sunrpc: .depend Only in linux-2.4.24/net/unix: .depend Only in linux-2.4.24/net/wanrouter: .depend Only in linux-2.4.24/net/x25: .depend Only in linux-2.4.24/scripts/lxdialog: checklist.o Only in linux-2.4.24/scripts/lxdialog: inputbox.o Only in linux-2.4.24/scripts/lxdialog: lxdialog Only in linux-2.4.24/scripts/lxdialog: lxdialog.o Only in linux-2.4.24/scripts/lxdialog: menubox.o Only in linux-2.4.24/scripts/lxdialog: msgbox.o Only in linux-2.4.24/scripts/lxdialog: textbox.o Only in linux-2.4.24/scripts/lxdialog: util.o Only in linux-2.4.24/scripts/lxdialog: yesno.o Only in linux-2.4.24/scripts: mkdep Only in linux-2.4.24/scripts: split-include Only in linux-2.4.24: .version