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