int swsusp_check(void) { int error; resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); memset(&swsusp_header, 0, sizeof(swsusp_header)); if ((error = bio_read_page(0, &swsusp_header))) return error; if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); /* Reset swap signature now */ error = bio_write_page(0, &swsusp_header); } else { return -EINVAL; } if (error) blkdev_put(resume_bdev); else pr_debug("swsusp: Signature found, resuming\n"); } else { error = PTR_ERR(resume_bdev); } if (error) pr_debug("swsusp: Error %d check for resume file\n", error); return error; }
static void mmc_panic_erase(void) { int i = 0; dev_t devid; struct apanic_data *ctx = &drv_ctx; struct block_device *bdev; struct bio bio; struct bio_vec bio_vec; struct completion complete; struct page *page; devid = MKDEV(ctx->mmchd->major, ctx->mmchd->first_minor + ctx->mmchd->partno); bdev = open_by_devnum(devid, FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "apanic: open device failed with %ld\n", PTR_ERR(bdev)); goto out_err; } page = virt_to_page(ctx->bounce); memset(ctx->bounce, 0, PAGE_SIZE); while (i < ctx->mmchd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_offset = 0; bio_vec.bv_page = page; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_sector = i; if (ctx->mmchd->nr_sects - i >= 8) { bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { bio_vec.bv_len = (ctx->mmchd->nr_sects - i) * 512; bio.bi_size = (ctx->mmchd->nr_sects - i) * 512; i = ctx->mmchd->nr_sects; } bio.bi_bdev = bdev; init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(WRITE, &bio); wait_for_completion(&complete); } blkdev_put(bdev, FMODE_WRITE); out_err: return; }
static int read_suspend_image(const char * specialfile, int noresume) { union diskpage *cur; unsigned long scratch_page = 0; int error; char b[BDEVNAME_SIZE]; resume_device = name_to_dev_t(specialfile); scratch_page = get_zeroed_page(GFP_ATOMIC); cur = (void *) scratch_page; if (cur) { struct block_device *bdev; printk("Resuming from device %s\n", __bdevname(resume_device, b)); bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW); if (IS_ERR(bdev)) { error = PTR_ERR(bdev); } else { set_blocksize(bdev, PAGE_SIZE); error = __read_suspend_image(bdev, cur, noresume); blkdev_put(bdev, BDEV_RAW); } } else error = -ENOMEM; if (scratch_page) free_page(scratch_page); switch (error) { case 0: PRINTK("Reading resume file was successful\n"); break; case -EINVAL: break; case -EIO: printk( "%sI/O error\n", name_resume); break; case -ENOENT: printk( "%s%s: No such file or directory\n", name_resume, specialfile); break; case -ENOMEM: printk( "%sNot enough memory\n", name_resume); break; default: printk( "%sError %d resuming\n", name_resume, error ); } MDELAY(1000); return error; }
/* * Open a device so we can use it as a map destination. */ static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md) { static char *_claim_ptr = "I belong to device-mapper"; struct block_device *bdev; int r; BUG_ON(d->bdev); bdev = open_by_devnum(dev, d->mode); if (IS_ERR(bdev)) return PTR_ERR(bdev); r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md)); if (r) blkdev_put(bdev); else d->bdev = bdev; return r; }
int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major, unsigned minor, int readonly, int cdrom) { struct vbd *vbd; struct block_device *bdev; vbd = &blkif->vbd; vbd->handle = handle; vbd->readonly = readonly; vbd->type = 0; vbd->pdevice = MKDEV(major, minor); bdev = open_by_devnum(vbd->pdevice, vbd->readonly ? FMODE_READ : FMODE_WRITE); if (IS_ERR(bdev)) { DPRINTK("vbd_creat: device %08x could not be opened.\n", vbd->pdevice); return -ENOENT; } vbd->bdev = bdev; vbd->size = vbd_size(vbd); if (vbd->bdev->bd_disk == NULL) { DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); vbd_free(vbd); return -ENOENT; } if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) vbd->type |= VDISK_CDROM; if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) vbd->type |= VDISK_REMOVABLE; DPRINTK("Successful creation of handle=%04x (dom=%u)\n", handle, blkif->domid); return 0; }
int __init pmdisk_read(void) { int error; if (!strlen(resume_file)) return -ENOENT; resume_device = name_to_dev_t(resume_file); pr_debug("pmdisk: Resume From Partition: %s\n", resume_file); resume_bdev = open_by_devnum(resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); error = read_suspend_image(); blkdev_put(resume_bdev); } else error = PTR_ERR(resume_bdev); if (!error) pr_debug("Reading resume file was successful\n"); else pr_debug("pmdisk: Error %d resuming\n", error); return error; }
int swsusp_check(void) { int error; hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(hib_resume_bdev)) { set_blocksize(hib_resume_bdev, PAGE_SIZE); memset(swsusp_header, 0, PAGE_SIZE); error = hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL); if (error) goto put; if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) { memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); /* Reset swap signature now */ error = hib_bio_write_page(swsusp_resume_block, swsusp_header, NULL); } else { error = -EINVAL; } put: if (error) blkdev_put(hib_resume_bdev, FMODE_READ); else pr_debug("PM: Signature found, resuming\n"); } else { error = PTR_ERR(hib_resume_bdev); } if (error) pr_debug("PM: Error %d checking image file\n", error); return error; }
/* Callback called before the device reboots. If the reboot cause is a recovery, this function is going to write the strings "boot-recovery" and "recovery" into the Bootloader Control Block (BCB) so the Android Bootloader can launch the recovery image instead of the boot image. */ static int reboot_notifier_callback( struct notifier_block *nb, unsigned long val, void *v) { struct raw_hd_struct *mmc_hd = NULL; struct bootloader_message *bcb; char *flashblock = NULL; if (mmc_misc_hd == NULL) goto clean_up; else mmc_hd = mmc_misc_hd; if (v == NULL) { board_sysconfig(SYSCFG_RESETREASON_SOFT_RESET, SYSCFG_DISABLE); goto clean_up; } if (!strncmp(v, "recovery", 8)) { int i = 0; dev_t devid; struct block_device *bdev; struct bio bio; struct bio_vec bio_vec; struct completion complete; struct page *page; /* Allocate a buffer to hold a block from 'misc' */ flashblock = kmalloc(mmc_hd->nr_sects * 512, GFP_KERNEL); memset(flashblock, 0, mmc_hd->nr_sects * 512); /* If the allocation fails, return */ if (flashblock == NULL) goto clean_up; /* read the BCB from the misc partition */ /* read the entire block as we'll have to rewrite it hence we need to erase */ devid = MKDEV(mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); bdev = open_by_devnum(devid, FMODE_READ); if (IS_ERR(bdev)) { printk(KERN_ERR "misc: open device failed with %ld\n", PTR_ERR(bdev)); goto clean_up; } page = virt_to_page(bounce); while (i < mmc_hd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_bdev = bdev; bio.bi_sector = i; if (mmc_hd->nr_sects - i >= 8) { bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { bio_vec.bv_len = (mmc_hd->nr_sects - i) * 512; bio.bi_size = (mmc_hd->nr_sects - i) * 512; i = mmc_hd->nr_sects; } init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(READ, &bio); wait_for_completion(&complete); /* Copy the read buffer */ memcpy(flashblock + (i * 512), page, bio.bi_size); } blkdev_put(bdev, FMODE_READ); printk(KERN_ERR "misc: Bound to mmc block device '(%d:%d)'\n", mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); /* BCB is stored at 0-bytes */ bcb = (struct bootloader_message *)&flashblock[0]; /* set bcb.command to "boot-recovery" */ strcpy(bcb->command, "boot-recovery"); /* clean bcb.status */ memset(bcb->status, 0, sizeof(bcb->status)); /* set bcb.recovery to "recovery" */ strcpy(bcb->recovery, "recovery"); /* Write the block back to 'misc' First, erase it */ devid = MKDEV(mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); bdev = open_by_devnum(devid, FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "misc: open device failed with %ld\n", PTR_ERR(bdev)); goto clean_up; } page = virt_to_page(bounce); i = 0; while (i < mmc_hd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_bdev = bdev; bio.bi_sector = i; if (mmc_hd->nr_sects - i >= 8) { bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { bio_vec.bv_len = (mmc_hd->nr_sects - i) * 512; bio.bi_size = (mmc_hd->nr_sects - i) * 512; i = mmc_hd->nr_sects; } init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(WRITE, &bio); wait_for_completion(&complete); } blkdev_put(bdev, FMODE_WRITE); /* Then write the block back */ devid = MKDEV(mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); bdev = open_by_devnum(devid, FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "misc: open device failed with %ld\n", PTR_ERR(bdev)); goto clean_up; } page = virt_to_page(bounce); i = 0; while (i < mmc_hd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_bdev = bdev; bio.bi_sector = i; if (mmc_hd->nr_sects - i >= 8) { /* Copy the BCB block to buffer */ memcpy(bounce, flashblock + (i * 512), PAGE_SIZE); bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { /* Copy the BCB block to buffer */ memcpy(bounce, flashblock + (i * 512), (mmc_hd->nr_sects - i) * 512); bio_vec.bv_len = (mmc_hd->nr_sects - i) * 512; bio.bi_size = (mmc_hd->nr_sects - i) * 512; i = mmc_hd->nr_sects; } init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(WRITE, &bio); wait_for_completion(&complete); } blkdev_put(bdev, FMODE_WRITE); } if (!strncmp(v, "ap_only", 7)) { board_sysconfig(SYSCFG_RESETREASON_AP_ONLY_BOOT, SYSCFG_DISABLE); } clean_up: if (flashblock != NULL) kfree(flashblock); return NOTIFY_DONE; }
static void mmc_panic_notify_add(struct raw_hd_struct *hd, struct raw_mmc_panic_ops *panic_ops) { dev_t devid; struct apanic_data *ctx = &drv_ctx; struct panic_header *hdr = ctx->bounce; struct block_device *bdev; struct bio bio; struct bio_vec bio_vec; struct completion complete; struct page *page; ctx->mmchd = hd; ctx->mmc_panic_ops = panic_ops; devid = MKDEV(hd->major, hd->first_minor + hd->partno); bdev = open_by_devnum(devid, FMODE_READ); if (IS_ERR(bdev)) { printk(KERN_ERR "apanic: open device failed with %ld\n", PTR_ERR(bdev)); goto out_err; } page = virt_to_page(ctx->bounce); bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_len = PAGE_SIZE; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_size = PAGE_SIZE; bio.bi_bdev = bdev; bio.bi_sector = 0; init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(READ, &bio); wait_for_completion(&complete); blkdev_put(bdev, FMODE_READ); printk(KERN_ERR "apanic: Bound to mmc block device '%s(%d:%d)'\n", apanic_dev_name, hd->major, hd->first_minor + hd->partno); if (hdr->magic != PANIC_MAGIC) { printk(KERN_INFO "apanic: No panic data available\n"); return; } if (hdr->version != PHDR_VERSION) { printk(KERN_INFO "apanic: Version mismatch (%d != %d)\n", hdr->version, PHDR_VERSION); return; } memcpy(&ctx->curr, hdr, sizeof(struct panic_header)); printk(KERN_INFO "apanic: c(%u, %u) t(%u, %u)\n", hdr->console_offset, hdr->console_length, hdr->threads_offset, hdr->threads_length); if (hdr->console_length) { ctx->apanic_console = create_proc_entry("apanic_console", S_IFREG | S_IRUGO, NULL); if (!ctx->apanic_console) printk(KERN_ERR "%s: failed creating procfile\n", __func__); else { ctx->apanic_console->read_proc = apanic_proc_read_mmc; ctx->apanic_console->write_proc = apanic_proc_write; ctx->apanic_console->size = hdr->console_length; ctx->apanic_console->data = (void *) 1; } } if (hdr->threads_length) { ctx->apanic_threads = create_proc_entry("apanic_threads", S_IFREG | S_IRUGO, NULL); if (!ctx->apanic_threads) printk(KERN_ERR "%s: failed creating procfile\n", __func__); else { ctx->apanic_threads->read_proc = apanic_proc_read_mmc; ctx->apanic_threads->write_proc = apanic_proc_write; ctx->apanic_threads->size = hdr->threads_length; ctx->apanic_threads->data = (void *) 2; } } return; out_err: ctx->mmchd = NULL; return; }
static int apanic_proc_read_mmc(char *buffer, char **start, off_t offset, int count, int *peof, void *dat) { int i, index = 0; int ret; int start_sect; int end_sect; size_t file_length; off_t file_offset; dev_t devid; struct apanic_data *ctx = &drv_ctx; struct block_device *bdev; struct bio bio; struct bio_vec bio_vec; struct completion complete; struct page *page; if (!count) return 0; mutex_lock(&drv_mutex); switch ((int) dat) { case 1: /* apanic_console */ file_length = ctx->curr.console_length; file_offset = ctx->curr.console_offset; break; case 2: /* apanic_threads */ file_length = ctx->curr.threads_length; file_offset = ctx->curr.threads_offset; break; default: pr_err("Bad dat (%d)\n", (int) dat); mutex_unlock(&drv_mutex); return -EINVAL; } if ((offset + count) > file_length) { mutex_unlock(&drv_mutex); return 0; } devid = MKDEV(ctx->mmchd->major, ctx->mmchd->first_minor + ctx->mmchd->partno); bdev = open_by_devnum(devid, FMODE_READ); if (IS_ERR(bdev)) { printk(KERN_ERR "apanic: open device failed with %ld\n", PTR_ERR(bdev)); ret = PTR_ERR(bdev); goto out_err; } page = virt_to_page(ctx->bounce); start_sect = (file_offset + offset) / 512; end_sect = (file_offset + offset + count - 1) / 512; for (i = start_sect; i <= end_sect; i++) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_len = 512; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_size = 512; bio.bi_bdev = bdev; bio.bi_sector = i; init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(READ, &bio); wait_for_completion(&complete); if (!test_bit(BIO_UPTODATE, &bio.bi_flags)) { ret = -EIO; goto out_err; } if ((i == start_sect) && ((file_offset + offset) % 512 != 0)) { /* first sect, may be the only sect */ memcpy(buffer, ctx->bounce + (file_offset + offset) % 512, min((unsigned long)count, (unsigned long) (512 - (file_offset + offset) % 512))); index += min((unsigned long)count, (unsigned long) (512 - (file_offset + offset) % 512)); } else if ((i == end_sect) && ((file_offset + offset + count) % 512 != 0)) { /* last sect */ memcpy(buffer + index, ctx->bounce, (file_offset + offset + count) % 512); } else { /* middle sect */ memcpy(buffer + index, ctx->bounce, 512); index += 512; } } blkdev_put(bdev, FMODE_READ); *start = (char *)count; if ((offset + count) == file_length) *peof = 1; mutex_unlock(&drv_mutex); return count; out_err: mutex_unlock(&drv_mutex); return ret; }