📄 i2o_block.c
字号:
case 7: printk("Optical device");break; default: printk("Type %d", type); } if(status&(1<<10)) printk("(RAID)"); if(((flags & (1<<3)) && !(status & (1<<3))) || ((flags & (1<<4)) && !(status & (1<<4)))) { printk(KERN_INFO " Not loaded.\n"); return 1; } printk("- %dMb, %d byte sectors", (int)(size>>20), blocksize); if(status&(1<<0)) { u32 cachesize; i2ob_query_device(dev, 0x0003, 0, &cachesize, 4); cachesize>>=10; if(cachesize>4095) printk(", %dMb cache", cachesize>>10); else printk(", %dKb cache", cachesize); } printk(".\n"); printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", d->dev_name, i2ob_max_sectors[unit]); /* * If this is the first I2O block device found on this IOP, * we need to initialize all the queue data structures * before any I/O can be performed. If it fails, this * device is useless. */ if(!i2ob_queues[c->unit]) { if(i2ob_init_iop(c->unit)) return 1; } /* * This will save one level of lookup/indirection in critical * code so that we can directly get the queue ptr from the * device instead of having to go the IOP data structure. */ dev->req_queue = &i2ob_queues[c->unit]->req_queue; grok_partitions(&i2ob_gendisk, unit>>4, 1<<4, (long)(size>>9)); /* * Register for the events we're interested in and that the * device actually supports. */ i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, (I2OB_EVENT_MASK & d->lct_data.event_capabilities)); return 0;}/* * Initialize IOP specific queue structures. This is called * once for each IOP that has a block device sitting behind it. */static int i2ob_init_iop(unsigned int unit){ int i; i2ob_queues[unit] = (struct i2ob_iop_queue*) kmalloc(sizeof(struct i2ob_iop_queue), GFP_ATOMIC); if(!i2ob_queues[unit]) { printk(KERN_WARNING "Could not allocate request queue for I2O block device!\n"); return -1; } for(i = 0; i< MAX_I2OB_DEPTH; i++) { i2ob_queues[unit]->request_queue[i].next = &i2ob_queues[unit]->request_queue[i+1]; i2ob_queues[unit]->request_queue[i].num = i; } /* Queue is MAX_I2OB + 1... */ i2ob_queues[unit]->request_queue[i].next = NULL; i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0]; atomic_set(&i2ob_queues[unit]->queue_depth, 0); blk_init_queue(&i2ob_queues[unit]->req_queue, i2ob_request); blk_queue_headactive(&i2ob_queues[unit]->req_queue, 0); i2ob_queues[unit]->req_queue.back_merge_fn = i2ob_back_merge; i2ob_queues[unit]->req_queue.front_merge_fn = i2ob_front_merge; i2ob_queues[unit]->req_queue.merge_requests_fn = i2ob_merge_requests; i2ob_queues[unit]->req_queue.queuedata = &i2ob_queues[unit]; return 0;}/* * Get the request queue for the given device. */ static request_queue_t* i2ob_get_queue(kdev_t dev){ int unit = MINOR(dev)&0xF0; return i2ob_dev[unit].req_queue;}/* * Probe the I2O subsytem for block class devices */static void i2ob_probe(void){ int i; int unit = 0; int warned = 0; for(i=0; i< MAX_I2O_CONTROLLERS; i++) { struct i2o_controller *c=i2o_find_controller(i); struct i2o_device *d; if(c==NULL) continue; for(d=c->devices;d!=NULL;d=d->next) { if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE) continue; if(d->lct_data.user_tid != 0xFFF) continue; 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 "\tDevice refused claim! Skipping installation\n"); continue; } if(unit<MAX_I2OB<<4) { /* * Get the device and fill in the * Tid and controller. */ struct i2ob_device *dev=&i2ob_dev[unit]; dev->i2odev = d; dev->controller = c; dev->unit = c->unit; dev->tid = d->lct_data.tid; if(i2ob_install_device(c,d,unit)) printk(KERN_WARNING "Could not install I2O block device\n"); else { 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", unit>>4); } i2o_release_device(d, &i2o_block_handler); } i2o_unlock_controller(c); }}/* * 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; } /* * Creating a RAID 5 volume takes a little while and the UTIL_CLAIM * will fail if we don't give the card enough time to do it's magic, * so we just sleep for a little while and let it do it's thing */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(3*HZ); 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; int 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"); 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); /* * Sync the device...this will force all outstanding I/Os * to attempt to complete, thus causing error messages. * We have to do this as the user could immediatelly create * a new volume that gets assigned the same minor number. * If there are still outstanding writes to the device, * that could cause data corruption on the new volume! * * The truth is that deleting a volume that you are currently * accessing will do _bad things_ to your system. This * handler will keep it from crashing, but must probably * you'll have to do a 'reboot' to get the system running * properly. Deleting disks you are using is dumb. * Umount them first and all will be good! * * It's not this driver's job to protect the system from * dumb user mistakes :) */ if(i2ob_dev[unit].refcnt) fsync_dev(MKDEV(MAJOR_NR,unit)); /* * 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--; return;}/* * 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; i2o_post_wait(dev->controller, msg, 20, 2); /* * 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); } } }static struct block_device_operations i2ob_fops ={ open: i2ob_open, release: i2ob_release, ioctl: i2ob_ioctl, check_media_change: i2ob_media_change, revalidate: i2ob_revalidate,};static struct gendisk i2ob_gendisk = { MAJOR_NR, "i2o/hd", 4, 1<<4, i2ob, i2ob_sizes, 0, NULL, NULL};/* * 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, 2000 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_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(); return 0;}#ifdef MODULEEXPORT_NO_SYMBOLS;MODULE_AUTHOR("Red Hat Software");MODULE_DESCRIPTION("I2O Block Device OSM");void cleanup_module(void){ struct gendisk **gdp; int i; /* * 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); } } /* * 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)); if(evt_running) { i = kill_proc(evt_pid, SIGTERM, 1); if(!i) { int count = 5 * 100; while(evt_running && --count) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } if(!count) printk(KERN_ERR "Giving up on i2oblock thread...\n"); } } /* * Why isnt register/unregister gendisk in the kernel ??? */ for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) if (*gdp == &i2ob_gendisk) break;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -