⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blkmtd.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
    current->state = TASK_RUNNING;    remove_wait_queue(&mtbd_sync_wq, &wait);    DEBUG(3, "blkmtd: sync: waking up after write task\n");    goto stuff_inq;  }  spin_unlock(&mbd_writeq_lock);  DEBUG(2, "blkmtd: sync: finished\n");}#ifdef BLKMTD_PROC_DEBUG/* procfs stuff */static int blkmtd_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data){  int clean = 0, dirty = 0, locked = 0;  struct list_head *temp;  int i, len, pages = 0, cnt;  MOD_INC_USE_COUNT;  spin_lock(&mbd_writeq_lock);  cnt = write_queue_cnt;  i = write_queue_tail;  while(cnt) {    if(!write_queue[i].iserase)      pages += write_queue[i].pagecnt;    i++;    i %= write_queue_sz;    cnt--;  }  /* Count the size of the page lists */  list_for_each(temp, &mtd_rawdevice->as.clean_pages) {    clean++;  }  list_for_each(temp, &mtd_rawdevice->as.dirty_pages) {    dirty++;  }  list_for_each(temp, &mtd_rawdevice->as.locked_pages) {    locked++;  }  len = sprintf(page, "Write queue head: %d\nWrite queue tail: %d\n"		"Write queue count: %d\nPages in queue: %d (%dK)\n"		"Clean Pages: %d\nDirty Pages: %d\nLocked Pages: %d\n"		"nrpages: %ld\n",		write_queue_head, write_queue_tail, write_queue_cnt,		pages, pages << (PAGE_SHIFT-10), clean, dirty, locked,		mtd_rawdevice->as.nrpages);  if(len <= count)    *eof = 1;  spin_unlock(&mbd_writeq_lock);  MOD_DEC_USE_COUNT;  return len;}#endif/* Cleanup and exit - sync the device and kill of the kernel thread */static void __exit cleanup_blkmtd(void){#ifdef BLKMTD_PROC_DEBUG  if(blkmtd_proc) {    remove_proc_entry("blkmtd_debug", NULL);  }#endif  if (mtd_rawdevice) {    /* sync the device */    if (!mtd_rawdevice->readonly) {      blkmtd_sync(&mtd_rawdevice->mtd_info);      write_task_finish = 1;      wake_up_interruptible(&thr_wq);      down(&thread_sem);    }    del_mtd_device(&mtd_rawdevice->mtd_info);    if(mtd_rawdevice->binding != NULL)      blkdev_put(mtd_rawdevice->binding, BDEV_RAW);    if(mtd_rawdevice->mtd_info.eraseregions)      kfree(mtd_rawdevice->mtd_info.eraseregions);    if(mtd_rawdevice->mtd_info.name)      kfree(mtd_rawdevice->mtd_info.name);    kfree(mtd_rawdevice);  }  if(write_queue)    kfree(write_queue);  if(erase_page) {    UnlockPage(erase_page);    __free_pages(erase_page, 0);  }  printk("blkmtd: unloaded for %s\n", device);}extern struct module __this_module;#ifndef MODULE/* Handle kernel boot params */static int __init param_blkmtd_device(char *str){  device = str;  return 1;}static int __init param_blkmtd_erasesz(char *str){  erasesz = simple_strtol(str, NULL, 0);  return 1;}static int __init param_blkmtd_ro(char *str){  ro = simple_strtol(str, NULL, 0);  return 1;}static int __init param_blkmtd_bs(char *str){  bs = simple_strtol(str, NULL, 0);  return 1;}static int __init param_blkmtd_count(char *str){  count = simple_strtol(str, NULL, 0);  return 1;}__setup("blkmtd_device=", param_blkmtd_device);__setup("blkmtd_erasesz=", param_blkmtd_erasesz);__setup("blkmtd_ro=", param_blkmtd_ro);__setup("blkmtd_bs=", param_blkmtd_bs);__setup("blkmtd_count=", param_blkmtd_count);#endif/* for a given size and initial erase size, calculate the number and size of each   erase region */static int __init calc_erase_regions(struct mtd_erase_region_info *info, size_t erase_size, size_t total_size){  int count = 0;  int offset = 0;  int regions = 0;   while(total_size) {     count = total_size / erase_size;     if(count) {       total_size = total_size % erase_size;       if(info) {	 info->offset = offset;	 info->erasesize = erase_size;	 info->numblocks = count;	 info++;       }       offset += (count * erase_size);       regions++;     }     while(erase_size > total_size)       erase_size >>= 1;   }   return regions;}extern kdev_t name_to_kdev_t(char *line) __init;/* Startup */static int __init init_blkmtd(void){#ifdef MODULE  struct file *file = NULL;  struct inode *inode;#endif  int maj, min;  int i, blocksize, blocksize_bits;  loff_t size = 0;  int readonly = 0;  int erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;  kdev_t rdev;  int err;  int mode;  int regions;  /* Check args */  if(device == 0) {    printk("blkmtd: error, missing `device' name\n");    return -EINVAL;  }  if(ro)    readonly = 1;  if(erasesz)    erase_size = erasesz;  if(wqs) {    if(wqs < 16)       wqs = 16;    if(wqs > 4*WRITE_QUEUE_SZ)      wqs = 4*WRITE_QUEUE_SZ;    write_queue_sz = wqs;  }  DEBUG(1, "blkmtd: device = `%s' erase size = %dK readonly = %s queue size = %d\n",	device, erase_size, readonly ? "yes" : "no", write_queue_sz);  /* Get a handle on the device */  mode = (readonly) ? O_RDONLY : O_RDWR;#ifdef MODULE  file = filp_open(device, mode, 0);  if(IS_ERR(file)) {    printk("blkmtd: error, cant open device %s\n", device);    DEBUG(2, "blkmtd: filp_open returned %ld\n", PTR_ERR(file));    return 1;  }    /* determine is this is a block device and if so get its major and minor     numbers */  inode = file->f_dentry->d_inode;  if(!S_ISBLK(inode->i_mode)) {    printk("blkmtd: %s not a block device\n", device);    filp_close(file, NULL);    return 1;  }  rdev = inode->i_rdev;  filp_close(file, NULL);#else  rdev = name_to_kdev_t(device);#endif  maj = MAJOR(rdev);  min = MINOR(rdev);  DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", maj, min);  if(!rdev) {    printk("blkmtd: bad block device: `%s'\n", device);    return 1;  }  if(maj == MTD_BLOCK_MAJOR) {    printk("blkmtd: attempting to use an MTD device as a block device\n");    return 1;  }  DEBUG(1, "blkmtd: devname = %s\n", bdevname(rdev));  blocksize = BLOCK_SIZE;  if(bs) {    blocksize = bs;  } else {    if (blksize_size[maj] && blksize_size[maj][min]) {      DEBUG(2, "blkmtd: blksize_size = %d\n", blksize_size[maj][min]);      blocksize = blksize_size[maj][min];    }  }  i = blocksize;  blocksize_bits = 0;  while(i != 1) {    blocksize_bits++;    i >>= 1;  }  if(count) {    size = count;  } else {    if (blk_size[maj]) {      size = ((loff_t) blk_size[maj][min] << BLOCK_SIZE_BITS) >> blocksize_bits;    }  }  size *= blocksize;  DEBUG(1, "blkmtd: size = %ld\n", (long int)size);  if(size == 0) {    printk("blkmtd: cant determine size\n");    return 1;  }  mtd_rawdevice = (mtd_raw_dev_data_t *)kmalloc(sizeof(mtd_raw_dev_data_t), GFP_KERNEL);  if(mtd_rawdevice == NULL) {    err = -ENOMEM;    goto init_err;  }  memset(mtd_rawdevice, 0, sizeof(mtd_raw_dev_data_t));  /* get the block device */  mtd_rawdevice->binding = bdget(kdev_t_to_nr(MKDEV(maj, min)));  err = blkdev_get(mtd_rawdevice->binding, mode, 0, BDEV_RAW);  if (err) {    goto init_err;  }  mtd_rawdevice->totalsize = size;  mtd_rawdevice->sector_size = blocksize;  mtd_rawdevice->sector_bits = blocksize_bits;  mtd_rawdevice->readonly = readonly;  /* See if device ends on page boundary */  if(size % PAGE_SIZE) {    mtd_rawdevice->partial_last_page = size >> PAGE_SHIFT;    mtd_rawdevice->last_page_sectors = (size & (PAGE_SIZE-1)) >> blocksize_bits;  }  DEBUG(2, "sector_size = %d, sector_bits = %d, partial_last_page = %d last_page_sectors = %d\n", 	mtd_rawdevice->sector_size, mtd_rawdevice->sector_bits,	mtd_rawdevice->partial_last_page, mtd_rawdevice->last_page_sectors);  /* Setup the MTD structure */  /* make the name contain the block device in */  mtd_rawdevice->mtd_info.name = kmalloc(9 + strlen(device), GFP_KERNEL);  if(mtd_rawdevice->mtd_info.name == NULL)    goto init_err;  sprintf(mtd_rawdevice->mtd_info.name, "blkmtd: %s", device);  if(readonly) {    mtd_rawdevice->mtd_info.type = MTD_ROM;    mtd_rawdevice->mtd_info.flags = MTD_CAP_ROM;    mtd_rawdevice->mtd_info.erasesize = erase_size << 10;  } else {    mtd_rawdevice->mtd_info.type = MTD_RAM;    mtd_rawdevice->mtd_info.flags = MTD_CAP_RAM;    mtd_rawdevice->mtd_info.erasesize = erase_size << 10;  }  mtd_rawdevice->mtd_info.size = size;  mtd_rawdevice->mtd_info.erase = blkmtd_erase;  mtd_rawdevice->mtd_info.read = blkmtd_read;  mtd_rawdevice->mtd_info.write = blkmtd_write;  mtd_rawdevice->mtd_info.sync = blkmtd_sync;  mtd_rawdevice->mtd_info.point = 0;  mtd_rawdevice->mtd_info.unpoint = 0;  mtd_rawdevice->mtd_info.priv = mtd_rawdevice;  regions = calc_erase_regions(NULL, erase_size << 10, size);  DEBUG(1, "blkmtd: init: found %d erase regions\n", regions);  mtd_rawdevice->mtd_info.eraseregions = kmalloc(regions * sizeof(struct mtd_erase_region_info), GFP_KERNEL);  if(mtd_rawdevice->mtd_info.eraseregions == NULL) {    err = -ENOMEM;    goto init_err;  }  mtd_rawdevice->mtd_info.numeraseregions = regions;  calc_erase_regions(mtd_rawdevice->mtd_info.eraseregions, erase_size << 10, size);  /* setup the page cache info */    mtd_rawdevice->as.nrpages = 0;  INIT_LIST_HEAD(&mtd_rawdevice->as.clean_pages);  INIT_LIST_HEAD(&mtd_rawdevice->as.dirty_pages);  INIT_LIST_HEAD(&mtd_rawdevice->as.locked_pages);  mtd_rawdevice->as.host = NULL;  spin_lock_init(&(mtd_rawdevice->as.i_shared_lock));  mtd_rawdevice->as.a_ops = &blkmtd_aops;  mtd_rawdevice->as.i_mmap = NULL;  mtd_rawdevice->as.i_mmap_shared = NULL;  mtd_rawdevice->as.gfp_mask = GFP_KERNEL;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  mtd_rawdevice->mtd_info.module = THIS_MODULE;			#endif  if (add_mtd_device(&mtd_rawdevice->mtd_info)) {    err = -EIO;    goto init_err;  }  if(!mtd_rawdevice->readonly) {    /* Allocate the write queue */    write_queue = kmalloc(write_queue_sz * sizeof(mtdblkdev_write_queue_t), GFP_KERNEL);    if(!write_queue) {      err = -ENOMEM;      goto init_err;    }    /* Set up the erase page */    erase_page = alloc_pages(GFP_KERNEL, 0);    if(erase_page == NULL) {      err = -ENOMEM;      goto init_err;    }    memset(page_address(erase_page), 0xff, PAGE_SIZE);    lock_page(erase_page);    init_waitqueue_head(&thr_wq);    init_waitqueue_head(&mtbd_sync_wq);    DEBUG(3, "blkmtd: init: kernel task @ %p\n", write_queue_task);    DEBUG(2, "blkmtd: init: starting kernel task\n");    kernel_thread(write_queue_task, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);    DEBUG(2, "blkmtd: init: started\n");    printk("blkmtd loaded: version = %s using %s erase_size = %dK %s\n",	   VERSION, device, erase_size, (readonly) ? "(read-only)" : "");  }#ifdef BLKMTD_PROC_DEBUG  /* create proc entry */  DEBUG(2, "Creating /proc/blkmtd_debug\n");  blkmtd_proc = create_proc_read_entry("blkmtd_debug", 0444,				       NULL, blkmtd_proc_read, NULL);  if(blkmtd_proc == NULL) {    printk("Cant create /proc/blkmtd_debug\n");  } else {    blkmtd_proc->owner = THIS_MODULE;  }#endif    /* Everything is ok if we got here */  return 0;   init_err:  if(mtd_rawdevice) {    if(mtd_rawdevice->mtd_info.eraseregions)      kfree(mtd_rawdevice->mtd_info.eraseregions);    if(mtd_rawdevice->mtd_info.name)      kfree(mtd_rawdevice->mtd_info.name);    if(mtd_rawdevice->binding)       blkdev_put(mtd_rawdevice->binding, BDEV_RAW);    kfree(mtd_rawdevice);  }  if(write_queue) {    kfree(write_queue);    write_queue = NULL;  }  if(erase_page)     __free_pages(erase_page, 0);  return err;}module_init(init_blkmtd);module_exit(cleanup_blkmtd);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -