示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
文件: swsusp.c 项目: xricson/knoppix
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;
}
示例#4
0
/*
 * 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;
}
示例#5
0
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;
}
示例#7
0
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;
}
示例#9
0
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;
}
示例#10
0
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;
}