~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/hpfs/buffer.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php