linux/kernel/power/block_io.c
<<
>>
Prefs
   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}
 104
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.