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