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 pr_err("%s(): read error\n", __func__); 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 pr_err("%s(): getblk failed\n", __func__); 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 char *data; 90 91 hpfs_lock_assert(s); 92 93 cond_resched(); 94 95 if (secno & 3) { 96 pr_err("%s(): unaligned read\n", __func__); 97 return NULL; 98 } 99 100 hpfs_prefetch_sectors(s, secno, 4 + ahead); 101 102 if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0; 103 if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1; 104 if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2; 105 if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3; 106 107 if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && 108 likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && 109 likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) { 110 return qbh->data = qbh->bh[0]->b_data; 111 } 112 113 qbh->data = data = kmalloc(2048, GFP_NOFS); 114 if (!data) { 115 pr_err("%s(): out of memory\n", __func__); 116 goto bail4; 117 } 118 119 memcpy(data + 0 * 512, qbh->bh[0]->b_data, 512); 120 memcpy(data + 1 * 512, qbh->bh[1]->b_data, 512); 121 memcpy(data + 2 * 512, qbh->bh[2]->b_data, 512); 122 memcpy(data + 3 * 512, qbh->bh[3]->b_data, 512); 123 124 return data; 125 126 bail4: 127 brelse(qbh->bh[3]); 128 bail3: 129 brelse(qbh->bh[2]); 130 bail2: 131 brelse(qbh->bh[1]); 132 bail1: 133 brelse(qbh->bh[0]); 134 bail0: 135 return NULL; 136} 137 138/* Don't read sectors */ 139 140void *hpfs_get_4sectors(struct super_block *s, unsigned secno, 141 struct quad_buffer_head *qbh) 142{ 143 cond_resched(); 144 145 hpfs_lock_assert(s); 146 147 if (secno & 3) { 148 pr_err("%s(): unaligned read\n", __func__); 149 return NULL; 150 } 151 152 if (!hpfs_get_sector(s, secno + 0, &qbh->bh[0])) goto bail0; 153 if (!hpfs_get_sector(s, secno + 1, &qbh->bh[1])) goto bail1; 154 if (!hpfs_get_sector(s, secno + 2, &qbh->bh[2])) goto bail2; 155 if (!hpfs_get_sector(s, secno + 3, &qbh->bh[3])) goto bail3; 156 157 if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && 158 likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && 159 likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) { 160 return qbh->data = qbh->bh[0]->b_data; 161 } 162 163 if (!(qbh->data = kmalloc(2048, GFP_NOFS))) { 164 pr_err("%s(): out of memory\n", __func__); 165 goto bail4; 166 } 167 return qbh->data; 168 169bail4: 170 brelse(qbh->bh[3]); 171bail3: 172 brelse(qbh->bh[2]); 173bail2: 174 brelse(qbh->bh[1]); 175bail1: 176 brelse(qbh->bh[0]); 177bail0: 178 return NULL; 179} 180 181 182void hpfs_brelse4(struct quad_buffer_head *qbh) 183{ 184 if (unlikely(qbh->data != qbh->bh[0]->b_data)) 185 kfree(qbh->data); 186 brelse(qbh->bh[0]); 187 brelse(qbh->bh[1]); 188 brelse(qbh->bh[2]); 189 brelse(qbh->bh[3]); 190} 191 192void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh) 193{ 194 if (unlikely(qbh->data != qbh->bh[0]->b_data)) { 195 memcpy(qbh->bh[0]->b_data, qbh->data + 0 * 512, 512); 196 memcpy(qbh->bh[1]->b_data, qbh->data + 1 * 512, 512); 197 memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); 198 memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); 199 } 200 mark_buffer_dirty(qbh->bh[0]); 201 mark_buffer_dirty(qbh->bh[1]); 202 mark_buffer_dirty(qbh->bh[2]); 203 mark_buffer_dirty(qbh->bh[3]); 204} 205