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