linux-bk/fs/iobuf.c
<<
>>
Prefs
   1/*
   2 * iobuf.c
   3 *
   4 * Keep track of the general-purpose IO-buffer structures used to track
   5 * abstract kernel-space io buffers.
   6 * 
   7 */
   8
   9#include <linux/iobuf.h>
  10#include <linux/slab.h>
  11
  12int end_kio_request(struct kiobuf *kiobuf, int uptodate)
  13{
  14        int ret = 1;
  15
  16        if ((!uptodate) && !kiobuf->errno)
  17                kiobuf->errno = -EIO;
  18
  19        if (atomic_dec_and_test(&kiobuf->io_count)) {
  20                ret = 0;
  21                if (kiobuf->end_io)
  22                        kiobuf->end_io(kiobuf);
  23                wake_up(&kiobuf->wait_queue);
  24        }
  25
  26        return ret;
  27}
  28
  29static void kiobuf_init(struct kiobuf *iobuf)
  30{
  31        init_waitqueue_head(&iobuf->wait_queue);
  32        atomic_set(&iobuf->io_count, 0);
  33        iobuf->array_len = KIO_STATIC_PAGES;
  34        iobuf->maplist   = iobuf->map_array;
  35        iobuf->nr_pages   = 0;
  36        iobuf->locked   = 0;
  37        iobuf->io_count.counter   = 0;
  38        iobuf->end_io = NULL;
  39}
  40
  41int alloc_kiovec(int nr, struct kiobuf **bufp)
  42{
  43        int i;
  44        struct kiobuf *iobuf;
  45        
  46        for (i = 0; i < nr; i++) {
  47                iobuf = kmalloc(sizeof(struct kiobuf), GFP_KERNEL);
  48                if (!iobuf) {
  49                        free_kiovec(i, bufp);
  50                        return -ENOMEM;
  51                }
  52                kiobuf_init(iobuf);
  53                bufp[i] = iobuf;
  54        }
  55        
  56        return 0;
  57}
  58
  59void free_kiovec(int nr, struct kiobuf **bufp) 
  60{
  61        int i;
  62        struct kiobuf *iobuf;
  63        
  64        for (i = 0; i < nr; i++) {
  65                iobuf = bufp[i];
  66                if (iobuf->locked)
  67                        unlock_kiovec(1, &iobuf);
  68                if (iobuf->array_len > KIO_STATIC_PAGES)
  69                        kfree (iobuf->maplist);
  70                kfree(bufp[i]);
  71        }
  72}
  73
  74int expand_kiobuf(struct kiobuf *iobuf, int wanted)
  75{
  76        struct page ** maplist;
  77        
  78        if (iobuf->array_len >= wanted)
  79                return 0;
  80        
  81        maplist = (struct page **) 
  82                kmalloc(wanted * sizeof(struct page **), GFP_KERNEL);
  83        if (!maplist)
  84                return -ENOMEM;
  85
  86        /* Did it grow while we waited? */
  87        if (iobuf->array_len >= wanted) {
  88                kfree(maplist);
  89                return 0;
  90        }
  91        
  92        memcpy (maplist, iobuf->maplist, iobuf->array_len * sizeof(struct page **));
  93
  94        if (iobuf->array_len > KIO_STATIC_PAGES)
  95                kfree (iobuf->maplist);
  96        
  97        iobuf->maplist   = maplist;
  98        iobuf->array_len = wanted;
  99        return 0;
 100}
 101
 102
 103void kiobuf_wait_for_io(struct kiobuf *kiobuf)
 104{
 105        struct task_struct *tsk = current;
 106        DECLARE_WAITQUEUE(wait, tsk);
 107
 108        if (atomic_read(&kiobuf->io_count) == 0)
 109                return;
 110
 111        add_wait_queue(&kiobuf->wait_queue, &wait);
 112repeat:
 113        set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 114        if (atomic_read(&kiobuf->io_count) != 0) {
 115                blk_run_queues();
 116                schedule();
 117                if (atomic_read(&kiobuf->io_count) != 0)
 118                        goto repeat;
 119        }
 120        tsk->state = TASK_RUNNING;
 121        remove_wait_queue(&kiobuf->wait_queue, &wait);
 122}
 123
 124
 125
 126
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.