📄 i2o_block.c
字号:
* The device list connected to the I2O Controller is doubly linked * Here we traverse the end of the list , and start claiming devices * from that end. This assures that within an I2O controller atleast * the newly created volumes get claimed after the older ones, thus * mapping to same major/minor (and hence device file name) after * every reboot. * The exception being: * 1. If there was a TID reuse. * 2. There was more than one I2O controller. */ if(!bios) { for (d=c->devices;d!=NULL;d=d->next) if(d->next == NULL) b = d; } else b = c->devices; while(b != NULL) { d=b; if(bios) b = b->next; else b = b->prev; if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE) continue; if(d->lct_data.user_tid != 0xFFF) continue; if(bios) { if(d->lct_data.bios_info != 0x80) continue; printk(KERN_INFO "Claiming as Boot device: Controller %d, TID %d\n", c->unit, d->lct_data.tid); } else { if(d->lct_data.bios_info == 0x80) continue; /*Already claimed on pass 1 */ } if(i2o_claim_device(d, &i2o_block_handler)) { printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit, d->lct_data.tid); printk(KERN_WARNING "\t%sevice refused claim! Skipping installation\n", bios?"Boot d":"D"); continue; } if(scan_unit<MAX_I2OB<<4) { /* * Get the device and fill in the * Tid and controller. */ dev=&i2ob_dev[scan_unit]; dev->i2odev = d; dev->controller = c; dev->unit = c->unit; dev->tid = d->lct_data.tid; if(i2ob_install_device(c,d,scan_unit)) printk(KERN_WARNING "Could not install I2O block device\n"); else { scan_unit+=16; i2ob_dev_count++; /* We want to know when device goes away */ i2o_device_notify_on(d, &i2o_block_handler); } } else { if(!warned++) printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit>>4); } i2o_release_device(d, &i2o_block_handler); } i2o_unlock_controller(c); }}static void i2ob_probe(void){ /* * Some overhead/redundancy involved here, while trying to * claim the first boot volume encountered as /dev/i2o/hda * everytime. All the i2o_controllers are searched and the * first i2o block device marked as bootable is claimed * If an I2O block device was booted off , the bios sets * its bios_info field to 0x80, this what we search for. * Assuming that the bootable volume is /dev/i2o/hda * everytime will prevent any kernel panic while mounting * root partition */ printk(KERN_INFO "i2o_block: Checking for Boot device...\n"); i2ob_scan(1); /* * Now the remainder. */ printk(KERN_INFO "i2o_block: Checking for I2O Block devices...\n"); i2ob_scan(0);}/* * New device notification handler. Called whenever a new * I2O block storage device is added to the system. * * Should we spin lock around this to keep multiple devs from * getting updated at the same time? * */void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d){ struct i2ob_device *dev; int unit = 0; printk(KERN_INFO "i2o_block: New device detected\n"); printk(KERN_INFO " Controller %d Tid %d\n",c->unit, d->lct_data.tid); /* Check for available space */ if(i2ob_dev_count>=MAX_I2OB<<4) { printk(KERN_ERR "i2o_block: No more devices allowed!\n"); return; } for(unit = 0; unit < (MAX_I2OB<<4); unit += 16) { if(!i2ob_dev[unit].i2odev) break; } if(i2o_claim_device(d, &i2o_block_handler)) { printk(KERN_INFO "i2o_block: Unable to claim device. Installation aborted\n"); return; } dev = &i2ob_dev[unit]; dev->i2odev = d; dev->controller = c; dev->tid = d->lct_data.tid; if(i2ob_install_device(c,d,unit)) printk(KERN_ERR "i2o_block: Could not install new device\n"); else { i2ob_dev_count++; i2o_device_notify_on(d, &i2o_block_handler); } i2o_release_device(d, &i2o_block_handler); return;}/* * Deleted device notification handler. Called when a device we * are talking to has been deleted by the user or some other * mysterious fource outside the kernel. */void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d){ int unit = 0; int i = 0; unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); /* * Need to do this...we somtimes get two events from the IRTOS * in a row and that causes lots of problems. */ i2o_device_notify_off(d, &i2o_block_handler); printk(KERN_INFO "I2O Block Device Deleted\n"); for(unit = 0; unit < MAX_I2OB<<4; unit += 16) { if(i2ob_dev[unit].i2odev == d) { printk(KERN_INFO " /dev/%s: Controller %d Tid %d\n", d->dev_name, c->unit, d->lct_data.tid); break; } } if(unit >= MAX_I2OB<<4) { printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n"); spin_unlock_irqrestore(&io_request_lock, flags); return; } /* * This will force errors when i2ob_get_queue() is called * by the kenrel. */ i2ob_dev[unit].req_queue = NULL; for(i = unit; i <= unit+15; i++) { i2ob_dev[i].i2odev = NULL; i2ob_sizes[i] = 0; i2ob_hardsizes[i] = 0; i2ob_max_sectors[i] = 0; i2ob[i].nr_sects = 0; i2ob_gendisk.part[i].nr_sects = 0; } spin_unlock_irqrestore(&io_request_lock, flags); /* * Decrease usage count for module */ while(i2ob_dev[unit].refcnt--) MOD_DEC_USE_COUNT; i2ob_dev[unit].refcnt = 0; i2ob_dev[i].tid = 0; /* * Do we need this? * The media didn't really change...the device is just gone */ i2ob_media_change_flag[unit] = 1; i2ob_dev_count--; }/* * Have we seen a media change ? */static int i2ob_media_change(kdev_t dev){ int i=MINOR(dev); i>>=4; if(i2ob_media_change_flag[i]) { i2ob_media_change_flag[i]=0; return 1; } return 0;}static int i2ob_revalidate(kdev_t dev){ return do_i2ob_revalidate(dev, 0);}/* * Reboot notifier. This is called by i2o_core when the system * shuts down. */static void i2ob_reboot_event(void){ int i; for(i=0;i<MAX_I2OB;i++) { struct i2ob_device *dev=&i2ob_dev[(i<<4)]; if(dev->refcnt!=0) { /* * Flush the onboard cache */ u32 msg[5]; int *query_done = &dev->done_flag; msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid; msg[2] = i2ob_context|0x40000000; msg[3] = (u32)query_done; msg[4] = 60<<16; DEBUG("Flushing..."); i2o_post_wait(dev->controller, msg, 20, 60); DEBUG("Unlocking..."); /* * Unlock the media */ msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid; msg[2] = i2ob_context|0x40000000; msg[3] = (u32)query_done; msg[4] = -1; i2o_post_wait(dev->controller, msg, 20, 2); DEBUG("Unlocked.\n"); } } }static struct block_device_operations i2ob_fops ={ owner: THIS_MODULE, open: i2ob_open, release: i2ob_release, ioctl: i2ob_ioctl, check_media_change: i2ob_media_change, revalidate: i2ob_revalidate,};static struct gendisk i2ob_gendisk = { major: MAJOR_NR, major_name: "i2o/hd", minor_shift: 4, max_p: 1<<4, part: i2ob, sizes: i2ob_sizes, nr_real: MAX_I2OB, fops: &i2ob_fops,};/* * And here should be modules and kernel interface * (Just smiley confuses emacs :-) */#ifdef MODULE#define i2o_block_init init_module#endifint i2o_block_init(void){ int i; printk(KERN_INFO "I2O Block Storage OSM v0.9\n"); printk(KERN_INFO " (c) Copyright 1999-2001 Red Hat Software.\n"); /* * Register the block device interfaces */ if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) { printk(KERN_ERR "Unable to get major number %d for i2o_block\n", MAJOR_NR); return -EIO; }#ifdef MODULE printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);#endif /* * Now fill in the boiler plate */ blksize_size[MAJOR_NR] = i2ob_blksizes; hardsect_size[MAJOR_NR] = i2ob_hardsizes; blk_size[MAJOR_NR] = i2ob_sizes; max_sectors[MAJOR_NR] = i2ob_max_sectors; blk_dev[MAJOR_NR].queue = i2ob_get_queue; blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request); blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0); for (i = 0; i < MAX_I2OB << 4; i++) { i2ob_dev[i].refcnt = 0; i2ob_dev[i].flags = 0; i2ob_dev[i].controller = NULL; i2ob_dev[i].i2odev = NULL; i2ob_dev[i].tid = 0; i2ob_dev[i].head = NULL; i2ob_dev[i].tail = NULL; i2ob_dev[i].depth = MAX_I2OB_DEPTH; i2ob_blksizes[i] = 1024; i2ob_max_sectors[i] = 2; } /* * Set up the queue */ for(i = 0; i < MAX_I2O_CONTROLLERS; i++) { i2ob_queues[i] = NULL; } /* * Timers */ init_timer(&i2ob_timer); i2ob_timer.function = i2ob_timer_handler; i2ob_timer.data = 0; /* * Register the OSM handler as we will need this to probe for * drives, geometry and other goodies. */ if(i2o_install_handler(&i2o_block_handler)<0) { unregister_blkdev(MAJOR_NR, "i2o_block"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); printk(KERN_ERR "i2o_block: unable to register OSM.\n"); return -EINVAL; } i2ob_context = i2o_block_handler.context; /* * Initialize event handling thread */ init_MUTEX_LOCKED(&i2ob_evt_sem); evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND); if(evt_pid < 0) { printk(KERN_ERR "i2o_block: Could not initialize event thread. Aborting\n"); i2o_remove_handler(&i2o_block_handler); return 0; } /* * Finally see what is actually plugged in to our controllers */ for (i = 0; i < MAX_I2OB; i++) register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4, &i2ob_fops, 0); i2ob_probe(); /* * Adding i2ob_gendisk into the gendisk list. */ add_gendisk(&i2ob_gendisk); return 0;}#ifdef MODULEEXPORT_NO_SYMBOLS;MODULE_AUTHOR("Red Hat Software");MODULE_DESCRIPTION("I2O Block Device OSM");MODULE_LICENSE("GPL");void cleanup_module(void){ int i; if(evt_running) { printk(KERN_INFO "Killing I2O block threads..."); i = kill_proc(evt_pid, SIGTERM, 1); if(!i) { printk("waiting..."); } /* Be sure it died */ wait_for_completion(&i2ob_thread_dead); printk("done.\n"); } /* * Unregister for updates from any devices..otherwise we still * get them and the core jumps to random memory :O */ if(i2ob_dev_count) { struct i2o_device *d; for(i = 0; i < MAX_I2OB; i++) if((d=i2ob_dev[i<<4].i2odev)) { i2o_device_notify_off(d, &i2o_block_handler); i2o_event_register(d->controller, d->lct_data.tid, i2ob_context, i<<4, 0); } } /* * We may get further callbacks for ourself. The i2o_core * code handles this case reasonably sanely. The problem here * is we shouldn't get them .. but a couple of cards feel * obliged to tell us stuff we dont care about. * * This isnt ideal at all but will do for now. */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ); /* * Flush the OSM */ i2o_remove_handler(&i2o_block_handler); /* * Return the block device */ if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0) printk("i2o_block: cleanup_module failed\n"); /* * free request queue */ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); del_gendisk(&i2ob_gendisk);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -