linux/fs/hpfs/buffer.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/hpfs/buffer.c
   3 *
   4 *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
   5 *
   6 *  general buffer i/o
   7 */
   8#include <linux/sched.h>
   9#include <linux/slab.h>
  10#include <linux/blkdev.h>
  11#include "hpfs_fn.h"
  12
  13void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
  14{
  15        struct buffer_head *bh;
  16        struct blk_plug plug;
  17
  18        if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size))
  19                return;
  20
  21        bh = sb_find_get_block(s, secno);
  22        if (bh) {
  23                if (buffer_uptodate(bh)) {
  24                        brelse(bh);
  25                        return;
  26                }
  27                brelse(bh);
  28        };
  29
  30        blk_start_plug(&plug);
  31        while (n > 0) {
  32                if (unlikely(secno >= hpfs_sb(s)->sb_fs_size))
  33                        break;
  34                sb_breadahead(s, secno);
  35                secno++;
  36                n--;
  37        }
  38        blk_finish_plug(&plug);
  39}
  40
  41/* Map a sector into a buffer and return pointers to it and to the buffer. */
  42
  43void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
  44                 int ahead)
  45{
  46        struct buffer_head *bh;
  47
  48        hpfs_lock_assert(s);
  49
  50        hpfs_prefetch_sectors(s, secno, ahead);
  51
  52        cond_resched();
  53
  54        *bhp = bh = sb_bread(s, secno);
  55        if (bh != NULL)
  56                return bh->b_data;
  57        else {
  58                printk("HPFS: hpfs_map_sector: read error\n");
  59                return NULL;
  60        }
  61}
  62
  63/* Like hpfs_map_sector but don't read anything */
  64
  65void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp)
  66{
  67        struct buffer_head *bh;
  68        /*return hpfs_map_sector(s, secno, bhp, 0);*/
  69
  70        hpfs_lock_assert(s);
  71
  72        cond_resched();
  73
  74        if ((*bhp = bh = sb_getblk(s, secno)) != NULL) {
  75                if (!buffer_uptodate(bh)) wait_on_buffer(bh);
  76                set_buffer_uptodate(bh);
  77                return bh->b_data;
  78        } else {
  79                printk("HPFS: hpfs_get_sector: getblk failed\n");
  80                return NULL;
  81        }
  82}
  83
  84/* Map 4 sectors into a 4buffer and return pointers to it and to the buffer. */
  85
  86void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh,
  87                   int ahead)
  88{
  89        struct buffer_head *bh;
  90        char *data;
  91
  92        hpfs_lock_assert(s);
  93
  94        cond_resched();
  95
  96        if (secno & 3) {
  97                printk("HPFS: hpfs_map_4sectors: unaligned read\n");
  98                return NULL;
  99        }
 100
 101        hpfs_prefetch_sectors(s, secno, 4 + ahead);
 102
 103        qbh->data = data = kmalloc(2048, GFP_NOFS);
 104        if (!data) {
 105                printk("HPFS: hpfs_map_4sectors: out of memory\n");
 106                goto bail;
 107        }
 108
 109        qbh->bh[0] = bh = sb_bread(s, secno);
 110        if (!bh)
 111                goto bail0;
 112        memcpy(data, bh->b_data, 512);
 113
 114        qbh->bh[1] = bh = sb_bread(s, secno + 1);
 115        if (!bh)
 116                goto bail1;
 117        memcpy(data + 512, bh->b_data, 512);
 118
 119        qbh->bh[2] = bh = sb_bread(s, secno + 2);
 120        if (!bh)
 121                goto bail2;
 122        memcpy(data + 2 * 512, bh->b_data, 512);
 123
 124        qbh->bh[3] = bh = sb_bread(s, secno + 3);
 125        if (!bh)
 126                goto bail3;
 127        memcpy(data + 3 * 512, bh->b_data, 512);
 128
 129        return data;
 130
 131 bail3:
 132        brelse(qbh->bh[2]);
 133 bail2:
 134        brelse(qbh->bh[1]);
 135 bail1:
 136        brelse(qbh->bh[0]);
 137 bail0:
 138        kfree(data);
 139        printk("HPFS: hpfs_map_4sectors: read error\n");
 140 bail:
 141        return NULL;
 142}
 143
 144/* Don't read sectors */
 145
 146void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
 147                          struct quad_buffer_head *qbh)
 148{
 149        cond_resched();
 150
 151        hpfs_lock_assert(s);
 152
 153        if (secno & 3) {
 154                printk("HPFS: hpfs_get_4sectors: unaligned read\n");
 155                return NULL;
 156        }
 157
 158        /*return hpfs_map_4sectors(s, secno, qbh, 0);*/
 159        if (!(qbh->data = kmalloc(2048, GFP_NOFS))) {
 160                printk("HPFS: hpfs_get_4sectors: out of memory\n");
 161                return NULL;
 162        }
 163        if (!(hpfs_get_sector(s, secno, &qbh->bh[0]))) goto bail0;
 164        if (!(hpfs_get_sector(s, secno + 1, &qbh->bh[1]))) goto bail1;
 165        if (!(hpfs_get_sector(s, secno + 2, &qbh->bh[2]))) goto bail2;
 166        if (!(hpfs_get_sector(s, secno + 3, &qbh->bh[3]))) goto bail3;
 167        memcpy(qbh->data, qbh->bh[0]->b_data, 512);
 168        memcpy(qbh->data + 512, qbh->bh[1]->b_data, 512);
 169        memcpy(qbh->data + 2*512, qbh->bh[2]->b_data, 512);
 170        memcpy(qbh->data + 3*512, qbh->bh[3]->b_data, 512);
 171        return qbh->data;
 172
 173        bail3:  brelse(qbh->bh[2]);
 174        bail2:  brelse(qbh->bh[1]);
 175        bail1:  brelse(qbh->bh[0]);
 176        bail0:
 177        return NULL;
 178}
 179        
 180
 181void hpfs_brelse4(struct quad_buffer_head *qbh)
 182{
 183        brelse(qbh->bh[3]);
 184        brelse(qbh->bh[2]);
 185        brelse(qbh->bh[1]);
 186        brelse(qbh->bh[0]);
 187        kfree(qbh->data);
 188}       
 189
 190void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh)
 191{
 192        memcpy(qbh->bh[0]->b_data, qbh->data, 512);
 193        memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512);
 194        memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512);
 195        memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512);
 196        mark_buffer_dirty(qbh->bh[0]);
 197        mark_buffer_dirty(qbh->bh[1]);
 198        mark_buffer_dirty(qbh->bh[2]);
 199        mark_buffer_dirty(qbh->bh[3]);
 200}
 201