/* * JFFS2 -- Journalling Flash File System, Version 2. * * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * */ #include "jffs2.h" #include "nodelist.h" #include "jffs2_fs_sb.h" #include "mtd_dev.h" #include "mtd_partition.h" #include "compr.h" #include "jffs2_hash.h" static unsigned char jffs2_mounted_number = 0; /* a counter to track the number of jffs2 instances mounted */ struct MtdNorDev jffs2_dev_list[CONFIG_MTD_PATTITION_NUM]; /* * fill in the superblock */ int jffs2_fill_super(struct super_block *sb) { int ret; struct jffs2_sb_info *c; struct MtdNorDev *device; c = JFFS2_SB_INFO(sb); device = (struct MtdNorDev*)(sb->s_dev); (void)mutex_init(&c->alloc_sem); (void)mutex_init(&c->erase_free_sem); spin_lock_init(&c->erase_completion_lock); spin_lock_init(&c->inocache_lock); /* sector size is the erase block size */ c->sector_size = device->blockSize; c->flash_size = (device->blockEnd - device->blockStart + 1) * device->blockSize; c->cleanmarker_size = sizeof(struct jffs2_unknown_node); ret = jffs2_do_mount_fs(c); if (ret) { (void)mutex_destroy(&c->alloc_sem); (void)mutex_destroy(&c->erase_free_sem); return ret; } D1(printk(KERN_DEBUG "jffs2_fill_super(): Getting root inode\n")); sb->s_root = jffs2_iget(sb, 1); if (IS_ERR(sb->s_root)) { D1(printk(KERN_WARNING "get root inode failed\n")); ret = PTR_ERR(sb->s_root); sb->s_root = NULL; jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); free(c->blocks); (void)mutex_destroy(&c->alloc_sem); (void)mutex_destroy(&c->erase_free_sem); return ret; } return 0; } int jffs2_mount(int part_no, struct jffs2_inode **root_node) { struct super_block *sb = NULL; struct jffs2_sb_info *c = NULL; LOS_DL_LIST *part_head = NULL; struct MtdDev *spinor_mtd = NULL; mtd_partition *mtd_part = GetSpinorPartitionHead(); int ret; jffs2_dbg(1, "begin los_jffs2_mount:%d\n", part_no); sb = zalloc(sizeof(struct super_block)); if (sb == NULL) { return -ENOMEM; } ret = Jffs2HashInit(&sb->s_node_hash_lock, &sb->s_node_hash[0]); if (ret) { free(sb); return ret; } part_head = &(GetSpinorPartitionHead()->node_info); LOS_DL_LIST_FOR_EACH_ENTRY(mtd_part,part_head, mtd_partition, node_info) { if (mtd_part->patitionnum == part_no) break; } #ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7 spinor_mtd = GetMtd("spinor"); #else spinor_mtd = (struct MtdDev *)LOS_DL_LIST_ENTRY(part_head->pstNext, mtd_partition, node_info)->mtd_info; #endif if (spinor_mtd == NULL) { free(sb); return -EPERM; } jffs2_dev_list[part_no].blockEnd = mtd_part->end_block; jffs2_dev_list[part_no].blockSize = spinor_mtd->eraseSize; jffs2_dev_list[part_no].blockStart = mtd_part->start_block; #ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7 (void)FreeMtd(spinor_mtd); #endif sb->jffs2_sb.mtd = mtd_part->mtd_info; sb->s_dev = &jffs2_dev_list[part_no]; c = JFFS2_SB_INFO(sb); c->flash_size = (mtd_part->end_block - mtd_part->start_block + 1) * spinor_mtd->eraseSize; c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size); c->sector_size = spinor_mtd->eraseSize; jffs2_dbg(1, "C mtd_size:%d,mtd-erase:%d,blocks:%d,hashsize:%d\n", c->flash_size, c->sector_size, c->flash_size / c->sector_size, c->inocache_hashsize); c->inocache_list = zalloc(sizeof(struct jffs2_inode_cache *) * c->inocache_hashsize); if (c->inocache_list == NULL) { free(sb); return -ENOMEM; } if (jffs2_mounted_number++ == 0) { (void)jffs2_create_slab_caches(); // No error check, cannot fail (void)jffs2_compressors_init(); } ret = jffs2_fill_super(sb); if (ret) { if (--jffs2_mounted_number == 0) { jffs2_destroy_slab_caches(); (void)jffs2_compressors_exit(); } free(sb); free(c->inocache_list); c->inocache_list = NULL; return ret; } jffs2_start_garbage_collect_thread(c); sb->s_mount_count++; *root_node = sb->s_root; return 0; } int jffs2_umount(struct jffs2_inode *root_node) { struct super_block *sb = root_node->i_sb; struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); struct jffs2_full_dirent *fd, *next; D2(PRINTK("Jffs2Umount\n")); // Only really umount if this is the only mount if (sb->s_mount_count == 1) { jffs2_stop_garbage_collect_thread(c); // free directory entries for (fd = root_node->jffs2_i.dents; fd; fd = next) { next = fd->next; jffs2_free_full_dirent(fd); } free(root_node); // Clean up the super block and root_node inode jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); free(c->blocks); c->blocks = NULL; free(c->inocache_list); c->inocache_list = NULL; (void)Jffs2HashDeinit(&sb->s_node_hash_lock); (void)mutex_destroy(&c->alloc_sem); (void)mutex_destroy(&c->erase_free_sem); free(sb); // That's all folks. D2(PRINTK("Jffs2Umount No current mounts\n")); } else { sb->s_mount_count--; } if (--jffs2_mounted_number == 0) { jffs2_destroy_slab_caches(); (void)jffs2_compressors_exit(); } return 0; }