source: trunk/kernel/fs/fatfs/fat32_mapper.c @ 9

Last change on this file since 9 was 1, checked in by alain, 7 years ago

First import

File size: 8.5 KB
Line 
1/*
2 * fat32/fat32_mapper.c - fat32 mapper related operations
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS-kernel.
8 *
9 * ALMOS-kernel is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS-kernel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <stdint.h>
24#include <page.h>
25#include <ppm.h>
26#include <pmm.h>
27#include <vfs.h>
28#include <thread.h>
29#include <driver.h>
30#include <blkio.h>
31#include <mapper.h>
32#include <list.h>
33
34#include <fat32.h>
35#include <fat32-private.h>
36
37//TODO: remove
38struct vfat_file_s
39{
40        struct vfat_context_s *ctx;
41        vfat_cluster_t  first_cluster;
42        vfat_cluster_t  pg_current_cluster;
43        vfat_cluster_t  pg_current_rank;
44};
45
46static inline error_t vfat_pgio_fat(struct vfat_context_s* ctx, struct page_s *page, uint_t flags) 
47{
48        struct blkio_s *blkio;
49        struct device_s* dev;
50        uint_t sectors_per_page;
51        vfat_cluster_t lba_start;
52        uint_t vaddr;
53        error_t err;
54
55        dev              = ctx->dev;
56        sectors_per_page = PMM_PAGE_SIZE / ctx->bytes_per_sector;
57        lba_start        = page->index * sectors_per_page;
58 
59        if((err = blkio_init(dev, page, 1)) != 0)
60                return err;
61
62        vaddr = (uint_t) ppm_page2addr(page);
63
64        blkio                 = list_first(&page->root, struct blkio_s, b_list);
65        blkio->b_dev_rq.src   = (void*)lba_start;
66        blkio->b_dev_rq.dst   = (void*)vaddr;
67        blkio->b_dev_rq.count = sectors_per_page;
68
69        err = blkio_sync(page,flags);
70        blkio_destroy(page);
71        return err;
72}
73
74//TODO: remove file info ?
75static inline error_t vfat_pgio_reg(struct vfat_file_s *file_info, struct page_s *page, uint_t flags)
76{
77        struct vfat_context_s* ctx;
78        struct slist_entry *iter;
79        struct blkio_s *blkio;
80        vfat_cluster_t cluster_rank;
81        vfat_cluster_t effective_rank;
82        vfat_cluster_t current_vfat_cluster;
83        uint_t sector_start;
84        uint_t sector_count;
85        uint_t blkio_nr;
86        uint_t clusters_per_page;
87        uint_t vaddr;
88        error_t err;
89
90        ctx = file_info->ctx;
91
92        clusters_per_page = (ctx->bytes_per_cluster <= PMM_PAGE_SIZE) ? 
93                PMM_PAGE_SIZE / ctx->bytes_per_cluster : 1;
94
95        vfat_cluster_t cluster_index[clusters_per_page];
96        uint_t extended[clusters_per_page];
97
98        current_vfat_cluster = file_info->pg_current_cluster;
99        cluster_rank     = (page->index << PMM_PAGE_SHIFT) / ctx->bytes_per_cluster;
100        effective_rank   = cluster_rank;
101        cluster_index[0] = current_vfat_cluster;
102        extended[0]      = 0;
103
104        vfat_dmsg(1, "%s: %d clusters per page, %d is the first clstr, current clstr %d, rank %d\n",
105                  __FUNCTION__, 
106                  clusters_per_page, 
107                  file_info->first_cluster, 
108                  current_vfat_cluster, 
109                  cluster_rank);
110
111        if(cluster_rank != file_info->pg_current_rank)
112        {
113                if(cluster_rank > file_info->pg_current_rank)
114                        effective_rank -= file_info->pg_current_rank;
115                else
116                        current_vfat_cluster = file_info->first_cluster;
117
118                vfat_dmsg(1, "%s: pgindex %d, cluster_rank %d, effective_rank %d, current_cluster %d\n",
119                          __FUNCTION__, 
120                          page->index, 
121                          cluster_rank, 
122                          effective_rank, 
123                          current_vfat_cluster);
124 
125                if(effective_rank != 0)
126                {
127                        err = vfat_cluster_lookup(ctx, 
128                                                  current_vfat_cluster, 
129                                                  effective_rank, 
130                                                  &cluster_index[0], 
131                                                  &extended[0]);
132
133                        if(err) return err;
134                }
135
136                current_vfat_cluster = cluster_index[0];
137        }
138
139        current_vfat_cluster = cluster_index[0];
140        vfat_dmsg(1, "%s: %d is the first cluster to be read\n", __FUNCTION__, current_vfat_cluster);
141 
142        for (blkio_nr = 1; blkio_nr < clusters_per_page; blkio_nr++) 
143        {
144                if((err = vfat_cluster_lookup(ctx,
145                                              current_vfat_cluster,
146                                              1,
147                                              &cluster_index[blkio_nr],
148                                              &extended[blkio_nr])) != 0) 
149                {
150                        if (err == VFS_ENOSPC && (flags & BLKIO_RD))
151                        {
152                                extended[blkio_nr] = 1; /* to adjust the i counter */
153                                break;
154                        }
155                        return err;
156                }
157                current_vfat_cluster = cluster_index[blkio_nr];
158        }
159
160        uint_t i = clusters_per_page;
161
162        if (flags & BLKIO_RD)
163        {
164                for (i = 0; i < clusters_per_page; i++)
165                        if (extended[i])
166                                break;
167        }
168 
169        current_vfat_cluster = cluster_index[0];
170        sector_start = VFAT_CONVERT_CLUSTER(ctx,current_vfat_cluster);
171 
172        if (i == 0) // Nothing to read because it's a new cluster.
173                return 0;
174
175        if(ctx->bytes_per_cluster <= PMM_PAGE_SIZE) 
176        {
177                // mutliple clusters per page
178                sector_count = ctx->sectors_per_cluster;
179        }
180        else 
181        {
182                // clusters in multiple pages
183                sector_count = PMM_PAGE_SIZE / ctx->bytes_per_sector;
184                blkio_nr     = page->index % (ctx->bytes_per_cluster >> PMM_PAGE_SHIFT);
185                sector_start = sector_start + blkio_nr * sector_count;
186        }
187 
188        // initializing the blkio structures
189        if((err = blkio_init(ctx->dev, page, i)))
190                return err;
191
192        vaddr = (uint_t) ppm_page2addr(page);
193        i = 0;
194
195        vfat_dmsg(1, "%s, new page %p\n", __FUNCTION__, vaddr);
196 
197        // we initialize the dev requests for each sector
198        list_foreach(&page->root, iter) 
199        {
200                blkio = list_element(iter, struct blkio_s, b_list);
201                blkio->b_dev_rq.src   = (void*)sector_start;
202                blkio->b_dev_rq.dst   = (void*)vaddr;
203                blkio->b_dev_rq.count = sector_count;
204                i++;
205
206                // lookup the next cluster
207                if((clusters_per_page > 1) && (i < clusters_per_page)) 
208                {
209                        current_vfat_cluster = cluster_index[i];
210                        sector_start         = VFAT_CONVERT_CLUSTER(ctx,current_vfat_cluster);
211                        vaddr               += ctx->bytes_per_cluster;
212                        cluster_rank ++;
213                }
214        }
215
216        err = blkio_sync(page,flags);
217        blkio_destroy(page);
218        file_info->pg_current_cluster = current_vfat_cluster;
219        file_info->pg_current_rank    = cluster_rank;
220
221        return err;
222}
223
224MAPPER_READ_PAGE(vfat_node_read_page)
225{
226        struct mapper_s *mapper;
227        struct vfs_inode_s *inode;
228        struct vfat_inode_s *node_info;
229        struct vfat_file_s file_info;
230        uint_t op_flags;
231
232        op_flags = (flags & MAPPER_SYNC_OP) ? BLKIO_SYNC | BLKIO_RD : BLKIO_RD;
233
234        mapper = page->mapper;
235
236        if(mapper->m_inode == NULL)
237                return vfat_pgio_fat(mapper->m_data, page, op_flags);
238
239        inode                        = mapper->m_inode;
240        node_info                    = inode->i_pv;
241        file_info.ctx                = &inode->i_ctx->ctx_vfat;
242        file_info.first_cluster       = node_info->first_cluster;
243        file_info.pg_current_cluster = node_info->first_cluster;
244        file_info.pg_current_rank    = 0;
245
246        return vfat_pgio_reg(&file_info, page, op_flags);
247}
248
249MAPPER_WRITE_PAGE(vfat_node_write_page) 
250{
251        struct mapper_s *mapper;
252        struct vfs_inode_s *inode;
253        struct vfat_inode_s *node_info;
254        struct vfat_file_s file_info;
255        uint_t op_flags;
256
257        op_flags = (flags & MAPPER_SYNC_OP) ? BLKIO_SYNC : 0;
258
259        mapper = page->mapper;
260
261        if(mapper->m_inode == NULL)
262                return vfat_pgio_fat(mapper->m_data, page, op_flags);
263
264        inode                        = page->mapper->m_inode;
265        node_info                    = inode->i_pv;
266        file_info.ctx                = &inode->i_ctx->ctx_vfat;
267        file_info.first_cluster       = node_info->first_cluster;
268        file_info.pg_current_cluster = node_info->first_cluster;
269        file_info.pg_current_rank    = 0;
270
271        return vfat_pgio_reg(&file_info, page, op_flags);
272}
273
274MAPPER_READ_PAGE(vfat_file_read_page) 
275{
276        uint_t op_flags;
277        struct mapper_s *mapper;
278        struct vfat_file_s file_info;
279        struct vfs_inode_s *inode;
280        struct vfat_inode_s *node_info;
281
282        op_flags = (flags & MAPPER_SYNC_OP) ? BLKIO_SYNC | BLKIO_RD : BLKIO_RD;
283
284        mapper = page->mapper;
285        inode                        = mapper->m_inode;
286        node_info                    = inode->i_pv;
287        file_info.ctx                = &inode->i_ctx->ctx_vfat;
288        file_info.first_cluster       = node_info->first_cluster;
289        file_info.pg_current_cluster = node_info->first_cluster;
290        file_info.pg_current_rank    = 0;
291
292        return vfat_pgio_reg(&file_info, page, op_flags);
293}
294
295const struct mapper_op_s vfat_file_mapper_op =
296{
297        .writepage        = vfat_node_write_page,
298        .readpage         = vfat_file_read_page,
299        .sync_page        = mapper_default_sync_page,
300        .set_page_dirty   = mapper_default_set_page_dirty,
301        .clear_page_dirty = mapper_default_clear_page_dirty,
302        .releasepage      = mapper_default_release_page,
303};
304
305const struct mapper_op_s vfat_inode_mapper_op =
306{
307        .writepage        = vfat_node_write_page,
308        .readpage         = vfat_node_read_page,
309        .sync_page        = mapper_default_sync_page,
310        .set_page_dirty   = mapper_default_set_page_dirty,
311        .clear_page_dirty = mapper_default_clear_page_dirty,
312        .releasepage      = mapper_default_release_page,
313};
Note: See TracBrowser for help on using the repository browser.