source: trunk/kernel/fs/fatfs/fat32_node.c @ 1

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

First import

File size: 17.3 KB
Line 
1/*
2 * fat32/fat32_node.c - fat32 node 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 <kmem.h>
24#include <string.h>
25#include <thread.h>
26#include <cluster.h>
27#include <ppm.h>
28#include <pmm.h>
29#include <page.h>
30#include <mapper.h>
31#include <vfs.h>
32
33#include <fat32.h>
34#include <fat32-private.h>
35
36
37KMEM_OBJATTR_INIT(vfat_kmem_inode_init)
38{
39        attr->type   = KMEM_VFAT_NODE;
40        attr->name   = "KCM VFAT Node";
41        attr->size   = sizeof(struct vfat_inode_s);
42        attr->aligne = 0;
43        attr->min    = CONFIG_VFAT_NODE_MIN;
44        attr->max    = CONFIG_VFAT_NODE_MAX;
45        attr->ctor   = NULL;
46        attr->dtor   = NULL;
47        return 0;
48}
49
50
51inline void vfat_getshortname(char *from, char *to) {
52        char *p = to;
53        char *q = from;
54        uint_fast8_t d;
55
56        for(d=0; (d < 8 && *q != ' '); d++)
57                *p++ = *q++;
58
59        if (*(q = &from[8]) != ' ')
60        {
61                *p++ = '.';
62                d = 0;
63                while (d++ < 3 && *q != ' ')
64                        *p++ = *q++;
65        }
66
67        *p = 0;
68}
69
70static inline void vfat_convert_name(char *str1, char *str2) {
71        uint_fast8_t i;
72        char *extention_ptr;
73
74        extention_ptr = str2 + 8;
75        memset(str2,' ',11);
76
77        for(i=0; ((*str1) && (*str1 != '.') && (i<11)) ; i++)
78                *str2++ = *str1++;
79
80        if((i<=8) && (*str1 == '.')) {
81                str1++;
82                memcpy(extention_ptr,str1,3);
83        }
84}
85
86
87VFS_INIT_NODE(vfat_init_node)
88{
89        struct vfat_inode_s *inode_info;
90        kmem_req_t req;
91
92        if(inode->i_type != VFS_VFAT_TYPE)
93                return VFS_EINVAL;
94
95        assert(inode->i_mapper);
96
97        if(inode->i_pv != NULL)
98                inode_info = (struct vfat_inode_s*)inode->i_pv;//?
99        else 
100        {
101                req.flags = AF_USER;//?
102                req.type = KMEM_VFAT_NODE;
103                req.size = sizeof(*inode_info);
104   
105                if((inode_info = kmem_alloc(&req)) == NULL)
106                {
107                        return VFS_ENOMEM;
108                }
109     
110                inode->i_pv = (void *) inode_info;
111        }
112
113        memset(inode_info, 0, sizeof(*inode_info));   
114        return 0;
115}
116
117
118VFS_RELEASE_NODE(vfat_release_node)
119{
120        kmem_req_t req;
121 
122        if(inode->i_pv != NULL)
123        {
124                req.type = KMEM_VFAT_NODE;
125                req.ptr  = inode->i_pv;
126                kmem_free(&req);
127                inode->i_pv = NULL;
128        }
129 
130        return 0;
131}
132
133
134VFS_ICREATE_NODE(vfat_icreate)
135{
136        struct vfat_inode_s *inode_info;
137        struct vfat_context_s *ctx;
138        struct page_s *tmp_page;
139        kmem_req_t req;
140        error_t err;
141
142       
143        err                             = 0;
144        ctx                             = &ic->ctx->ctx_vfat;
145        inode_info                      = inode->i_pv;
146        assert(inode->i_mapper);
147        inode->i_mapper->m_ops          = &vfat_file_mapper_op;
148
149        inode_info->flags               = ic->vfat_icreate.fat_attr;
150        inode_info->first_cluster       = ic->vfat_icreate.first_cluster;
151
152        vfat_dmsg(1, "Creating new inode with flags %x\n", inode_info->flags);
153
154
155        if(ic->attr & VFS_DIR) 
156        {
157                inode->i_mapper->m_ops = &vfat_inode_mapper_op;
158
159                if(ic->new)
160                {
161                        req.type  = KMEM_PAGE;
162                        req.size  = 0;
163                        req.flags = AF_USER | AF_ZERO;
164                        tmp_page  = kmem_alloc(&req);
165             
166                        if(tmp_page != NULL)
167                                err = mapper_add_page(inode->i_mapper, tmp_page, 0);
168                        else 
169                                err = ENOMEM;
170
171                        if(err)
172                        {
173                                if(tmp_page != NULL)
174                                {
175                                        req.ptr = tmp_page;
176                                        kmem_free(&req);
177                                }
178                                return err;
179                        }
180                        /* FIXME: we should also create dot & dotdot entries */
181                }
182 
183        }
184
185        return err;
186}
187
188//parent must be refcounted!
189//dentry must be set as INLOAD: no other thread can
190//deleted or insert it's entry!
191VFS_CREATE_NODE(vfat_create) 
192{
193        struct vfat_dentry_s *dentry_info;
194        struct vfat_inode_s *parent_info;
195        struct vfat_context_s *ctx;
196        struct page_s *page;
197        struct mapper_s *mapper;
198        struct vfat_DirEntry_s *dir;
199        struct page_s *tmp_page;
200        kmem_req_t req;
201        uint_t current_page;
202        uint_t entries_nr;
203        uint_t entry;
204        vfat_cluster_t new_cluster;
205        size_t current_offset;
206        error_t err;
207
208        ctx         = &parent->i_ctx->ctx_vfat;
209        entries_nr  = PMM_PAGE_SIZE / sizeof(struct vfat_DirEntry_s);
210        mapper      = parent->i_mapper;
211        dir         = NULL;
212        parent_info = NULL;
213        new_cluster = 0;
214        err         = 0;
215        entry       = 0;
216        page        = NULL;
217
218        vfat_dmsg(1,"vfat_create started, dentry/node to be created %s, its parent %s\n",
219                  dentry->d_name, parent->i_number);
220
221        if(dentry->d_ctx->ctx_type != VFS_VFAT_TYPE)
222                return VFS_EINVAL;
223
224        // find a first cluster for the new file
225        if(!(dentry->d_attr & (VFS_FIFO | VFS_DEV)))
226        {
227                if(vfat_alloc_fat_entry(ctx, &new_cluster))
228                        return VFS_IO_ERR;
229   
230                if(new_cluster == 0)
231                        return -VFS_ENOSPC;
232        }
233
234        dentry_info    = &dentry->d_vfat;
235        parent_info    = (struct vfat_inode_s*) parent->i_pv;
236        current_page   = 0;
237        current_offset = 0;
238
239        while(1) 
240        {
241                //TODO: lock the page in read_only to read it and then lock it back to lock to modify it or
242                //use CAS to allocate entrys ?
243                if ((page = mapper_get_page(mapper, current_page, MAPPER_SYNC_OP)) == NULL)
244                {
245                        err = VFS_IO_ERR;
246                        goto VFAT_CREATE_NODE_ERR;
247                }
248
249                dir = (struct vfat_DirEntry_s*) ppm_page2addr(page);
250   
251                page_lock(page);
252   
253                for(entry=0; entry < entries_nr; entry ++)
254                {
255                        if((dir[entry].DIR_Name[0] == 0x00) || (dir[entry].DIR_Name[0] == 0xE5))
256                        {
257                                vfat_dmsg(1,"%s: found entry %d in page %d, name[0] %d\n",
258                                          __FUNCTION__,
259                                          entry, 
260                                          current_page, 
261                                          dir[entry].DIR_Name[0]);
262                                goto FREE_ENTRY_FOUND;
263                        }
264                        current_offset += sizeof (struct vfat_DirEntry_s);
265                }
266   
267                page_unlock(page);
268                current_page ++;
269        }
270
271FREE_ENTRY_FOUND:
272        current_offset += sizeof (struct vfat_DirEntry_s);
273        // we need to set the next entry to 0 if we got the last one
274        if (dir[entry].DIR_Name[0] == 0x00) 
275        {
276                if(entry == entries_nr - 1) 
277                {
278                        req.type  = KMEM_PAGE;
279                        req.size  = 0;
280                        req.flags = AF_USER | AF_ZERO;
281                        tmp_page  = kmem_alloc(&req);
282     
283                        if(tmp_page != NULL)
284                                err = mapper_add_page(mapper, tmp_page, current_page + 1);
285                        else 
286                                err = ENOMEM;
287
288                        if(err)
289                        {
290                                page_unlock(page);
291
292                                if(tmp_page != NULL)
293                                {
294                                        req.ptr = tmp_page;
295                                        kmem_free(&req);
296                                }
297
298                                goto VFAT_CREATE_NODE_ERR;
299                        }
300               
301                        mapper->m_ops->set_page_dirty(tmp_page);
302
303                        if (current_offset == parent->i_size)
304                                parent->i_size += ctx->bytes_per_cluster;
305                }
306                else
307                        dir[entry+1].DIR_Name[0] = 0x00;
308        }
309
310        dir[entry].DIR_FstClusHI = new_cluster >> 16;
311        dir[entry].DIR_FstClusLO = new_cluster & 0xFFFF;
312        dir[entry].DIR_FileSize  = 0;
313        dir[entry].DIR_Attr      = 0;
314
315        if((dentry->d_attr & (VFS_SYS | VFS_FIFO | VFS_DEV)))
316                dir[entry].DIR_Attr |= VFAT_ATTR_SYSTEM;
317
318        if(dentry->d_attr & VFS_ARCHIVE)
319                dir[entry].DIR_Attr |= VFAT_ATTR_ARCHIVE;
320
321        if((dentry->d_attr & (VFS_RD_ONLY | VFS_FIFO | VFS_DEV)))
322                dir[entry].DIR_Attr |= VFAT_ATTR_READ_ONLY;
323
324        if(dentry->d_attr & VFS_DIR)
325                dir[entry].DIR_Attr  |= VFAT_ATTR_DIRECTORY;
326
327        vfat_convert_name(dentry->d_name,(char *)dir[entry].DIR_Name);  /* FIXME: name may be long */
328
329
330#if VFAT_INSTRUMENT
331        wr_count ++;
332#endif
333
334        dentry_info->entry_index    = current_page*entries_nr + entry;
335        dentry_info->first_cluster  = new_cluster;
336        page_unlock(page);
337
338        uint32_t ino = vfs_inum_new(parent->i_ctx);
339        /* As a dir has alwas a page allocated */
340        uint32_t isize = dentry->d_attr & VFS_DIR ? ctx->bytes_per_cluster : 0;
341
342        struct vfs_icreate_s ic = 
343                        {.ctx = parent->i_ctx, 
344                        .dentry = dentry, 
345                        .parent = {.ptr = parent, 
346                                .gc = parent->i_gc, 
347                                .cid = current_cid},
348                        .ino = ino,
349                        .size = isize,
350                        .attr = dentry->d_attr
351                        };
352
353        ic.vfat_icreate.first_cluster = new_cluster;
354        ic.vfat_icreate.fat_attr = dir[entry].DIR_Attr;
355
356        err = vfs_create_inode(&ic);
357
358        if(!err)
359                return 0;
360
361        //find the page of dir, lock it and remove the entry!
362        page_lock(page); //FIXME: is the page still valid ?
363        dir->DIR_Name[0] = (dir[1].DIR_Name[0] == 0x00) ? 0x00 : 0xE5;
364        page_unlock(page);
365
366VFAT_CREATE_NODE_ERR:
367        vfat_free_fat_entry(ctx, new_cluster);
368        return err;
369}
370
371
372//Synchro: since the corresponding dentry is set INLOAD
373//no one can delete the dentry
374VFS_LOOKUP_NODE(vfat_lookup)
375{
376        struct vfat_context_s *ctx;
377        struct vfat_inode_s *parent_info;
378        struct vfat_dentry_s *dentry_info;
379        struct vfat_entry_request_s rq;
380        struct vfat_DirEntry_s dir;
381        size_t isize;
382        vfat_cluster_t first_cluster;
383        uint_t entry_index;
384        error_t err;
385
386        ctx         = &parent->i_ctx->ctx_vfat;
387        parent_info = parent->i_pv;
388        dentry_info = &dentry->d_vfat;
389        err         = 0;
390        isize       = 0;
391
392        if(!(parent_info->flags & VFAT_ATTR_DIRECTORY))
393                return VFS_ENOTDIR;
394
395        rq.ctx         = ctx;
396        rq.parent      = parent;
397        rq.entry       = &dir;
398        rq.entry_name  = dentry->d_name;
399        rq.entry_index = &entry_index;
400
401        if((err=vfat_locate_entry(&rq)))
402                return err;
403
404#if 0
405        if(((node->i_attr & VFS_DIR) && 1) ^ ((dir.DIR_Attr & VFAT_ATTR_DIRECTORY) && 1))
406                return VFS_ENOTDIR;
407#else
408        if((dentry->d_attr & VFS_DIR) && !(dir.DIR_Attr & VFAT_ATTR_DIRECTORY))
409                return VFS_ENOTDIR;
410#endif
411
412        if(dir.DIR_Attr & VFAT_ATTR_DIRECTORY)
413                dentry->d_attr |= VFS_DIR;
414        else
415                isize = dir.DIR_FileSize;
416
417        if(dir.DIR_Attr & VFAT_ATTR_SYSTEM)    dentry->d_attr |= VFS_SYS;
418        if(dir.DIR_Attr & VFAT_ATTR_ARCHIVE)   dentry->d_attr |= VFS_ARCHIVE;
419        if(dir.DIR_Attr & VFAT_ATTR_READ_ONLY) dentry->d_attr |= VFS_RD_ONLY;
420 
421        first_cluster                   = dir.DIR_FstClusHI << 16;
422        first_cluster                   |= (0x0000FFFF & dir.DIR_FstClusLO);
423
424        if((!first_cluster)   && 
425           (dentry->d_attr & VFS_SYS)     && 
426           (dentry->d_attr & VFS_RD_ONLY) && 
427           (dentry->d_attr & VFS_DIR)) 
428        {
429                dentry->d_attr |= VFS_DEV;
430                dentry->d_attr &= ~(VFS_SYS | VFS_RD_ONLY | VFS_DIR);
431        } 
432        else
433        {
434                if((!first_cluster) && 
435                   (dentry->d_attr & VFS_SYS)   && 
436                   (dentry->d_attr & VFS_RD_ONLY)) 
437                {
438                        dentry->d_attr |= VFS_FIFO;
439                        dentry->d_attr &= ~(VFS_SYS | VFS_RD_ONLY);
440                }
441        }
442
443        if((first_cluster) && (dentry->d_attr & VFS_DIR))
444                isize = vfat_cluster_count(ctx, first_cluster) * ctx->bytes_per_cluster;
445
446        dentry_info->entry_index        = entry_index;
447        dentry_info->first_cluster      = first_cluster;
448
449        uint32_t ino = vfs_inum_new(parent->i_ctx);
450        /* As a dir has alwas a page allocated */
451
452        struct vfs_icreate_s ic = 
453                        {.ctx = parent->i_ctx, 
454                        .dentry = dentry, 
455                        .parent = {.ptr = parent, 
456                                .gc = parent->i_gc, 
457                                .cid = current_cid},
458                        .ino = ino,
459                        .size = isize,
460                        .attr = dentry->d_attr,
461                        };
462
463        ic.vfat_icreate.first_cluster = first_cluster;
464        ic.vfat_icreate.fat_attr = dir.DIR_Attr;
465
466        err = vfs_create_inode(&ic);
467
468        //drop page ?
469        if(err) return err;
470
471        return VFS_FOUND;
472}
473
474VFS_STAT_NODE(vfat_stat_node)
475{
476        struct vfat_inode_s *inode_info;
477
478        inode_info = inode->i_pv;
479
480        return vfs_stat_inode(inode, inode_info->first_cluster);
481}
482
483RPC_DECLARE(__vfat_write_inode, RPC_RET(RPC_RET_PTR(error_t, err)),
484                RPC_ARG(RPC_ARG_VAL(struct vfs_dentry_s*, dentry), 
485                RPC_ARG_VAL(size_t, size),
486                RPC_ARG_VAL(uint32_t, attr)))
487{
488        struct page_s *page;
489        struct mapper_s *mapper;
490        struct vfs_inode_s *parent;
491        struct vfat_dentry_s *dentry_info;
492        struct vfat_DirEntry_s *dir;
493        uint_t entry_index_page;
494
495        parent          = dentry->d_parent;
496        mapper          = parent->i_mapper;
497        dentry_info     = &dentry->d_vfat;
498        entry_index_page = dentry_info->entry_index * sizeof(struct vfat_DirEntry_s*) >> PMM_PAGE_SHIFT;
499        dentry->d_attr  = attr; 
500
501        *err = VFS_EINVAL;
502        if(dentry->d_ctx->ctx_type != VFS_VFAT_TYPE)
503                return; 
504
505        *err = VFS_IO_ERR;
506        //rd_lock is enough since we are supposed to be holding the dentry above with the INLOAD flag
507        if ((page = mapper_get_page(mapper, entry_index_page, MAPPER_SYNC_OP)) == NULL)
508                return; 
509
510        //do the locking of mapper_get_page, like : MAPPER_PAGE_RD_LOCK
511        page_lock(page);
512
513        dir  = (struct vfat_DirEntry_s*) ppm_page2addr(page);
514        dir += dentry_info->entry_index;
515
516        if(attr & VFS_DIR) dir->DIR_Attr |= VFAT_ATTR_DIRECTORY;
517        if(attr & VFS_SYS) dir->DIR_Attr |= VFAT_ATTR_SYSTEM;
518        if(attr & VFS_ARCHIVE) dir->DIR_Attr |= VFAT_ATTR_ARCHIVE;
519        if(attr & VFS_RD_ONLY) dir->DIR_Attr |= VFAT_ATTR_READ_ONLY;
520
521        dir->DIR_FileSize = size;
522
523        mapper->m_ops->set_page_dirty(page);
524
525        page_unlock(page);
526
527        *err = 0;
528}
529
530//update the dentry of this inode
531//FIXME: check syncro
532VFS_WRITE_NODE(vfat_write_node)
533{
534        struct vfs_dentry_s *dentry;
535        cid_t dentry_cid;
536        error_t err;
537        uint32_t attr;
538        size_t isize;
539
540        dentry          = inode->i_dentry;
541        dentry_cid      = inode->i_parent.cid;
542        isize           = inode->i_size;
543        attr            = inode->i_attr;
544
545        RCPC(dentry_cid, RPC_PRIO_FS_WRITE, __vfat_write_inode, RPC_RECV(RPC_RECV_OBJ(err)),
546                RPC_SEND(RPC_SEND_OBJ(dentry), RPC_SEND_OBJ(isize), RPC_SEND_OBJ(attr)));
547
548#if VFAT_INSTRUMENT
549        wr_count ++;
550#endif
551        return err;
552}
553
554#if 1
555/* Check if dir is empty and    *
556 * empty dir/files
557 * return 0 if success
558 * else return 1                *
559 * The deletion of the inode is *
560 * no necesseray for the FAT fs *
561 * (as inode does not exist).   */
562VFS_DELETE_NODE(vfat_delete)
563{
564        struct vfat_inode_s *inode_info;
565        struct vfat_DirEntry_s dir;
566        struct vfat_context_s *ctx;
567        struct mapper_s *mapper;
568        struct page_s *page;
569        uint8_t *buff;
570        uint32_t found;
571        uint32_t offset; //64 bits?
572        error_t err;
573
574        ctx             = &inode->i_ctx->ctx_vfat;
575        inode_info      = inode->i_pv;
576        mapper          = inode->i_mapper;
577        found           = 0;
578        offset          = 0;
579        err             = 0;
580
581        if(!(inode->i_attr & VFS_DIR) )
582                goto FREE_CNT;
583
584
585        /* TODO: dont call mapper every time, as page can be reused */
586        while(!found) 
587        {
588                if ((page = mapper_get_page(mapper, 
589                                            offset >> PMM_PAGE_SHIFT, 
590                                            MAPPER_SYNC_OP)) == NULL)
591                        return VFS_IO_ERR;
592
593                page_lock(page);
594
595                buff  = ppm_page2addr(page);
596                buff += offset % PMM_PAGE_SIZE;
597
598                //is a memcpy necessary?
599                memcpy(&dir, buff, sizeof(dir));
600
601                if(dir.DIR_Name[0] == 0x00) {
602                        vfat_dmsg(3,"vfat_readdir: entries termination found (0x00)\n");
603                        page_unlock(page);
604                        break;
605                }
606
607                if(dir.DIR_Name[0] == 0xE5) {
608                        vfat_dmsg(3,"entry was freeed previously\n");
609                        goto VFS_READ_DIR_NEXT;
610                }
611
612                if(dir.DIR_Attr == 0x0F) {
613                        vfat_dmsg(3,"this entry is a long one\n");
614                        // FIXME should not delete dirs who contain long name ?
615                        // knowink that we can't read them.
616                        //goto VFS_READ_DIR_NEXT;
617                        //found = 1;
618                        page_unlock(page);
619                        break;
620                }
621
622                if(dir.DIR_Name[0] == '.') // dot and dot_dot entries: since fat doesnot support hiden file!
623                        goto VFS_READ_DIR_NEXT;
624
625                vfat_dmsg(1, "DIR NOT empty (%s), name: %s\n",__FUNCTION__, dir.DIR_Name);
626                found = 1;
627
628        VFS_READ_DIR_NEXT:
629                page_unlock(page);
630                if(found) break;
631                offset += sizeof(struct vfat_DirEntry_s);
632        }
633
634FREE_CNT:
635
636        //Free content if not fifo
637        if(!(inode->i_attr & VFS_FIFO))
638                err=vfat_free_fat_entry(ctx, inode_info->first_cluster);
639
640        assert(!err);
641
642        return found ? VFS_ENOTEMPTY : 0;
643}
644
645VFS_UNLINK_NODE(vfat_unlink_node)
646{
647        struct vfat_entry_request_s rq;
648        struct page_s *page;
649        struct page_s *page2;
650        struct mapper_s *mapper;
651        struct vfat_context_s *ctx;
652        struct vfat_dentry_s *dentry_info;
653        struct vfat_DirEntry_s *dir;
654        struct vfat_DirEntry_s *last_dir;
655        uint_t entry_index;
656        uint_t entry_index_page;
657        error_t err;
658        uint_t val;
659
660        page2           = NULL;
661        err             = 0;
662        ctx             = &dentry->d_ctx->ctx_vfat;
663        dentry_info     = &dentry->d_vfat;
664        mapper          = parent->i_mapper;
665
666        //Free FAT name directory entry
667        if((dentry->d_attr & VFS_FIFO) && (dentry->d_op != &vfat_d_op)) //?
668        {
669                rq.entry       = NULL;
670                rq.ctx         = ctx;
671                rq.parent      = parent;
672                rq.entry_name  = dentry->d_name;
673                rq.entry_index = &entry_index;
674
675                if((err=vfat_locate_entry(&rq)))
676                        return err;
677
678        } else 
679        {
680                entry_index = dentry_info->entry_index;
681        }
682
683        entry_index_page = (entry_index*sizeof(struct vfat_DirEntry_s)) >> PMM_PAGE_SHIFT;
684        page = mapper_get_page(mapper, entry_index_page, MAPPER_SYNC_OP);
685
686        if(page == NULL)
687        { 
688                val = entry_index_page;
689                err = VFS_IO_ERR;
690                goto UNLINK_IOERR;
691        }
692
693        dir = (struct vfat_DirEntry_s*) ppm_page2addr(page);
694        dir += entry_index % (PMM_PAGE_SIZE / sizeof(struct vfat_DirEntry_s));
695
696        uint_t entries_nr = PMM_PAGE_SIZE / sizeof(struct vfat_DirEntry_s);
697        val = 0;
698
699        // we are at the last entry in the page, looking for the next page
700        if (entry_index == (entries_nr - 1))
701        {
702                page2 = mapper_get_page(mapper, entry_index_page+1, MAPPER_SYNC_OP);
703
704                if(page2 == NULL)
705                {
706                        val = entry_index_page + 1;
707                        err = VFS_IO_ERR;
708                        goto UNLINK_IOERR;
709                }
710               
711                last_dir = (struct vfat_DirEntry_s*) ppm_page2addr(page2);
712        } 
713        else 
714        {
715                last_dir = &dir[1];
716        }
717
718        //TODO: set page up (here) when the cache can shrink
719
720        //TODO: negatif dentry should be handled in the upper layer
721        assert(dentry->d_inode.cid != CID_NULL);
722       
723        /*  For dirs, this function also check that it is empty.*/
724        err=vfs_unlink_inode(&dentry->d_inode);
725        if(err)
726                goto UNLINK_IOERR;
727
728        if(page2) page_lock(page2);
729        page_lock(page);
730
731        if (last_dir->DIR_Name[0] == 0x00)
732                dir->DIR_Name[0] = 0x00;
733        else
734                dir->DIR_Name[0] = 0xE5;
735
736        mapper->m_ops->set_page_dirty(page);
737        page_unlock(page);
738
739        if(page2) page_unlock(page2);
740
741#if VFAT_INSTRUMENT
742        wr_count ++;
743#endif
744
745UNLINK_IOERR:
746
747        if (err == VFS_IO_ERR)
748        {
749                printk(WARNING,"%s: unable to load page #%d of inode %d while removing node %s\n",
750                       __FUNCTION__,
751                       val,
752                       parent->i_number,
753                       dentry->d_name);
754        }
755        return err;
756}
757#endif
758
759const struct vfs_inode_op_s vfat_i_op =
760{
761        .init    = vfat_init_node,
762        .create  = vfat_create,
763        .icreate = vfat_icreate,
764        .lookup  = vfat_lookup,
765        .write   = vfat_write_node,
766        .release = vfat_release_node,
767        .unlink  = vfat_unlink_node,
768        .delete  = vfat_delete,
769        .stat    = vfat_stat_node,
770        .trunc   = NULL
771};
772
773VFS_COMPARE_DIRENT(vfat_compare)
774{
775        return strcasecmp(first, second);//TODO
776}
777
778const struct vfs_dentry_op_s vfat_d_op =
779{
780        .compare    = vfat_compare
781};
Note: See TracBrowser for help on using the repository browser.