• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "vfs_jffs2.h"
32 
33 #include "fcntl.h"
34 #include "sys/stat.h"
35 #include "sys/statfs.h"
36 #include "errno.h"
37 
38 #include "los_config.h"
39 #include "los_typedef.h"
40 #include "los_mux.h"
41 #include "los_tables.h"
42 #include "los_vm_filemap.h"
43 #include "los_crc32.h"
44 #include "capability_type.h"
45 #include "capability_api.h"
46 
47 #include "fs/dirent_fs.h"
48 #include "fs/fs.h"
49 #include "fs/driver.h"
50 #include "vnode.h"
51 #include "mtd_list.h"
52 #include "mtd_partition.h"
53 #include "jffs2_hash.h"
54 
55 #include "os-linux.h"
56 #include "jffs2/nodelist.h"
57 
58 #ifdef LOSCFG_FS_JFFS
59 
60 /* forward define */
61 struct VnodeOps g_jffs2Vops;
62 struct file_operations_vfs g_jffs2Fops;
63 
64 static LosMux g_jffs2FsLock;  /* lock for all jffs2 ops */
65 
66 static pthread_mutex_t g_jffs2NodeLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
67 struct Vnode *g_jffs2PartList[CONFIG_MTD_PATTITION_NUM];
68 
Jffs2SetVtype(struct jffs2_inode * node,struct Vnode * pVnode)69 static void Jffs2SetVtype(struct jffs2_inode *node, struct Vnode *pVnode)
70 {
71     switch (node->i_mode & S_IFMT) {
72         case S_IFREG:
73             pVnode->type = VNODE_TYPE_REG;
74             break;
75         case S_IFDIR:
76             pVnode->type = VNODE_TYPE_DIR;
77             break;
78         case S_IFLNK:
79             pVnode->type = VNODE_TYPE_LNK;
80             break;
81         default:
82             pVnode->type = VNODE_TYPE_UNKNOWN;
83             break;
84     }
85 }
86 
Jffs2CurSec(void)87 time_t Jffs2CurSec(void)
88 {
89     struct timeval tv;
90     if (gettimeofday(&tv, NULL))
91         return 0;
92     return (uint32_t)(tv.tv_sec);
93 }
94 
Jffs2NodeLock(void)95 void Jffs2NodeLock(void)
96 {
97     (void)pthread_mutex_lock(&g_jffs2NodeLock);
98 }
99 
Jffs2NodeUnlock(void)100 void Jffs2NodeUnlock(void)
101 {
102     (void)pthread_mutex_unlock(&g_jffs2NodeLock);
103 }
104 
VfsJffs2Bind(struct Mount * mnt,struct Vnode * blkDriver,const void * data)105 int VfsJffs2Bind(struct Mount *mnt, struct Vnode *blkDriver, const void *data)
106 {
107     int ret;
108     int partNo;
109     mtd_partition *p = NULL;
110     struct MtdDev *mtd = NULL;
111     struct Vnode *pv = NULL;
112     struct jffs2_inode *rootNode = NULL;
113 
114     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
115     p = (mtd_partition *)((struct drv_data *)blkDriver->data)->priv;
116     mtd = (struct MtdDev *)(p->mtd_info);
117 
118     /* find a empty mte in partition table */
119     if (mtd == NULL || mtd->type != MTD_NORFLASH) {
120         LOS_MuxUnlock(&g_jffs2FsLock);
121         return -EINVAL;
122     }
123 
124     partNo = p->patitionnum;
125 
126     ret = jffs2_mount(partNo, &rootNode, mnt->mountFlags);
127     if (ret != 0) {
128         LOS_MuxUnlock(&g_jffs2FsLock);
129         return ret;
130     }
131 
132     ret = VnodeAlloc(&g_jffs2Vops, &pv);
133     if (ret != 0) {
134         LOS_MuxUnlock(&g_jffs2FsLock);
135         goto ERROR_WITH_VNODE;
136     }
137     pv->type = VNODE_TYPE_DIR;
138     pv->data = (void *)rootNode;
139     pv->originMount = mnt;
140     pv->fop = &g_jffs2Fops;
141     mnt->data = p;
142     mnt->vnodeCovered = pv;
143     pv->uid = rootNode->i_uid;
144     pv->gid = rootNode->i_gid;
145     pv->mode = rootNode->i_mode;
146 
147     (void)VfsHashInsert(pv, rootNode->i_ino);
148 
149     g_jffs2PartList[partNo] = blkDriver;
150 
151     LOS_MuxUnlock(&g_jffs2FsLock);
152 
153     return 0;
154 ERROR_WITH_VNODE:
155     return ret;
156 }
157 
VfsJffs2Unbind(struct Mount * mnt,struct Vnode ** blkDriver)158 int VfsJffs2Unbind(struct Mount *mnt, struct Vnode **blkDriver)
159 {
160     int ret;
161     mtd_partition *p = NULL;
162     int partNo;
163 
164     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
165 
166     p = (mtd_partition *)mnt->data;
167     if (p == NULL) {
168         LOS_MuxUnlock(&g_jffs2FsLock);
169         return -EINVAL;
170     }
171 
172     partNo = p->patitionnum;
173     ret = jffs2_umount((struct jffs2_inode *)mnt->vnodeCovered->data);
174     if (ret) {
175         LOS_MuxUnlock(&g_jffs2FsLock);
176         return ret;
177     }
178 
179     free(p->mountpoint_name);
180     p->mountpoint_name = NULL;
181     *blkDriver = g_jffs2PartList[partNo];
182 
183     LOS_MuxUnlock(&g_jffs2FsLock);
184     return 0;
185 }
186 
VfsJffs2Lookup(struct Vnode * parentVnode,const char * path,int len,struct Vnode ** ppVnode)187 int VfsJffs2Lookup(struct Vnode *parentVnode, const char *path, int len, struct Vnode **ppVnode)
188 {
189     int ret;
190     struct Vnode *newVnode = NULL;
191     struct jffs2_inode *node = NULL;
192     struct jffs2_inode *parentNode = NULL;
193 
194     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
195 
196     parentNode = (struct jffs2_inode *)parentVnode->data;
197     node = jffs2_lookup(parentNode, (const unsigned char *)path, len);
198     if (!node) {
199         LOS_MuxUnlock(&g_jffs2FsLock);
200         return -ENOENT;
201     }
202 
203     (void)VfsHashGet(parentVnode->originMount, node->i_ino, &newVnode, NULL, NULL);
204     if (newVnode) {
205         if (newVnode->data == NULL) {
206             LOS_Panic("#####VfsHashGet error#####\n");
207         }
208         newVnode->parent = parentVnode;
209         *ppVnode = newVnode;
210         LOS_MuxUnlock(&g_jffs2FsLock);
211         return 0;
212     }
213     ret = VnodeAlloc(&g_jffs2Vops, &newVnode);
214     if (ret != 0) {
215         PRINT_ERR("%s-%d, ret: %x\n", __FUNCTION__, __LINE__, ret);
216         (void)jffs2_iput(node);
217         LOS_MuxUnlock(&g_jffs2FsLock);
218         return ret;
219     }
220 
221     Jffs2SetVtype(node, newVnode);
222     newVnode->fop = parentVnode->fop;
223     newVnode->data = node;
224     newVnode->parent = parentVnode;
225     newVnode->originMount = parentVnode->originMount;
226     newVnode->uid = node->i_uid;
227     newVnode->gid = node->i_gid;
228     newVnode->mode = node->i_mode;
229 
230     (void)VfsHashInsert(newVnode, node->i_ino);
231 
232     *ppVnode = newVnode;
233 
234     LOS_MuxUnlock(&g_jffs2FsLock);
235     return 0;
236 }
237 
VfsJffs2Create(struct Vnode * parentVnode,const char * path,int mode,struct Vnode ** ppVnode)238 int VfsJffs2Create(struct Vnode *parentVnode, const char *path, int mode, struct Vnode **ppVnode)
239 {
240     int ret;
241     struct jffs2_inode *newNode = NULL;
242     struct Vnode *newVnode = NULL;
243 
244     ret = VnodeAlloc(&g_jffs2Vops, &newVnode);
245     if (ret != 0) {
246         return -ENOMEM;
247     }
248 
249     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
250     ret = jffs2_create((struct jffs2_inode *)parentVnode->data, (const unsigned char *)path, mode, &newNode);
251     if (ret != 0) {
252         VnodeFree(newVnode);
253         LOS_MuxUnlock(&g_jffs2FsLock);
254         return ret;
255     }
256 
257     newVnode->type = VNODE_TYPE_REG;
258     newVnode->fop = parentVnode->fop;
259     newVnode->data = newNode;
260     newVnode->parent = parentVnode;
261     newVnode->originMount = parentVnode->originMount;
262     newVnode->uid = newNode->i_uid;
263     newVnode->gid = newNode->i_gid;
264     newVnode->mode = newNode->i_mode;
265 
266     (void)VfsHashInsert(newVnode, newNode->i_ino);
267 
268     *ppVnode = newVnode;
269 
270     LOS_MuxUnlock(&g_jffs2FsLock);
271     return 0;
272 }
273 
VfsJffs2Close(struct file * filep)274 int VfsJffs2Close(struct file *filep)
275 {
276     return 0;
277 }
278 
VfsJffs2ReadPage(struct Vnode * vnode,char * buffer,off_t off)279 ssize_t VfsJffs2ReadPage(struct Vnode *vnode, char *buffer, off_t off)
280 {
281     struct jffs2_inode *node = NULL;
282     struct jffs2_inode_info *f = NULL;
283     struct jffs2_sb_info *c = NULL;
284     int ret;
285 
286     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
287 
288     node = (struct jffs2_inode *)vnode->data;
289     f = JFFS2_INODE_INFO(node);
290     c = JFFS2_SB_INFO(node->i_sb);
291 
292     off_t pos = min(node->i_size, off);
293     ssize_t len = min(PAGE_SIZE, (node->i_size - pos));
294     ret = jffs2_read_inode_range(c, f, (unsigned char *)buffer, off, len);
295     if (ret) {
296         LOS_MuxUnlock(&g_jffs2FsLock);
297         return ret;
298     }
299     node->i_atime = Jffs2CurSec();
300 
301     LOS_MuxUnlock(&g_jffs2FsLock);
302 
303     return len;
304 }
305 
VfsJffs2Read(struct file * filep,char * buffer,size_t bufLen)306 ssize_t VfsJffs2Read(struct file *filep, char *buffer, size_t bufLen)
307 {
308     struct jffs2_inode *node = NULL;
309     struct jffs2_inode_info *f = NULL;
310     struct jffs2_sb_info *c = NULL;
311     int ret;
312 
313     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
314     node = (struct jffs2_inode *)filep->f_vnode->data;
315     f = JFFS2_INODE_INFO(node);
316     c = JFFS2_SB_INFO(node->i_sb);
317 
318     off_t pos = min(node->i_size, filep->f_pos);
319     off_t len = min(bufLen, (node->i_size - pos));
320     ret = jffs2_read_inode_range(c, f, (unsigned char *)buffer, filep->f_pos, len);
321     if (ret) {
322         LOS_MuxUnlock(&g_jffs2FsLock);
323         return ret;
324     }
325     node->i_atime = Jffs2CurSec();
326     filep->f_pos += len;
327 
328     LOS_MuxUnlock(&g_jffs2FsLock);
329 
330     return len;
331 }
332 
VfsJffs2WritePage(struct Vnode * vnode,char * buffer,off_t pos,size_t buflen)333 ssize_t VfsJffs2WritePage(struct Vnode *vnode, char *buffer, off_t pos, size_t buflen)
334 {
335     struct jffs2_inode *node = NULL;
336     struct jffs2_inode_info *f = NULL;
337     struct jffs2_sb_info *c = NULL;
338     struct jffs2_raw_inode ri = {0};
339     struct IATTR attr = {0};
340     int ret;
341     uint32_t writtenLen;
342 
343     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
344 
345     node = (struct jffs2_inode *)vnode->data;
346     f = JFFS2_INODE_INFO(node);
347     c = JFFS2_SB_INFO(node->i_sb);
348 
349     if (pos < 0) {
350         LOS_MuxUnlock(&g_jffs2FsLock);
351         return -EINVAL;
352     }
353 
354     ri.ino = cpu_to_je32(f->inocache->ino);
355     ri.mode = cpu_to_jemode(node->i_mode);
356     ri.uid = cpu_to_je16(node->i_uid);
357     ri.gid = cpu_to_je16(node->i_gid);
358     ri.atime = ri.ctime = ri.mtime = cpu_to_je32(Jffs2CurSec());
359 
360     if (pos > node->i_size) {
361         int err;
362         attr.attr_chg_valid = CHG_SIZE;
363         attr.attr_chg_size = pos;
364         err = jffs2_setattr(node, &attr);
365         if (err) {
366             LOS_MuxUnlock(&g_jffs2FsLock);
367             return err;
368         }
369     }
370     ri.isize = cpu_to_je32(node->i_size);
371 
372     ret = jffs2_write_inode_range(c, f, &ri, (unsigned char *)buffer, pos, buflen, &writtenLen);
373     if (ret) {
374         node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
375         LOS_MuxUnlock(&g_jffs2FsLock);
376         return ret;
377     }
378 
379     node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
380 
381     LOS_MuxUnlock(&g_jffs2FsLock);
382 
383     return (ssize_t)writtenLen;
384 }
385 
VfsJffs2Write(struct file * filep,const char * buffer,size_t bufLen)386 ssize_t VfsJffs2Write(struct file *filep, const char *buffer, size_t bufLen)
387 {
388     struct jffs2_inode *node = NULL;
389     struct jffs2_inode_info *f = NULL;
390     struct jffs2_sb_info *c = NULL;
391     struct jffs2_raw_inode ri = {0};
392     struct IATTR attr = {0};
393     int ret;
394     off_t pos;
395     uint32_t writtenLen;
396 
397     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
398 
399     node = (struct jffs2_inode *)filep->f_vnode->data;
400     f = JFFS2_INODE_INFO(node);
401     c = JFFS2_SB_INFO(node->i_sb);
402     pos = filep->f_pos;
403 
404 #ifdef LOSCFG_KERNEL_SMP
405     struct super_block *sb = node->i_sb;
406     UINT16 gcCpuMask = LOS_TaskCpuAffiGet(sb->s_gc_thread);
407     UINT32 curTaskId = LOS_CurTaskIDGet();
408     UINT16 curCpuMask = LOS_TaskCpuAffiGet(curTaskId);
409     if (curCpuMask != gcCpuMask) {
410         if (curCpuMask != LOSCFG_KERNEL_CPU_MASK) {
411             (void)LOS_TaskCpuAffiSet(sb->s_gc_thread, curCpuMask);
412         } else {
413             (void)LOS_TaskCpuAffiSet(curTaskId, gcCpuMask);
414         }
415     }
416 #endif
417     if (pos < 0) {
418         LOS_MuxUnlock(&g_jffs2FsLock);
419         return -EINVAL;
420     }
421 
422     ri.ino = cpu_to_je32(f->inocache->ino);
423     ri.mode = cpu_to_jemode(node->i_mode);
424     ri.uid = cpu_to_je16(node->i_uid);
425     ri.gid = cpu_to_je16(node->i_gid);
426     ri.atime = ri.ctime = ri.mtime = cpu_to_je32(Jffs2CurSec());
427 
428     if (pos > node->i_size) {
429         int err;
430         attr.attr_chg_valid = CHG_SIZE;
431         attr.attr_chg_size = pos;
432         err = jffs2_setattr(node, &attr);
433         if (err) {
434             LOS_MuxUnlock(&g_jffs2FsLock);
435             return err;
436         }
437     }
438     ri.isize = cpu_to_je32(node->i_size);
439 
440     ret = jffs2_write_inode_range(c, f, &ri, (unsigned char *)buffer, pos, bufLen, &writtenLen);
441     if (ret) {
442         pos += writtenLen;
443 
444         node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
445         if (pos > node->i_size)
446             node->i_size = pos;
447 
448         filep->f_pos = pos;
449 
450         LOS_MuxUnlock(&g_jffs2FsLock);
451 
452         return ret;
453     }
454 
455     if (writtenLen != bufLen) {
456         pos += writtenLen;
457 
458         node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
459         if (pos > node->i_size)
460             node->i_size = pos;
461 
462         filep->f_pos = pos;
463 
464         LOS_MuxUnlock(&g_jffs2FsLock);
465 
466         return -ENOSPC;
467     }
468 
469     pos += bufLen;
470 
471     node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
472     if (pos > node->i_size)
473         node->i_size = pos;
474 
475     filep->f_pos = pos;
476 
477     LOS_MuxUnlock(&g_jffs2FsLock);
478 
479     return writtenLen;
480 }
481 
VfsJffs2Seek(struct file * filep,off_t offset,int whence)482 off_t VfsJffs2Seek(struct file *filep, off_t offset, int whence)
483 {
484     struct jffs2_inode *node = NULL;
485     loff_t filePos;
486 
487     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
488 
489     node = (struct jffs2_inode *)filep->f_vnode->data;
490     filePos = filep->f_pos;
491 
492     switch (whence) {
493         case SEEK_SET:
494             filePos = offset;
495             break;
496 
497         case SEEK_CUR:
498             filePos += offset;
499             break;
500 
501         case SEEK_END:
502             filePos = node->i_size + offset;
503             break;
504 
505         default:
506             LOS_MuxUnlock(&g_jffs2FsLock);
507             return -EINVAL;
508     }
509 
510     LOS_MuxUnlock(&g_jffs2FsLock);
511 
512     if (filePos < 0)
513         return -EINVAL;
514 
515     return filePos;
516 }
517 
VfsJffs2Ioctl(struct file * filep,int cmd,unsigned long arg)518 int VfsJffs2Ioctl(struct file *filep, int cmd, unsigned long arg)
519 {
520     PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
521     return -ENOSYS;
522 }
523 
VfsJffs2Fsync(struct file * filep)524 int VfsJffs2Fsync(struct file *filep)
525 {
526     /* jffs2_write directly write to flash, sync is OK.
527         BUT after pagecache enabled, pages need to be flushed to flash */
528     return 0;
529 }
530 
VfsJffs2Dup(const struct file * oldFile,struct file * newFile)531 int VfsJffs2Dup(const struct file *oldFile, struct file *newFile)
532 {
533     PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
534     return -ENOSYS;
535 }
536 
VfsJffs2Opendir(struct Vnode * pVnode,struct fs_dirent_s * dir)537 int VfsJffs2Opendir(struct Vnode *pVnode, struct fs_dirent_s *dir)
538 {
539     dir->fd_int_offset = 0;
540     return 0;
541 }
542 
VfsJffs2Readdir(struct Vnode * pVnode,struct fs_dirent_s * dir)543 int VfsJffs2Readdir(struct Vnode *pVnode, struct fs_dirent_s *dir)
544 {
545     int ret;
546     int i = 0;
547 
548     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
549 
550     /* set jffs2_d */
551     while (i < dir->read_cnt) {
552         ret = jffs2_readdir((struct jffs2_inode *)pVnode->data, &dir->fd_position,
553                             &dir->fd_int_offset, &dir->fd_dir[i]);
554         if (ret) {
555             break;
556         }
557 
558         i++;
559     }
560 
561     LOS_MuxUnlock(&g_jffs2FsLock);
562 
563     return i;
564 }
565 
VfsJffs2Seekdir(struct Vnode * pVnode,struct fs_dirent_s * dir,unsigned long offset)566 int VfsJffs2Seekdir(struct Vnode *pVnode, struct fs_dirent_s *dir, unsigned long offset)
567 {
568     return 0;
569 }
570 
VfsJffs2Rewinddir(struct Vnode * pVnode,struct fs_dirent_s * dir)571 int VfsJffs2Rewinddir(struct Vnode *pVnode, struct fs_dirent_s *dir)
572 {
573     dir->fd_int_offset = 0;
574 
575     return 0;
576 }
577 
VfsJffs2Closedir(struct Vnode * node,struct fs_dirent_s * dir)578 int VfsJffs2Closedir(struct Vnode *node, struct fs_dirent_s *dir)
579 {
580     return 0;
581 }
582 
VfsJffs2Mkdir(struct Vnode * parentNode,const char * dirName,mode_t mode,struct Vnode ** ppVnode)583 int VfsJffs2Mkdir(struct Vnode *parentNode, const char *dirName, mode_t mode, struct Vnode **ppVnode)
584 {
585     int ret;
586     struct jffs2_inode *node = NULL;
587     struct Vnode *newVnode = NULL;
588 
589     ret = VnodeAlloc(&g_jffs2Vops, &newVnode);
590     if (ret != 0) {
591         return -ENOMEM;
592     }
593 
594     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
595 
596     ret = jffs2_mkdir((struct jffs2_inode *)parentNode->data, (const unsigned char *)dirName, mode, &node);
597     if (ret != 0) {
598         LOS_MuxUnlock(&g_jffs2FsLock);
599         VnodeFree(newVnode);
600         return ret;
601     }
602 
603     newVnode->type = VNODE_TYPE_DIR;
604     newVnode->fop = parentNode->fop;
605     newVnode->data = node;
606     newVnode->parent = parentNode;
607     newVnode->originMount = parentNode->originMount;
608     newVnode->uid = node->i_uid;
609     newVnode->gid = node->i_gid;
610     newVnode->mode = node->i_mode;
611 
612     *ppVnode = newVnode;
613 
614     (void)VfsHashInsert(newVnode, node->i_ino);
615 
616     LOS_MuxUnlock(&g_jffs2FsLock);
617 
618     return 0;
619 }
620 
Jffs2Truncate(struct Vnode * pVnode,unsigned int len)621 static int Jffs2Truncate(struct Vnode *pVnode, unsigned int len)
622 {
623     int ret;
624     struct IATTR attr = {0};
625 
626     attr.attr_chg_size = len;
627     attr.attr_chg_valid = CHG_SIZE;
628 
629     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
630     ret = jffs2_setattr((struct jffs2_inode *)pVnode->data, &attr);
631     LOS_MuxUnlock(&g_jffs2FsLock);
632     return ret;
633 }
634 
VfsJffs2Truncate(struct Vnode * pVnode,off_t len)635 int VfsJffs2Truncate(struct Vnode *pVnode, off_t len)
636 {
637     int ret = Jffs2Truncate(pVnode, (unsigned int)len);
638     return ret;
639 }
640 
VfsJffs2Truncate64(struct Vnode * pVnode,off64_t len)641 int VfsJffs2Truncate64(struct Vnode *pVnode, off64_t len)
642 {
643     int ret = Jffs2Truncate(pVnode, (unsigned int)len);
644     return ret;
645 }
646 
VfsJffs2Chattr(struct Vnode * pVnode,struct IATTR * attr)647 int VfsJffs2Chattr(struct Vnode *pVnode, struct IATTR *attr)
648 {
649     int ret;
650     struct jffs2_inode *node = NULL;
651 
652     if (pVnode == NULL) {
653         return -EINVAL;
654     }
655 
656     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
657 
658     node = pVnode->data;
659     ret = jffs2_setattr(node, attr);
660     if (ret == 0) {
661         pVnode->uid = node->i_uid;
662         pVnode->gid = node->i_gid;
663         pVnode->mode = node->i_mode;
664     }
665     LOS_MuxUnlock(&g_jffs2FsLock);
666     return ret;
667 }
668 
VfsJffs2Rmdir(struct Vnode * parentVnode,struct Vnode * targetVnode,const char * path)669 int VfsJffs2Rmdir(struct Vnode *parentVnode, struct Vnode *targetVnode, const char *path)
670 {
671     int ret;
672     struct jffs2_inode *parentInode = NULL;
673     struct jffs2_inode *targetInode = NULL;
674 
675     if (!parentVnode || !targetVnode) {
676         return -EINVAL;
677     }
678 
679     parentInode = (struct jffs2_inode *)parentVnode->data;
680     targetInode = (struct jffs2_inode *)targetVnode->data;
681 
682     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
683 
684     ret = jffs2_rmdir(parentInode, targetInode, (const unsigned char *)path);
685     if (ret == 0) {
686         (void)jffs2_iput(targetInode);
687     }
688 
689     LOS_MuxUnlock(&g_jffs2FsLock);
690     return ret;
691 }
692 
VfsJffs2Link(struct Vnode * oldVnode,struct Vnode * newParentVnode,struct Vnode ** newVnode,const char * newName)693 int VfsJffs2Link(struct Vnode *oldVnode, struct Vnode *newParentVnode, struct Vnode **newVnode, const char *newName)
694 {
695     int ret;
696     struct jffs2_inode *oldInode = oldVnode->data;
697     struct jffs2_inode *newParentInode = newParentVnode->data;
698     struct Vnode *pVnode = NULL;
699 
700     ret = VnodeAlloc(&g_jffs2Vops, &pVnode);
701     if (ret != 0) {
702         return -ENOMEM;
703     }
704 
705     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
706     ret = jffs2_link(oldInode, newParentInode, (const unsigned char *)newName);
707     if (ret != 0) {
708         LOS_MuxUnlock(&g_jffs2FsLock);
709         VnodeFree(pVnode);
710         return ret;
711     }
712 
713     pVnode->type = VNODE_TYPE_REG;
714     pVnode->fop = &g_jffs2Fops;
715     pVnode->parent = newParentVnode;
716     pVnode->originMount = newParentVnode->originMount;
717     pVnode->data = oldInode;
718     pVnode->uid = oldVnode->uid;
719     pVnode->gid = oldVnode->gid;
720     pVnode->mode = oldVnode->mode;
721 
722     *newVnode = pVnode;
723     (void)VfsHashInsert(*newVnode, oldInode->i_ino);
724 
725     LOS_MuxUnlock(&g_jffs2FsLock);
726     return ret;
727 }
728 
VfsJffs2Symlink(struct Vnode * parentVnode,struct Vnode ** newVnode,const char * path,const char * target)729 int VfsJffs2Symlink(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target)
730 {
731     int ret;
732     struct jffs2_inode *inode = NULL;
733     struct Vnode *pVnode = NULL;
734 
735     ret = VnodeAlloc(&g_jffs2Vops, &pVnode);
736     if (ret != 0) {
737         return -ENOMEM;
738     }
739 
740     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
741     ret = jffs2_symlink((struct jffs2_inode *)parentVnode->data, &inode, (const unsigned char *)path, target);
742     if (ret != 0) {
743         LOS_MuxUnlock(&g_jffs2FsLock);
744         VnodeFree(pVnode);
745         return ret;
746     }
747 
748     pVnode->type = VNODE_TYPE_LNK;
749     pVnode->fop = &g_jffs2Fops;
750     pVnode->parent = parentVnode;
751     pVnode->originMount = parentVnode->originMount;
752     pVnode->data = inode;
753     pVnode->uid = inode->i_uid;
754     pVnode->gid = inode->i_gid;
755     pVnode->mode = inode->i_mode;
756 
757     *newVnode = pVnode;
758     (void)VfsHashInsert(*newVnode, inode->i_ino);
759 
760     LOS_MuxUnlock(&g_jffs2FsLock);
761     return ret;
762 }
763 
VfsJffs2Readlink(struct Vnode * vnode,char * buffer,size_t bufLen)764 ssize_t VfsJffs2Readlink(struct Vnode *vnode, char *buffer, size_t bufLen)
765 {
766     struct jffs2_inode *inode = NULL;
767     struct jffs2_inode_info *f = NULL;
768     ssize_t targetLen;
769     ssize_t cnt;
770 
771     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
772 
773     inode = (struct jffs2_inode *)vnode->data;
774     f = JFFS2_INODE_INFO(inode);
775     targetLen = strlen((const char *)f->target);
776     if (bufLen == 0) {
777         LOS_MuxUnlock(&g_jffs2FsLock);
778         return 0;
779     }
780 
781     cnt = (bufLen - 1) < targetLen ? (bufLen - 1) : targetLen;
782     if (LOS_CopyFromKernel(buffer, bufLen, (const char *)f->target, cnt) != 0) {
783         LOS_MuxUnlock(&g_jffs2FsLock);
784         return -EFAULT;
785     }
786     buffer[cnt] = '\0';
787 
788     LOS_MuxUnlock(&g_jffs2FsLock);
789 
790     return cnt;
791 }
792 
VfsJffs2Unlink(struct Vnode * parentVnode,struct Vnode * targetVnode,const char * path)793 int VfsJffs2Unlink(struct Vnode *parentVnode, struct Vnode *targetVnode, const char *path)
794 {
795     int ret;
796     struct jffs2_inode *parentInode = NULL;
797     struct jffs2_inode *targetInode = NULL;
798 
799     if (!parentVnode || !targetVnode) {
800         PRINTK("%s-%d parentVnode=%x, targetVnode=%x\n", __FUNCTION__, __LINE__, parentVnode, targetVnode);
801         return -EINVAL;
802     }
803 
804     parentInode = (struct jffs2_inode *)parentVnode->data;
805     targetInode = (struct jffs2_inode *)targetVnode->data;
806 
807     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
808 
809     ret = jffs2_unlink(parentInode, targetInode, (const unsigned char *)path);
810     if (ret == 0) {
811         (void)jffs2_iput(targetInode);
812     }
813 
814     LOS_MuxUnlock(&g_jffs2FsLock);
815     return ret;
816 }
817 
VfsJffs2Rename(struct Vnode * fromVnode,struct Vnode * toParentVnode,const char * fromName,const char * toName)818 int VfsJffs2Rename(struct Vnode *fromVnode, struct Vnode *toParentVnode, const char *fromName, const char *toName)
819 {
820     int ret;
821     struct Vnode *fromParentVnode = NULL;
822     struct Vnode *toVnode = NULL;
823     struct jffs2_inode *fromNode = NULL;
824 
825     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
826     fromParentVnode = fromVnode->parent;
827 
828     ret = VfsJffs2Lookup(toParentVnode, toName, strlen(toName), &toVnode);
829     if (ret == 0) {
830         if (toVnode->type == VNODE_TYPE_DIR) {
831             ret = VfsJffs2Rmdir(toParentVnode, toVnode, (char *)toName);
832         } else {
833             ret = VfsJffs2Unlink(toParentVnode, toVnode, (char *)toName);
834         }
835         if (ret) {
836             PRINTK("%s-%d remove newname(%s) failed ret=%d\n", __FUNCTION__, __LINE__, toName, ret);
837             LOS_MuxUnlock(&g_jffs2FsLock);
838             return ret;
839         }
840     }
841     fromNode = (struct jffs2_inode *)fromVnode->data;
842     ret = jffs2_rename((struct jffs2_inode *)fromParentVnode->data, fromNode,
843         (const unsigned char *)fromName, (struct jffs2_inode *)toParentVnode->data, (const unsigned char *)toName);
844     fromVnode->parent = toParentVnode;
845     LOS_MuxUnlock(&g_jffs2FsLock);
846 
847     if (ret) {
848         return ret;
849     }
850 
851     return 0;
852 }
853 
VfsJffs2Stat(struct Vnode * pVnode,struct stat * buf)854 int VfsJffs2Stat(struct Vnode *pVnode, struct stat *buf)
855 {
856     struct jffs2_inode *node = NULL;
857 
858     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
859 
860     node = (struct jffs2_inode *)pVnode->data;
861     switch (node->i_mode & S_IFMT) {
862         case S_IFREG:
863         case S_IFDIR:
864         case S_IFLNK:
865             buf->st_mode = node->i_mode;
866             break;
867 
868         default:
869             buf->st_mode = DT_UNKNOWN;
870             break;
871     }
872 
873     buf->st_dev = 0;
874     buf->st_ino = node->i_ino;
875     buf->st_nlink = node->i_nlink;
876     buf->st_uid = node->i_uid;
877     buf->st_gid = node->i_gid;
878     buf->st_size = node->i_size;
879     buf->st_blksize = BLOCK_SIZE;
880     buf->st_blocks = buf->st_size / buf->st_blksize;
881     buf->st_atime = node->i_atime;
882     buf->st_mtime = node->i_mtime;
883     buf->st_ctime = node->i_ctime;
884 
885     /* Adapt to kstat member long tv_sec */
886     buf->__st_atim32.tv_sec = (long)node->i_atime;
887     buf->__st_mtim32.tv_sec = (long)node->i_mtime;
888     buf->__st_ctim32.tv_sec = (long)node->i_ctime;
889 
890     LOS_MuxUnlock(&g_jffs2FsLock);
891 
892     return 0;
893 }
894 
VfsJffs2Reclaim(struct Vnode * pVnode)895 int VfsJffs2Reclaim(struct Vnode *pVnode)
896 {
897     return 0;
898 }
899 
VfsJffs2Statfs(struct Mount * mnt,struct statfs * buf)900 int VfsJffs2Statfs(struct Mount *mnt, struct statfs *buf)
901 {
902     unsigned long freeSize;
903     struct jffs2_sb_info *c = NULL;
904     struct jffs2_inode *rootNode = NULL;
905 
906     LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
907 
908     rootNode = (struct jffs2_inode *)mnt->vnodeCovered->data;
909     c = JFFS2_SB_INFO(rootNode->i_sb);
910 
911     freeSize = c->free_size + c->dirty_size;
912     buf->f_type = JFFS2_SUPER_MAGIC;
913     buf->f_bsize = PAGE_SIZE;
914     buf->f_blocks = (((uint64_t)c->nr_blocks) * c->sector_size) / PAGE_SIZE;
915     buf->f_bfree = freeSize / PAGE_SIZE;
916     buf->f_bavail = buf->f_bfree;
917     buf->f_namelen = NAME_MAX;
918     buf->f_fsid.__val[0] = JFFS2_SUPER_MAGIC;
919     buf->f_fsid.__val[1] = 1;
920     buf->f_frsize = BLOCK_SIZE;
921     buf->f_files = 0;
922     buf->f_ffree = 0;
923     buf->f_flags = mnt->mountFlags;
924 
925     LOS_MuxUnlock(&g_jffs2FsLock);
926     return 0;
927 }
928 
Jffs2MutexCreate(void)929 int Jffs2MutexCreate(void)
930 {
931     if (LOS_MuxInit(&g_jffs2FsLock, NULL) != LOS_OK) {
932         PRINT_ERR("%s, LOS_MuxCreate failed\n", __FUNCTION__);
933         return -1;
934     } else {
935         return 0;
936     }
937 }
938 
Jffs2MutexDelete(void)939 void Jffs2MutexDelete(void)
940 {
941     (void)LOS_MuxDestroy(&g_jffs2FsLock);
942 }
943 
944 const struct MountOps jffs_operations = {
945     .Mount = VfsJffs2Bind,
946     .Unmount = VfsJffs2Unbind,
947     .Statfs = VfsJffs2Statfs,
948 };
949 
950 struct VnodeOps g_jffs2Vops = {
951     .Lookup = VfsJffs2Lookup,
952     .Create = VfsJffs2Create,
953     .ReadPage = VfsJffs2ReadPage,
954     .WritePage = VfsJffs2WritePage,
955     .Rename = VfsJffs2Rename,
956     .Mkdir = VfsJffs2Mkdir,
957     .Getattr = VfsJffs2Stat,
958     .Opendir = VfsJffs2Opendir,
959     .Readdir = VfsJffs2Readdir,
960     .Closedir = VfsJffs2Closedir,
961     .Rewinddir = VfsJffs2Rewinddir,
962     .Unlink = VfsJffs2Unlink,
963     .Rmdir = VfsJffs2Rmdir,
964     .Chattr = VfsJffs2Chattr,
965     .Reclaim = VfsJffs2Reclaim,
966     .Truncate = VfsJffs2Truncate,
967     .Truncate64 = VfsJffs2Truncate64,
968     .Link = VfsJffs2Link,
969     .Symlink = VfsJffs2Symlink,
970     .Readlink = VfsJffs2Readlink,
971 };
972 
973 struct file_operations_vfs g_jffs2Fops = {
974     .read = VfsJffs2Read,
975     .write = VfsJffs2Write,
976     .mmap = OsVfsFileMmap,
977     .seek = VfsJffs2Seek,
978     .close = VfsJffs2Close,
979     .fsync = VfsJffs2Fsync,
980 };
981 
982 
983 FSMAP_ENTRY(jffs_fsmap, "jffs2", jffs_operations, TRUE, TRUE);
984 
985 #endif
986