static int nrf905_release(struct inode *inode, struct file *filp) { char devno[20]; struct nrf905_dev_data *dev = filp->private_data; int fp_open; if (mutex_lock_interruptible(&dev->cdev_mutex)) return -EINTR; fp_open = atomic_dec_return(&dev->fp_open); dev_info(dev->char_dev, "release: proc: %s, PID: %d, devno: %s, fp_open: %d\n", current->comm, current->pid, format_dev_t(devno, dev->cdev.dev), fp_open); if (!fp_open) { /* Wait transmission to finish. */ if (dev->chip.mode == NRF905_TX) usleep_range(20000UL, 22000UL); set_nrf905_op_mode(dev, NRF905_POWER_DOWN); dev->active_sender = NULL; dev->active_listener = NULL; } mutex_unlock(&dev->cdev_mutex); return 0; }
static int nrf905_open(struct inode *inode, struct file *filp) { int retval = 0; struct nrf905_dev_data *dev = container_of(inode->i_cdev, struct nrf905_dev_data, cdev); char devno[20]; int fp_open; if (mutex_lock_interruptible(&dev->cdev_mutex)) return -EINTR; filp->private_data = dev; nonseekable_open(inode, filp); fp_open = atomic_inc_return(&dev->fp_open); dev_info(dev->char_dev, "open: proc: %s, PID: %d, devno: %s, fp_open: %d\n", current->comm, current->pid, format_dev_t(devno, dev->cdev.dev), fp_open); mutex_unlock(&dev->cdev_mutex); return retval; }
/**ltl * 功能: 将目标设备加入到列表中 * 参数: t ->映射表 * ti ->映射目标 * path ->映射目标<major:minor> * start-> 映射目标相对低层设备的起始偏移量(类似磁盘分区的起始地址) * len -> 此目标设备在dm设备的长度 * mode -> rw * result-> 底层设备对象 * 返回值: * 说明: */ static int __table_get_device(struct dm_table *t, struct dm_target *ti, const char *path, sector_t start, sector_t len, int mode, struct dm_dev **result) { int r; dev_t dev; struct dm_dev *dd; unsigned int major, minor; BUG_ON(!t); /* 获取主设备号和次设备号 */ if (sscanf(path, "%u:%u", &major, &minor) == 2) { /* Extract the major/minor numbers */ dev = MKDEV(major, minor); if (MAJOR(dev) != major || MINOR(dev) != minor) return -EOVERFLOW; } else { /* convert the path to a device */ if ((r = lookup_device(path, &dev))) /* 根据设备路径/dev/sdb获取<major:minor> */ return r; } /* 在列表中查找映射目标 */ dd = find_device(&t->devices, dev); if (!dd) { dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) return -ENOMEM; dd->mode = mode; dd->bdev = NULL; /* 打开设备 */ if ((r = open_dev(dd, dev, t->md))) { kfree(dd); return r; } format_dev_t(dd->name, dev); /* 主设备号次设备号 */ atomic_set(&dd->count, 0); /* 将目标设备插入到映射表中 */ list_add(&dd->list, &t->devices); } else if (dd->mode != (mode | dd->mode)) { r = upgrade_mode(dd, mode, t->md); if (r) return r; } atomic_inc(&dd->count); /* 检查区域是否超过设备 */ if (!check_device_area(dd, start, len)) { DMWARN("device %s too small for target", path); dm_put_device(ti, dd); return -EINVAL; } *result = dd; return 0; }
int toi_bio_mark_have_image(void) { int result = 0; char buf[32]; struct fs_info *fs_info; toi_message(TOI_IO, TOI_VERBOSE, 0, "Recording that an image exists."); memcpy(toi_sig_data->sig, tuxonice_signature, sizeof(tuxonice_signature)); toi_sig_data->have_image = 1; toi_sig_data->resumed_before = 0; toi_sig_data->header_dev_t = get_header_dev_t(); toi_sig_data->have_uuid = 0; #if 1 // JJ: check this uuid is mismatch, such that it will failed on toi_bio_read_header_init() !!! fs_info = fs_info_from_block_dev(get_header_bdev()); if (fs_info && !IS_ERR(fs_info)) { memcpy(toi_sig_data->header_uuid, &fs_info->uuid, 16); free_fs_info(fs_info); } else result = (int) PTR_ERR(fs_info); #endif if (!result) { toi_message(TOI_IO, TOI_VERBOSE, 0, "Got uuid for dev_t %s.", format_dev_t(buf, get_header_dev_t())); toi_sig_data->have_uuid = 1; } else toi_message(TOI_IO, TOI_VERBOSE, 0, "Could not get uuid for " "dev_t %s.", format_dev_t(buf, get_header_dev_t())); toi_sig_data->first_header_block = get_headerblock(); have_image = 1; toi_message(TOI_IO, TOI_VERBOSE, 0, "header dev_t is %x. First block " "is %d.", toi_sig_data->header_dev_t, toi_sig_data->first_header_block); memcpy(toi_sig_data->sig2, tuxonice_signature, sizeof(tuxonice_signature)); toi_sig_data->header_version = TOI_HEADER_VERSION; return toi_bio_ops.bdev_page_io(WRITE, resume_block_device, resume_firstblock, virt_to_page(toi_cur_sig_page)); }
static int __init helloworld_init(void) { int result; PDEBUG("init\n"); PDEBUG("memory= '%s'\n", memory); // TODO check voor errors, concurrency /* allocate a memory area */ memory = kcalloc(memory_size, 1, GFP_KERNEL); if (!memory) { PDEBUG("error allocating memory\n"); return -1; } /* insert initial data into memory */ memcpy(memory, initial_data, sizeof(char) * strlen(initial_data)); /* Get a range of major, minor numbers. */ result = alloc_chrdev_region(&hello_devt, 0, 1, "helloworld"); if (result < 0) { PDEBUG("allocate device\n"); return result; } char *test = kmalloc(sizeof(char)*1000, GFP_KERNEL); PDEBUG("registered device %s\n", format_dev_t(test, hello_devt)); kfree(test); /* Register character device, set file operations */ hello_cdev = cdev_alloc(); if (!hello_cdev) { PDEBUG("can't alloc cdev.\n"); goto fail; } hello_cdev->ops = &hello_fops; hello_cdev->owner = THIS_MODULE; result = cdev_add(hello_cdev, hello_devt, 1); if (result < 0) { PDEBUG("adding device to kernel failed.\n"); goto fail; } /* Create proc file */ hello_proc = proc_create("driver/helloworldmem", 0, NULL, &hello_proc_fops); if (!hello_proc) { PDEBUG("adding proc dirent failed"); goto fail; } return 0; fail: PDEBUG("fail during initialization!\n"); /* helloworld_exit(); */ return result; }
/** * toi_open_bdev: Open a bdev at resume time. * * index: The swap index. May be MAX_SWAPFILES for the resume_dev_t * (the user can have resume= pointing at a swap partition/file that isn't * swapon'd when they hibernate. MAX_SWAPFILES+1 for the first page of the * header. It will be from a swap partition that was enabled when we hibernated, * but we don't know it's real index until we read that first page. * dev_t: The device major/minor. * display_errs: Whether to try to do this quietly. * * We stored a dev_t in the image header. Open the matching device without * requiring /dev/<whatever> in most cases and record the details needed * to close it later and avoid duplicating work. */ struct block_device *toi_open_bdev(char *uuid, dev_t default_device, int display_errs) { struct block_device *bdev; dev_t device = default_device; char buf[32]; int retried = 0; retry: if (uuid) { struct fs_info seek; strncpy((char *)&seek.uuid, uuid, 16); seek.dev_t = 0; seek.last_mount_size = 0; device = blk_lookup_fs_info(&seek); if (!device) { device = default_device; printk(KERN_DEBUG "Unable to resolve uuid. Falling back" " to dev_t.\n"); } else printk(KERN_DEBUG "Resolved uuid to device %s.\n", format_dev_t(buf, device)); } if (!device) { printk(KERN_ERR "TuxOnIce attempting to open a " "blank dev_t!\n"); dump_stack(); return NULL; } bdev = toi_open_by_devnum(device); if (IS_ERR(bdev) || !bdev) { if (!retried) { retried = 1; wait_for_device_probe(); goto retry; } if (display_errs) toi_early_boot_message(1, TOI_CONTINUE_REQ, "Failed to get access to block device " "\"%x\" (error %d).\n Maybe you need " "to run mknod and/or lvmsetup in an " "initrd/ramfs?", device, bdev); return ERR_PTR(-EINVAL); } toi_message(TOI_BIO, TOI_VERBOSE, 0, "TuxOnIce got bdev %p for dev_t %x.", bdev, device); return bdev; }
int acqiris_open(struct inode* inode, struct file* filp) { struct acqiris_driver *drv; struct acqiris_device *aq_dev; char buffer[20]; int minor; int dev_num; minor = MINOR(inode->i_rdev); if (dbgl&DINIT) printk(ACQRS_INFO "acqiris_open(%s)\n", format_dev_t(buffer, inode->i_rdev)); /* Opening the main device is always possible */ if (minor == 0) { drv = container_of(inode->i_cdev, struct acqiris_driver, cdev); filp->private_data = drv; return 0; }
static int disk_status(struct dirty_log *log, status_type_t status, char *result, unsigned int maxlen) { int sz = 0; char buffer[16]; struct log_c *lc = log->context; switch(status) { case STATUSTYPE_INFO: break; case STATUSTYPE_TABLE: format_dev_t(buffer, lc->log_dev->bdev->bd_dev); DMEMIT("%s %u %s %u ", log->type->name, lc->sync == DEFAULTSYNC ? 2 : 3, buffer, lc->region_size); DMEMIT_SYNC; } return sz; }
/* * Allocate and initialise a blank device with a given minor. */ static struct mapped_device *alloc_dev(int minor) { int r; struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); void *old_md; if (!md) { DMWARN("unable to allocate device, out of memory."); return NULL; } if (!try_module_get(THIS_MODULE)) goto bad0; /* get a minor number for the dev */ if (minor == DM_ANY_MINOR) r = next_free_minor(md, &minor); else r = specific_minor(md, minor); if (r < 0) goto bad1; memset(md, 0, sizeof(*md)); init_rwsem(&md->io_lock); init_MUTEX(&md->suspend_lock); spin_lock_init(&md->pushback_lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); atomic_set(&md->event_nr, 0); md->queue = blk_alloc_queue(GFP_KERNEL); if (!md->queue) goto bad1_free_minor; md->queue->queuedata = md; md->queue->backing_dev_info.congested_fn = dm_any_congested; md->queue->backing_dev_info.congested_data = md; blk_queue_make_request(md->queue, dm_request); blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); md->queue->unplug_fn = dm_unplug_all; md->queue->issue_flush_fn = dm_flush_all; md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); if (!md->io_pool) goto bad2; md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache); if (!md->tio_pool) goto bad3; md->bs = bioset_create(16, 16); if (!md->bs) goto bad_no_bioset; md->disk = alloc_disk(1); if (!md->disk) goto bad4; atomic_set(&md->pending, 0); init_waitqueue_head(&md->wait); init_waitqueue_head(&md->eventq); md->disk->major = _major; md->disk->first_minor = minor; md->disk->fops = &dm_blk_dops; md->disk->queue = md->queue; md->disk->private_data = md; sprintf(md->disk->disk_name, "dm-%d", minor); add_disk(md->disk); format_dev_t(md->name, MKDEV(_major, minor)); /* Populate the mapping, nobody knows we exist yet */ spin_lock(&_minor_lock); old_md = idr_replace(&_minor_idr, md, minor); spin_unlock(&_minor_lock); BUG_ON(old_md != MINOR_ALLOCED); return md; bad4: bioset_free(md->bs); bad_no_bioset: mempool_destroy(md->tio_pool); bad3: mempool_destroy(md->io_pool); bad2: blk_cleanup_queue(md->queue); bad1_free_minor: free_minor(minor); bad1: module_put(THIS_MODULE); bad0: kfree(md); return NULL; }
static int __init nrf905_init(void) { int retval = -ENODEV; dev_t devno = 0; char cdevno[20]; struct nrf905_dev_data *dev; if (nrf905_major) { devno = MKDEV(nrf905_major, nrf905_minor); retval = register_chrdev_region(devno, NRF905_NR_DEVS, "nrf905"); } else { retval = alloc_chrdev_region(&devno, nrf905_minor, NRF905_NR_DEVS, "nrf905"); nrf905_major = MAJOR(devno); } if (retval < 0) { pr_err("nrf905: can't get major %d\n", nrf905_major); goto err_major; } pr_info("nrf905: %s\n", format_dev_t(cdevno, devno)); dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (IS_ERR_OR_NULL(dev)) { pr_err("nrf905: can't allocate memory for nrf905_dev\n"); retval = -ENOMEM; goto err_nrf905_dev; } nrf905_dev = dev; init_waitqueue_head(&dev->recv_waitq); mutex_init(&dev->cdev_mutex); mutex_init(&dev->dev_mutex); spin_lock_init(&dev->chip.irq_lock); atomic_set(&nrf905_dev->fp_open, 0); dev->nrf905_class = class_create(THIS_MODULE, "nrf905"); if (IS_ERR(dev->nrf905_class)) { pr_err("nrf905: class create fail\n"); retval = PTR_ERR(dev->nrf905_class); goto err_class; } dev->nrf905_class->dev_groups = chip_config_groups; dev->char_dev = device_create(dev->nrf905_class, NULL, MKDEV(nrf905_major, nrf905_minor), NULL, "nrf905"); if (IS_ERR(dev->char_dev)) { pr_err("nrf905: char device create failed\n"); retval = PTR_ERR(dev->char_dev); goto err_char_dev; } dev_set_drvdata(dev->char_dev, dev); nrf905_dev->work_q = alloc_workqueue("nrf905", 0, 0); if (IS_ERR_OR_NULL(nrf905_dev->work_q)) { retval = -ENOMEM; goto err_workq; } INIT_WORK(&nrf905_dev->work, nrf905_data_ready); pr_info("nrf905: register spi driver\n"); retval = spi_register_driver(&nrf905_driver); if (retval < 0) { pr_err("nrf905: spi driver register fail\n"); goto err_spi_register; } cdev_init(&dev->cdev, &nrf905_fops); dev->cdev.owner = THIS_MODULE; retval = cdev_add(&dev->cdev, devno, 1); if (retval < 0) { pr_err("nrf905: cdev reg. failed, major %d, minor %d: %d\n", nrf905_major, nrf905_minor, retval); goto err_cdev; } pr_info("nrf905 init ready: %d\n", retval); return retval; err_cdev: spi_unregister_driver(&nrf905_driver); err_spi_register: remove_proc_entry("nrf905", NULL); device_destroy(dev->nrf905_class, MKDEV(nrf905_major, nrf905_minor)); err_workq: destroy_workqueue(nrf905_dev->work_q); err_char_dev: class_destroy(dev->nrf905_class); err_class: kfree(dev); err_nrf905_dev: unregister_chrdev_region(devno, NRF905_NR_DEVS); err_major: return retval; }
static ssize_t nrf905_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { ssize_t retval = -EFBIG; char devno[20]; struct nrf905_dev_data *dev = filp->private_data; if (mutex_lock_interruptible(&dev->dev_mutex)) return -EINTR; if (dev->chip.mode != NRF905_POWER_DOWN && dev->chip.mode != NRF905_RX) { dev_err(dev->char_dev, "Chip busy\n"); retval = -EBUSY; goto out; } if (dev->active_sender != NULL && dev->active_sender != filp) { dev_err(dev->char_dev, "Only one TX operation at the time\n"); retval = -EBUSY; goto out; } dev->active_sender = filp; dev_info(dev->char_dev, "write: proc: %s, PID: %d, devno: %s, count: %lu, pos: %lld\n", current->comm, current->pid, format_dev_t(devno, dev->cdev.dev), (unsigned long) count, *f_pos); if (*f_pos >= NRF905_PAYLOAD_LEN || count > NRF905_PAYLOAD_LEN || *f_pos + count > NRF905_PAYLOAD_LEN) { dev_err(dev->char_dev, "Out of buffer\n"); goto err; } /* Clear buffer only when write started at the beginning. */ if (*f_pos == 0) memset(dev->dev_send_buf, 0, NRF905_PAYLOAD_LEN); if (copy_from_user(dev->dev_send_buf + *f_pos, buf, count)) { retval = -EFAULT; goto err; } *f_pos += count; retval = count; if (*f_pos == NRF905_PAYLOAD_LEN) { retval = set_nrf905_op_mode(dev, NRF905_TX); dev->active_sender = NULL; /* Start a new msg*/ *f_pos = 0; } goto out; err: dev->active_sender = NULL; out: mutex_unlock(&dev->dev_mutex); return retval; }