xref: /kernel/liteos_a/fs/jffs2/src/vfs_jffs2.c (revision 0d163575)
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 */
61struct VnodeOps g_jffs2Vops;
62struct file_operations_vfs g_jffs2Fops;
63
64static LosMux g_jffs2FsLock;  /* lock for all jffs2 ops */
65
66static pthread_mutex_t g_jffs2NodeLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
67struct Vnode *g_jffs2PartList[CONFIG_MTD_PATTITION_NUM];
68
69static 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
87time_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
95void Jffs2NodeLock(void)
96{
97    (void)pthread_mutex_lock(&g_jffs2NodeLock);
98}
99
100void Jffs2NodeUnlock(void)
101{
102    (void)pthread_mutex_unlock(&g_jffs2NodeLock);
103}
104
105int 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;
154ERROR_WITH_VNODE:
155    return ret;
156}
157
158int 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
187int 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
238int 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
274int VfsJffs2Close(struct file *filep)
275{
276    return 0;
277}
278
279ssize_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
306ssize_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
333ssize_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
386ssize_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
482off_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_CUR:
494            filePos += offset;
495            break;
496
497        case SEEK_SET:
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
518int VfsJffs2Ioctl(struct file *filep, int cmd, unsigned long arg)
519{
520    PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
521    return -ENOSYS;
522}
523
524int 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
531int VfsJffs2Dup(const struct file *oldFile, struct file *newFile)
532{
533    PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
534    return -ENOSYS;
535}
536
537int VfsJffs2Opendir(struct Vnode *pVnode, struct fs_dirent_s *dir)
538{
539    dir->fd_int_offset = 0;
540    return 0;
541}
542
543int 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
566int VfsJffs2Seekdir(struct Vnode *pVnode, struct fs_dirent_s *dir, unsigned long offset)
567{
568    return 0;
569}
570
571int VfsJffs2Rewinddir(struct Vnode *pVnode, struct fs_dirent_s *dir)
572{
573    dir->fd_int_offset = 0;
574
575    return 0;
576}
577
578int VfsJffs2Closedir(struct Vnode *node, struct fs_dirent_s *dir)
579{
580    return 0;
581}
582
583int 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
621static 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
635int VfsJffs2Truncate(struct Vnode *pVnode, off_t len)
636{
637    int ret = Jffs2Truncate(pVnode, (unsigned int)len);
638    return ret;
639}
640
641int VfsJffs2Truncate64(struct Vnode *pVnode, off64_t len)
642{
643    int ret = Jffs2Truncate(pVnode, (unsigned int)len);
644    return ret;
645}
646
647int 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
669int 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
693int 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
729int 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
764ssize_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
793int 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
818int 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
854int 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
895int VfsJffs2Reclaim(struct Vnode *pVnode)
896{
897    return 0;
898}
899
900int 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
929int 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
939void Jffs2MutexDelete(void)
940{
941    (void)LOS_MuxDestroy(&g_jffs2FsLock);
942}
943
944const struct MountOps jffs_operations = {
945    .Mount = VfsJffs2Bind,
946    .Unmount = VfsJffs2Unbind,
947    .Statfs = VfsJffs2Statfs,
948};
949
950struct 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
973struct 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
983FSMAP_ENTRY(jffs_fsmap, "jffs2", jffs_operations, TRUE, TRUE);
984
985#endif
986