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 "hpfs_fn.h" 11 12 /* Map a sector into a buffer and return pointers to it and to the buffer. */ 13 14 void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp, 15 int ahead) 16 { 17 struct buffer_head *bh; 18 19 hpfs_lock_assert(s); 20 21 cond_resched(); 22 23 *bhp = bh = sb_bread(s, secno); 24 if (bh != NULL) 25 return bh->b_data; 26 else { 27 printk("HPFS: hpfs_map_sector: read error\n"); 28 return NULL; 29 } 30 } 31 32 /* Like hpfs_map_sector but don't read anything */ 33 34 void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp) 35 { 36 struct buffer_head *bh; 37 /*return hpfs_map_sector(s, secno, bhp, 0);*/ 38 39 hpfs_lock_assert(s); 40 41 cond_resched(); 42 43 if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { 44 if (!buffer_uptodate(bh)) wait_on_buffer(bh); 45 set_buffer_uptodate(bh); 46 return bh->b_data; 47 } else { 48 printk("HPFS: hpfs_get_sector: getblk failed\n"); 49 return NULL; 50 } 51 } 52 53 /* Map 4 sectors into a 4buffer and return pointers to it and to the buffer. */ 54 55 void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh, 56 int ahead) 57 { 58 struct buffer_head *bh; 59 char *data; 60 61 hpfs_lock_assert(s); 62 63 cond_resched(); 64 65 if (secno & 3) { 66 printk("HPFS: hpfs_map_4sectors: unaligned read\n"); 67 return NULL; 68 } 69 70 qbh->data = data = kmalloc(2048, GFP_NOFS); 71 if (!data) { 72 printk("HPFS: hpfs_map_4sectors: out of memory\n"); 73 goto bail; 74 } 75 76 qbh->bh[0] = bh = sb_bread(s, secno); 77 if (!bh) 78 goto bail0; 79 memcpy(data, bh->b_data, 512); 80 81 qbh->bh[1] = bh = sb_bread(s, secno + 1); 82 if (!bh) 83 goto bail1; 84 memcpy(data + 512, bh->b_data, 512); 85 86 qbh->bh[2] = bh = sb_bread(s, secno + 2); 87 if (!bh) 88 goto bail2; 89 memcpy(data + 2 * 512, bh->b_data, 512); 90 91 qbh->bh[3] = bh = sb_bread(s, secno + 3); 92 if (!bh) 93 goto bail3; 94 memcpy(data + 3 * 512, bh->b_data, 512); 95 96 return data; 97 98 bail3: 99 brelse(qbh->bh[2]); 100 bail2: 101 brelse(qbh->bh[1]); 102 bail1: 103 brelse(qbh->bh[0]); 104 bail0: 105 kfree(data); 106 printk("HPFS: hpfs_map_4sectors: read error\n"); 107 bail: 108 return NULL; 109 } 110 111 /* Don't read sectors */ 112 113 void *hpfs_get_4sectors(struct super_block *s, unsigned secno, 114 struct quad_buffer_head *qbh) 115 { 116 cond_resched(); 117 118 hpfs_lock_assert(s); 119 120 if (secno & 3) { 121 printk("HPFS: hpfs_get_4sectors: unaligned read\n"); 122 return NULL; 123 } 124 125 /*return hpfs_map_4sectors(s, secno, qbh, 0);*/ 126 if (!(qbh->data = kmalloc(2048, GFP_NOFS))) { 127 printk("HPFS: hpfs_get_4sectors: out of memory\n"); 128 return NULL; 129 } 130 if (!(hpfs_get_sector(s, secno, &qbh->bh[0]))) goto bail0; 131 if (!(hpfs_get_sector(s, secno + 1, &qbh->bh[1]))) goto bail1; 132 if (!(hpfs_get_sector(s, secno + 2, &qbh->bh[2]))) goto bail2; 133 if (!(hpfs_get_sector(s, secno + 3, &qbh->bh[3]))) goto bail3; 134 memcpy(qbh->data, qbh->bh[0]->b_data, 512); 135 memcpy(qbh->data + 512, qbh->bh[1]->b_data, 512); 136 memcpy(qbh->data + 2*512, qbh->bh[2]->b_data, 512); 137 memcpy(qbh->data + 3*512, qbh->bh[3]->b_data, 512); 138 return qbh->data; 139 140 bail3: brelse(qbh->bh[2]); 141 bail2: brelse(qbh->bh[1]); 142 bail1: brelse(qbh->bh[0]); 143 bail0: 144 return NULL; 145 } 146 147 148 void hpfs_brelse4(struct quad_buffer_head *qbh) 149 { 150 brelse(qbh->bh[3]); 151 brelse(qbh->bh[2]); 152 brelse(qbh->bh[1]); 153 brelse(qbh->bh[0]); 154 kfree(qbh->data); 155 } 156 157 void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh) 158 { 159 memcpy(qbh->bh[0]->b_data, qbh->data, 512); 160 memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512); 161 memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); 162 memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); 163 mark_buffer_dirty(qbh->bh[0]); 164 mark_buffer_dirty(qbh->bh[1]); 165 mark_buffer_dirty(qbh->bh[2]); 166 mark_buffer_dirty(qbh->bh[3]); 167 } 168