Linux Audio

Check our new training course

Loading...
  1/*
  2 * This file provides functions for block I/O operations on swap/file.
  3 *
  4 * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
  5 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
  6 *
  7 * This file is released under the GPLv2.
  8 */
  9
 10#include <linux/bio.h>
 11#include <linux/kernel.h>
 12#include <linux/pagemap.h>
 13#include <linux/swap.h>
 14
 15#include "power.h"
 16
 17/**
 18 *	submit - submit BIO request.
 19 *	@rw:	READ or WRITE.
 20 *	@off	physical offset of page.
 21 *	@page:	page we're reading or writing.
 22 *	@bio_chain: list of pending biod (for async reading)
 23 *
 24 *	Straight from the textbook - allocate and initialize the bio.
 25 *	If we're reading, make sure the page is marked as dirty.
 26 *	Then submit it and, if @bio_chain == NULL, wait.
 27 */
 28static int submit(int rw, struct block_device *bdev, sector_t sector,
 29		struct page *page, struct bio **bio_chain)
 30{
 31	const int bio_rw = rw | REQ_SYNC;
 32	struct bio *bio;
 33
 34	bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
 35	bio->bi_sector = sector;
 36	bio->bi_bdev = bdev;
 37	bio->bi_end_io = end_swap_bio_read;
 38
 39	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
 40		printk(KERN_ERR "PM: Adding page to bio failed at %llu\n",
 41			(unsigned long long)sector);
 42		bio_put(bio);
 43		return -EFAULT;
 44	}
 45
 46	lock_page(page);
 47	bio_get(bio);
 48
 49	if (bio_chain == NULL) {
 50		submit_bio(bio_rw, bio);
 51		wait_on_page_locked(page);
 52		if (rw == READ)
 53			bio_set_pages_dirty(bio);
 54		bio_put(bio);
 55	} else {
 56		if (rw == READ)
 57			get_page(page);	/* These pages are freed later */
 58		bio->bi_private = *bio_chain;
 59		*bio_chain = bio;
 60		submit_bio(bio_rw, bio);
 61	}
 62	return 0;
 63}
 64
 65int hib_bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
 66{
 67	return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
 68			virt_to_page(addr), bio_chain);
 69}
 70
 71int hib_bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
 72{
 73	return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
 74			virt_to_page(addr), bio_chain);
 75}
 76
 77int hib_wait_on_bio_chain(struct bio **bio_chain)
 78{
 79	struct bio *bio;
 80	struct bio *next_bio;
 81	int ret = 0;
 82
 83	if (bio_chain == NULL)
 84		return 0;
 85
 86	bio = *bio_chain;
 87	if (bio == NULL)
 88		return 0;
 89	while (bio) {
 90		struct page *page;
 91
 92		next_bio = bio->bi_private;
 93		page = bio->bi_io_vec[0].bv_page;
 94		wait_on_page_locked(page);
 95		if (!PageUptodate(page) || PageError(page))
 96			ret = -EIO;
 97		put_page(page);
 98		bio_put(bio);
 99		bio = next_bio;
100	}
101	*bio_chain = NULL;
102	return ret;
103}