super.c 5.0 KB
Newer Older
W
wangchenyang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
/*
 * JFFS2 -- Journalling Flash File System, Version 2.
 *
 * Copyright © 2001-2007 Red Hat, Inc.
 *
 * Created by David Woodhouse <dwmw2@infradead.org>
 *
 * 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;
}

71
int jffs2_mount(int part_no, struct jffs2_inode **root_node, unsigned long mountflags)
W
wangchenyang 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
{
	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;
	}
97
#ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
W
wangchenyang 已提交
98
	spinor_mtd = GetMtd("spinor");
99 100 101
#else
	spinor_mtd = (struct MtdDev *)LOS_DL_LIST_ENTRY(part_head->pstNext, mtd_partition, node_info)->mtd_info;
#endif
W
wangchenyang 已提交
102 103 104 105 106 107 108
	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;
109
#ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
W
wangchenyang 已提交
110
	(void)FreeMtd(spinor_mtd);
111
#endif
W
wangchenyang 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
	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;
	}

146 147 148
	if (!(mountflags & MS_RDONLY)) {
		jffs2_start_garbage_collect_thread(c);
	}
W
wangchenyang 已提交
149

150
	sb->s_mount_flags = mountflags;
W
wangchenyang 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163
	*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
164
	if (!(sb->s_mount_flags & MS_RDONLY)) {
W
wangchenyang 已提交
165
		jffs2_stop_garbage_collect_thread(c);
166
	}
W
wangchenyang 已提交
167

168 169 170 171 172
	// free directory entries
	for (fd = root_node->jffs2_i.dents; fd; fd = next) {
		next = fd->next;
		jffs2_free_full_dirent(fd);
	}
W
wangchenyang 已提交
173

174
	free(root_node);
W
wangchenyang 已提交
175

176 177 178 179 180 181 182 183 184 185 186 187 188 189
	// 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"));
W
wangchenyang 已提交
190 191 192 193 194 195 196

	if (--jffs2_mounted_number == 0) {
		jffs2_destroy_slab_caches();
		(void)jffs2_compressors_exit();
	}
	return 0;
}