提交 93aed1ac 编写于 作者: W wangchenyang 提交者: mamingshuai

Description:vfs refactoring

Feature or Bugfix:Feature
Binary Source:Huawei
PrivateCode(Yes/No):Yes

Change-Id: I175d2648bc6f9078c34de2c0a5c93fda10b86c47
ChangeID:13306412
上级 5f9f02f4
......@@ -28,11 +28,6 @@ struct jffs2_acl_header {
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
extern int jffs2_init_acl_pre(struct inode *, struct inode *, umode_t *);
extern int jffs2_init_acl_post(struct inode *);
#else
#define jffs2_get_acl (NULL)
......
......@@ -13,17 +13,14 @@
#include <linux/kernel.h>
#include <stdio.h>
#include "nodelist.h"
#include "porting.h"
#if defined(CYGOPT_FS_JFFS2_GCTHREAD)
#include "vfs_jffs2.h"
#include "mtd_partition.h"
#define GC_THREAD_FLAG_TRIG 1
#define GC_THREAD_FLAG_STOP 2
#define GC_THREAD_FLAG_HAS_EXIT 4
#endif
extern struct MtdNorDev *jffs2_dev_list;
static void jffs2_garbage_collect_thread(unsigned long data);
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
......@@ -31,27 +28,25 @@ void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
struct super_block *sb = OFNI_BS_2SFFJ(c);
/* Wake up the thread */
jffs2_dbg(1, "jffs2_garbage_collect_trigger\n");
jffs_event_send(&sb->s_gc_thread_flags, GC_THREAD_FLAG_TRIG);
LOS_EventWrite(&sb->s_gc_thread_flags, GC_THREAD_FLAG_TRIG);
}
extern struct MtdNorDev jffs_part[CONFIG_MTD_PATTITION_NUM];
/* This must only ever be called when no GC thread is currently running */
void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
{
struct super_block *sb = OFNI_BS_2SFFJ(c);
TSK_INIT_PARAM_S stGcTask;
struct super_block *sb = OFNI_BS_2SFFJ(c);
TSK_INIT_PARAM_S stGcTask;
if (c == NULL)
if (c == NULL)
return;
if (sb->s_root == NULL)
if (sb->s_root == NULL)
return;
jffs_event_create(&sb->s_gc_thread_flags);
LOS_EventInit(&sb->s_gc_thread_flags);
/* Start the thread. Doesn't matter if it fails -- it's only an
* optimisation anyway */
/* Start the thread. Doesn't matter if it fails -- it's only an
* optimisation anyway */
(void)memset_s(&stGcTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
stGcTask.pfnTaskEntry = (TSK_ENTRY_FUNC)jffs2_garbage_collect_thread;
......@@ -61,12 +56,12 @@ void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
#if (LOSCFG_KERNEL_SMP == YES)
unsigned int i;
for (i = 0; i < CONFIG_MTD_PATTITION_NUM; i++) {
if (sb->s_dev == &jffs_part[i])
if (sb->s_dev == &jffs2_dev_list[i])
break;
}
stGcTask.usCpuAffiMask = CPUID_TO_AFFI_MASK(i % LOSCFG_KERNEL_CORE_NUM);
#endif
stGcTask.usTaskPrio = CYGNUM_JFFS2_GC_THREAD_PRIORITY;
stGcTask.usTaskPrio = JFFS2_GC_THREAD_PRIORITY;
if (LOS_TaskCreate(&sb->s_gc_thread, &stGcTask))
JFFS2_ERROR("Create gc task failed!!!\n");
......@@ -74,24 +69,24 @@ void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
{
struct super_block *sb = OFNI_BS_2SFFJ(c);
struct super_block *sb = OFNI_BS_2SFFJ(c);
JFFS2_DEBUG("jffs2_stop_garbage_collect_thread\n");
/* Stop the thread and wait for it if necessary */
JFFS2_DEBUG("jffs2_stop_garbage_collect_thread\n");
/* Stop the thread and wait for it if necessary */
jffs_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP);
LOS_EventWrite(&sb->s_gc_thread_flags, GC_THREAD_FLAG_STOP);
JFFS2_DEBUG("jffs2_stop_garbage_collect_thread wait\n");
JFFS2_DEBUG("jffs2_stop_garbage_collect_thread wait\n");
(void)jffs_event_recv(&sb->s_gc_thread_flags,
(void)LOS_EventRead(&sb->s_gc_thread_flags,
GC_THREAD_FLAG_HAS_EXIT,
LOS_WAITMODE_OR | LOS_WAITMODE_CLR,
LOS_WAIT_FOREVER);
// Kill and free the resources ... this is safe due to the flag
// from the thread.
(void)LOS_TaskDelete(sb->s_gc_thread);
jffs_event_detach(&sb->s_gc_thread_flags);
// Kill and free the resources ... this is safe due to the flag
// from the thread.
(void)LOS_TaskDelete(sb->s_gc_thread);
(void)LOS_EventWrite(&sb->s_gc_thread_flags, 0xFFFFFFFF);
}
static void jffs2_garbage_collect_thread(unsigned long data)
......@@ -102,7 +97,7 @@ static void jffs2_garbage_collect_thread(unsigned long data)
jffs2_dbg(1, "jffs2_garbage_collect_thread START\n");
while(1) {
flag=jffs_event_recv(&sb->s_gc_thread_flags,
flag = LOS_EventRead(&sb->s_gc_thread_flags,
GC_THREAD_FLAG_TRIG | GC_THREAD_FLAG_STOP,
LOS_WAITMODE_OR | LOS_WAITMODE_CLR,
LOS_WAIT_FOREVER
......@@ -123,5 +118,5 @@ static void jffs2_garbage_collect_thread(unsigned long data)
jffs2_dbg(1, "jffs2: GC THREAD GC END\n");
}
JFFS2_DEBUG("jffs2_garbage_collect_thread EXIT\n");
jffs_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT);
LOS_EventWrite(&sb->s_gc_thread_flags, GC_THREAD_FLAG_HAS_EXIT);
}
......@@ -10,6 +10,7 @@
*
*/
#include <dirent.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
......
......@@ -10,25 +10,26 @@
*
*/
#include <dirent.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include "los_crc32.h"
#include "nodelist.h"
#include "vfs_jffs2.h"
#include "porting.h"
#include "jffs2_hash.h"
/* We keep the dirent list sorted in increasing order of name hash,
and we use the same hash function as the dentries. Makes this
nice and simple
*/
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen)
struct jffs2_inode *jffs2_lookup(struct jffs2_inode *dir_i, const unsigned char *d_name, int namelen)
{
struct jffs2_inode_info *dir_f;
struct jffs2_full_dirent *fd = NULL, *fd_list;
uint32_t ino = 0;
uint32_t hash = full_name_hash(d_name, namelen);
struct _inode *inode = NULL;
struct jffs2_inode *inode = NULL;
jffs2_dbg(1, "jffs2_lookup()\n");
......@@ -42,9 +43,9 @@ struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, i
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) {
if (fd_list->nhash == hash &&
(!fd || fd_list->version > fd->version) &&
strlen((char *)fd_list->name) == namelen&&
!strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
(!fd || fd_list->version > fd->version) &&
strlen((char *)fd_list->name) == namelen &&
!strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
fd = fd_list;
}
}
......@@ -60,17 +61,13 @@ struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, i
return inode;
}
/***********************************************************************/
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
int jffs2_unlink(struct jffs2_inode *dir_i, struct jffs2_inode *d_inode, const unsigned char *d_name)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
int ret;
uint32_t now = get_seconds();
uint32_t now = Jffs2CurSec();
ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
strlen((char *)d_name), dead_f, now);
......@@ -80,10 +77,8 @@ int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned ch
dir_i->i_mtime = dir_i->i_ctime = now;
return ret;
}
/***********************************************************************/
int jffs2_link(struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name)
int jffs2_link(struct jffs2_inode *old_d_inode, struct jffs2_inode *dir_i, const unsigned char *d_name)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
......@@ -96,9 +91,9 @@ int jffs2_link(struct _inode *old_d_inode, struct _inode *dir_i, const unsigned
type = (old_d_inode->i_mode & S_IFMT) >> 12;
if (!type) type = DT_REG;
now = get_seconds();
now = Jffs2CurSec();
ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, (const char *)d_name,
strlen((char *)d_name), now);
strlen((char *)d_name), now);
if (!ret) {
mutex_lock(&f->sem);
......@@ -109,13 +104,11 @@ int jffs2_link(struct _inode *old_d_inode, struct _inode *dir_i, const unsigned
return ret;
}
/***********************************************************************/
int jffs2_mkdir(struct _inode *dir_i, const unsigned char *d_name, int mode)
int jffs2_mkdir(struct jffs2_inode *dir_i, const unsigned char *d_name, int mode, struct jffs2_inode **new_i)
{
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
struct _inode *inode;
struct jffs2_inode *inode;
struct jffs2_raw_inode *ri;
struct jffs2_raw_dirent *rd;
struct jffs2_full_dnode *fn;
......@@ -152,7 +145,6 @@ int jffs2_mkdir(struct _inode *dir_i, const unsigned char *d_name, int mode)
}
f = JFFS2_INODE_INFO(inode);
/* but ic->pino_nlink is the parent ino# */
f->inocache->pino_nlink = dir_i->i_ino;
......@@ -203,7 +195,7 @@ int jffs2_mkdir(struct _inode *dir_i, const unsigned char *d_name, int mode)
rd->pino = cpu_to_je32(dir_i->i_ino);
rd->version = cpu_to_je32(++dir_f->highest_version);
rd->ino = cpu_to_je32(inode->i_ino);
rd->mctime = cpu_to_je32(get_seconds());
rd->mctime = cpu_to_je32(Jffs2CurSec());
rd->nsize = namelen;
rd->type = DT_DIR;
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
......@@ -232,82 +224,72 @@ int jffs2_mkdir(struct _inode *dir_i, const unsigned char *d_name, int mode)
mutex_unlock(&dir_f->sem);
jffs2_complete_reservation(c);
jffs2_iput(inode);
*new_i = inode;
return 0;
fail:
inode->i_nlink = 0;
jffs2_iput(inode);
inode->i_nlink = 0;
jffs2_iput(inode);
return ret;
}
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
int jffs2_rmdir (struct jffs2_inode *dir_i, struct jffs2_inode *d_inode, const unsigned char *d_name)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
struct jffs2_full_dirent *fd;
int ret;
uint32_t now = get_seconds();
uint32_t now = Jffs2CurSec();
for (fd = f->dents ; fd; fd = fd->next) {
if (fd->ino)
if (fd->ino) {
PRINT_ERR("%s-%d: ret=%d\n", __FUNCTION__, __LINE__, ENOTEMPTY);
return -ENOTEMPTY;
}
}
ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
strlen((char *)d_name), f, now);
if (!ret) {
strlen((char *)d_name), f, now);
if (f->inocache)
d_inode->i_nlink = f->inocache->pino_nlink;
if (!ret)
dir_i->i_mtime = dir_i->i_ctime = now;
}
return ret;
}
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
struct _inode *new_dir_i, const unsigned char *new_d_name)
int jffs2_rename (struct jffs2_inode *old_dir_i, struct jffs2_inode *d_inode, const unsigned char *old_d_name,
struct jffs2_inode *new_dir_i, const unsigned char *new_d_name)
{
int ret;
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
struct jffs2_inode_info *victim_f = NULL;
uint8_t type;
uint32_t now;
/* XXX: We probably ought to alloc enough space for
both nodes at the same time. Writing the new link,
then getting -ENOSPC, is quite bad :)
*/
/* Make a hard link */
/* XXX: This is ugly */
type = (d_inode->i_mode & S_IFMT) >> 12;
if (!type) type = DT_REG;
now = get_seconds();
now = Jffs2CurSec();
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
d_inode->i_ino, type,
(const char *)new_d_name, strlen((char *)new_d_name), now);
d_inode->i_ino, type,
(const char *)new_d_name, strlen((char *)new_d_name), now);
if (ret)
return ret;
if (victim_f) {
/* There was a victim. Kill it off nicely */
/* Don't oops if the victim was a dirent pointing to an
inode which didn't exist. */
if (victim_f->inocache) {
mutex_lock(&victim_f->sem);
victim_f->inocache->pino_nlink--;
mutex_unlock(&victim_f->sem);
}
/* If it was a directory we moved, and there was no victim,
increase i_nlink on its new parent */
if ((d_inode->i_mode & S_IFMT) == S_IFDIR) {
new_dir_i->i_nlink++;
}
/* Unlink the original */
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
(const char *)old_d_name, strlen((char *)old_d_name), NULL, now);
(const char *)old_d_name, strlen((char *)old_d_name), NULL, now);
/* We don't touch inode->i_nlink */
......@@ -332,15 +314,13 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
return 0;
}
/***********************************************************************/
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
struct _inode **new_i)
int jffs2_create(struct jffs2_inode *dir_i, const unsigned char *d_name, int mode,
struct jffs2_inode **new_i)
{
struct jffs2_raw_inode *ri;
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
struct _inode *inode;
struct jffs2_inode *inode;
int ret;
mode &= ~S_IFMT;
mode |= S_IFREG;
......@@ -385,4 +365,57 @@ int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink));
*new_i = inode;
return 0;
}
\ No newline at end of file
}
static __inline void fill_name(char *dst_name, int nlen, const unsigned char *name, int namlen)
{
int len = nlen < namlen ? nlen : namlen;
(void)memcpy_s(dst_name, nlen, name, len);
dst_name[len] = '\0';
}
int jffs2_readdir(struct jffs2_inode *inode, off_t *offset, off_t *int_off, struct dirent *ent)
{
struct jffs2_inode_info *f;
struct jffs2_full_dirent *fd;
off_t curofs = 0;
f = JFFS2_INODE_INFO(inode);
mutex_lock(&f->sem);
for (fd = f->dents; fd; fd = fd->next) {
if (curofs++ < *int_off) {
D2(printk
(KERN_DEBUG
"Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
fd->name, fd->ino, fd->type, curofs, offset));
continue;
}
if (!fd->ino) {
D2(printk (KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name));
(*int_off)++;
continue;
}
D2(printk
(KERN_DEBUG "%s-%d: Dirent %ld: \"%s\", ino #%u, type %d\n", __FUNCTION__, __LINE__, offset,
fd->name, fd->ino, fd->type));
fill_name(ent->d_name, sizeof(ent->d_name) - 1, fd->name, strlen((char *)fd->name));
ent->d_type = fd->type;
ent->d_off = ++(*offset);
ent->d_reclen = (uint16_t)sizeof(struct dirent);
(*int_off)++;
break;
}
mutex_unlock(&f->sem);
if (fd == NULL) {
D2(printk(KERN_DEBUG "reached the end of the directory\n"));
return ENOENT;
}
return ENOERR;
}
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
#include "los_vm_common.h"
#include "nodelist.h"
#include "vfs_jffs2.h"
static unsigned char gc_buffer[PAGE_SIZE]; //avoids malloc when user may be under memory pressure
unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
struct jffs2_inode_info *f,
unsigned long offset,
unsigned long *priv)
{
/* FIXME: This works only with one file system mounted at a time */
int ret;
ret = jffs2_read_inode_range(c, f, gc_buffer,
offset & ~(PAGE_SIZE-1), PAGE_SIZE);
if (ret)
return ERR_PTR(ret);
return gc_buffer;
}
void jffs2_gc_release_page(struct jffs2_sb_info *c,
unsigned char *ptr,
unsigned long *priv)
{
/* Do nothing */
}
......@@ -12,6 +12,341 @@
#include <linux/delay.h>
#include "nodelist.h"
#include "os-linux.h"
#include "los_crc32.h"
#include "jffs2_hash.h"
#include "capability_type.h"
#include "capability_api.h"
int jffs2_setattr (struct jffs2_inode *inode, struct IATTR *attr)
{
struct jffs2_full_dnode *old_metadata, *new_metadata;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode *ri;
unsigned int ivalid;
mode_t tmp_mode;
uint c_uid = OsCurrUserGet()->effUserID;
uint c_gid = OsCurrUserGet()->effGid;
uint32_t alloclen;
int ret;
int alloc_type = ALLOC_NORMAL;
jffs2_dbg(1, "%s(): ino #%lu\n", __func__, inode->i_ino);
ri = jffs2_alloc_raw_inode();
if (!ri) {
return -ENOMEM;
}
ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret) {
jffs2_free_raw_inode(ri);
return ret;
}
mutex_lock(&f->sem);
ivalid = attr->attr_chg_valid;
tmp_mode = inode->i_mode;
ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
ri->totlen = cpu_to_je32(sizeof(*ri));
ri->hdr_crc = cpu_to_je32(crc32(0, ri, (sizeof(struct jffs2_unknown_node)-4)));
ri->ino = cpu_to_je32(inode->i_ino);
ri->version = cpu_to_je32(++f->highest_version);
ri->uid = cpu_to_je16(inode->i_uid);
ri->gid = cpu_to_je16(inode->i_gid);
if (ivalid & CHG_UID) {
if (((c_uid != inode->i_uid) || (attr->attr_chg_uid != inode->i_uid)) && (!IsCapPermit(CAP_CHOWN))) {
jffs2_complete_reservation(c);
jffs2_free_raw_inode(ri);
mutex_unlock(&f->sem);
return -EPERM;
} else {
ri->uid = cpu_to_je16(attr->attr_chg_uid);
}
}
if (ivalid & CHG_GID) {
if (((c_gid != inode->i_gid) || (attr->attr_chg_gid != inode->i_gid)) && (!IsCapPermit(CAP_CHOWN))) {
jffs2_complete_reservation(c);
jffs2_free_raw_inode(ri);
mutex_unlock(&f->sem);
return -EPERM;
} else {
ri->gid = cpu_to_je16(attr->attr_chg_gid);
}
}
if (ivalid & CHG_MODE) {
if (!IsCapPermit(CAP_FOWNER) && (c_uid != inode->i_uid)) {
jffs2_complete_reservation(c);
jffs2_free_raw_inode(ri);
mutex_unlock(&f->sem);
return -EPERM;
} else {
attr->attr_chg_mode &= ~S_IFMT; // delete file type
tmp_mode &= S_IFMT;
tmp_mode = attr->attr_chg_mode | tmp_mode; // add old file type
}
}
ri->mode = cpu_to_jemode(tmp_mode);
ri->isize = cpu_to_je32((ivalid & CHG_SIZE) ? attr->attr_chg_size : inode->i_size);
ri->atime = cpu_to_je32(inode->i_atime);
ri->mtime = cpu_to_je32(Jffs2CurSec());
ri->ctime = cpu_to_je32(Jffs2CurSec());
ri->offset = cpu_to_je32(0);
ri->csize = ri->dsize = cpu_to_je32(0);
ri->compr = JFFS2_COMPR_NONE;
if (ivalid & CHG_SIZE && inode->i_size < attr->attr_chg_size) {
/* It's an extension. Make it a hole node */
ri->compr = JFFS2_COMPR_ZERO;
ri->dsize = cpu_to_je32(attr->attr_chg_size - inode->i_size);
ri->offset = cpu_to_je32(inode->i_size);
} else if (ivalid & CHG_SIZE && !attr->attr_chg_size) {
/* For truncate-to-zero, treat it as deletion because
it'll always be obsoleting all previous nodes */
alloc_type = ALLOC_DELETION;
}
ri->node_crc = cpu_to_je32(crc32(0, ri, (sizeof(*ri)-8)));
ri->data_crc = cpu_to_je32(0);
new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, alloc_type);
if (IS_ERR(new_metadata)) {
jffs2_complete_reservation(c);
jffs2_free_raw_inode(ri);
mutex_unlock(&f->sem);
return PTR_ERR(new_metadata);
}
/* It worked. Update the inode */
inode->i_atime = je32_to_cpu(ri->atime);
inode->i_ctime = je32_to_cpu(ri->ctime);
inode->i_mtime = je32_to_cpu(ri->mtime);
inode->i_mode = jemode_to_cpu(ri->mode);
inode->i_uid = je16_to_cpu(ri->uid);
inode->i_gid = je16_to_cpu(ri->gid);
old_metadata = f->metadata;
if (ivalid & CHG_SIZE && inode->i_size > attr->attr_chg_size)
jffs2_truncate_fragtree (c, &f->fragtree, attr->attr_chg_size);
if (ivalid & CHG_SIZE && inode->i_size < attr->attr_chg_size) {
jffs2_add_full_dnode_to_inode(c, f, new_metadata);
inode->i_size = attr->attr_chg_size;
f->metadata = NULL;
} else {
f->metadata = new_metadata;
}
if (old_metadata) {
jffs2_mark_node_obsolete(c, old_metadata->raw);
jffs2_free_full_dnode(old_metadata);
}
jffs2_free_raw_inode(ri);
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
/* We have to do the truncate_setsize() without f->sem held, since
some pages may be locked and waiting for it in readpage().
We are protected from a simultaneous write() extending i_size
back past iattr->ia_size, because do_truncate() holds the
generic inode semaphore. */
if (ivalid & CHG_SIZE && inode->i_size > attr->attr_chg_size) {
inode->i_size = attr->attr_chg_size; // truncate_setsize
}
return 0;
}
static void jffs2_clear_inode (struct jffs2_inode *inode)
{
/* We can forget about this inode for now - drop all
* the nodelists associated with it, etc.
*/
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
jffs2_do_clear_inode(c, f);
}
static struct jffs2_inode *ilookup(struct super_block *sb, uint32_t ino)
{
struct jffs2_inode *node = NULL;
if (sb->s_root == NULL) {
return NULL;
}
// Check for this inode in the cache
Jffs2NodeLock();
(void)Jffs2HashGet(&sb->s_node_hash_lock, &sb->s_node_hash[0], sb, ino, &node);
Jffs2NodeUnlock();
return node;
}
struct jffs2_inode *new_inode(struct super_block *sb)
{
struct jffs2_inode *inode = NULL;
inode = zalloc(sizeof (struct jffs2_inode));
if (inode == NULL)
return 0;
D2(PRINTK("malloc new_inode %x ####################################\n",
inode));
inode->i_sb = sb;
inode->i_ino = 1;
inode->i_nlink = 1; // Let JFFS2 manage the link count
inode->i_size = 0;
LOS_ListInit((&(inode->i_hashlist)));
return inode;
}
struct jffs2_inode *jffs2_iget(struct super_block *sb, uint32_t ino)
{
struct jffs2_inode_info *f;
struct jffs2_sb_info *c;
struct jffs2_raw_inode latest_node;
struct jffs2_inode *inode;
int ret;
Jffs2NodeLock();
inode = ilookup(sb, ino);
if (inode) {
Jffs2NodeUnlock();
return inode;
}
inode = new_inode(sb);
if (inode == NULL) {
Jffs2NodeUnlock();
return (struct jffs2_inode *)-ENOMEM;
}
inode->i_ino = ino;
f = JFFS2_INODE_INFO(inode);
c = JFFS2_SB_INFO(inode->i_sb);
(void)mutex_init(&f->sem);
(void)mutex_lock(&f->sem);
ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
if (ret) {
(void)mutex_unlock(&f->sem);
inode->i_nlink = 0;
free(inode);
Jffs2NodeUnlock();
return (struct jffs2_inode *)ret;
}
inode->i_mode = jemode_to_cpu(latest_node.mode);
inode->i_uid = je16_to_cpu(latest_node.uid);
inode->i_gid = je16_to_cpu(latest_node.gid);
inode->i_size = je32_to_cpu(latest_node.isize);
inode->i_atime = je32_to_cpu(latest_node.atime);
inode->i_mtime = je32_to_cpu(latest_node.mtime);
inode->i_ctime = je32_to_cpu(latest_node.ctime);
inode->i_nlink = f->inocache->pino_nlink;
(void)mutex_unlock(&f->sem);
(void)Jffs2HashInsert(&sb->s_node_hash_lock, &sb->s_node_hash[0], inode, ino);
jffs2_dbg(1, "jffs2_read_inode() returning\n");
Jffs2NodeUnlock();
return inode;
}
// -------------------------------------------------------------------------
// Decrement the reference count on an inode. If this makes the ref count
// zero, then this inode can be freed.
int jffs2_iput(struct jffs2_inode *i)
{
// Called in jffs2_find
// (and jffs2_open and jffs2_ops_mkdir?)
// super.c jffs2_fill_super,
// and gc.c jffs2_garbage_collect_pass
struct jffs2_inode_info *f = NULL;
Jffs2NodeLock();
if (!i || i->i_nlink) {
// and let it fault...
Jffs2NodeUnlock();
return -EBUSY;
}
jffs2_clear_inode(i);
f = JFFS2_INODE_INFO(i);
(void)mutex_destroy(&(f->sem));
(void)Jffs2HashRemove(&i->i_sb->s_node_hash_lock, i);
(void)memset_s(i, sizeof(*i), 0x5a, sizeof(*i));
free(i);
Jffs2NodeUnlock();
return 0;
}
/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
fill in the raw_inode while you're at it. */
struct jffs2_inode *jffs2_new_inode (struct jffs2_inode *dir_i, int mode, struct jffs2_raw_inode *ri)
{
struct jffs2_inode *inode;
struct super_block *sb = dir_i->i_sb;
struct jffs2_sb_info *c;
struct jffs2_inode_info *f;
int ret;
c = JFFS2_SB_INFO(sb);
Jffs2NodeLock();
inode = new_inode(sb);
if (!inode)
return (struct jffs2_inode *)-ENOMEM;
f = JFFS2_INODE_INFO(inode);
(void)mutex_init(&f->sem);
(void)mutex_lock(&f->sem);;
memset(ri, 0, sizeof(*ri));
/* Set OS-specific defaults for new inodes */
ri->uid = cpu_to_je16(OsCurrUserGet()->effUserID);
ri->gid = cpu_to_je16(OsCurrUserGet()->effGid);
ret = jffs2_do_new_inode (c, f, mode, ri);
if (ret) {
mutex_unlock(&(f->sem));
jffs2_clear_inode(inode);
(void)mutex_destroy(&(f->sem));
(void)memset_s(inode, sizeof(*inode), 0x6a, sizeof(*inode));
free(inode);
Jffs2NodeUnlock();
return (struct jffs2_inode *)ret;
}
inode->i_nlink = 1;
inode->i_ino = je32_to_cpu(ri->ino);
inode->i_mode = jemode_to_cpu(ri->mode);
inode->i_gid = je16_to_cpu(ri->gid);
inode->i_uid = je16_to_cpu(ri->uid);
inode->i_atime = inode->i_ctime = inode->i_mtime = Jffs2CurSec();
ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
inode->i_size = 0;
(void)Jffs2HashInsert(&sb->s_node_hash_lock, &sb->s_node_hash[0], inode, inode->i_ino);
Jffs2NodeUnlock();
return inode;
}
int calculate_inocache_hashsize(uint32_t flash_size)
{
......@@ -32,3 +367,68 @@ int calculate_inocache_hashsize(uint32_t flash_size)
return hashsize;
}
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
struct jffs2_inode_info *f)
{
struct jffs2_inode *node = OFNI_EDONI_2SFFJ(f);
jffs2_iput(node);
}
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
int inum, int unlinked)
{
struct jffs2_inode *inode;
struct jffs2_inode_cache *ic;
if (unlinked) {
/* The inode has zero nlink but its nodes weren't yet marked
obsolete. This has to be because we're still waiting for
the final (close() and) iput() to happen.
There's a possibility that the final iput() could have
happened while we were contemplating. In order to ensure
that we don't cause a new read_inode() (which would fail)
for the inode in question, we use ilookup() in this case
instead of iget().
The nlink can't _become_ zero at this point because we're
holding the alloc_sem, and jffs2_do_unlink() would also
need that while decrementing nlink on any inode.
*/
inode = ilookup(OFNI_BS_2SFFJ(c), inum);
if (!inode) {
jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n",
inum);
spin_lock(&c->inocache_lock);
ic = jffs2_get_ino_cache(c, inum);
if (!ic) {
jffs2_dbg(1, "Inode cache for ino #%u is gone\n",
inum);
spin_unlock(&c->inocache_lock);
return NULL;
}
if (ic->state != INO_STATE_CHECKEDABSENT) {
/* Wait for progress. Don't just loop */
jffs2_dbg(1, "Waiting for ino #%u in state %d\n",
ic->ino, ic->state);
sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
} else {
spin_unlock(&c->inocache_lock);
}
return NULL;
}
} else {
/* Inode has links to it still; they're not going away because
jffs2_do_unlink() would need the alloc_sem and we have it.
Just iget() it, and if read_inode() is necessary that's OK.
*/
inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
if (inode <= 0)
return (struct jffs2_inode_info *)inode;
}
return JFFS2_INODE_INFO(inode);
}
......@@ -442,9 +442,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
ret = 0;
goto release_sem;
}
ret = jffs2_garbage_collect_live(c, jeb, raw, f);
jffs2_gc_release_inode(c, f);
test_gcnode:
......
......@@ -13,6 +13,7 @@
#ifndef __LINUX_JFFS2_H__
#define __LINUX_JFFS2_H__
#include <linux/types.h>
#ifdef __cplusplus
#if __cplusplus
......
......@@ -55,7 +55,24 @@ struct jffs2_inode_info {
uint16_t flags;
uint8_t usercompr;
struct inode vfs_inode;
};
struct super_block;
struct jffs2_inode {
uint32_t i_ino;
mode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
gid_t i_gid;
time_t i_atime;
time_t i_mtime;
time_t i_ctime;
struct Vnode *i_vnode;
off_t i_size;
struct super_block *i_sb;
LOS_DL_LIST i_hashlist;
struct jffs2_inode_info jffs2_i;
};
#ifdef __cplusplus
......
......@@ -21,7 +21,7 @@
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/rwsem.h>
#include "jffs2_config.h"
#include "vfs_jffs2.h"
#include "mtd_dev.h"
#ifdef __cplusplus
......@@ -166,6 +166,23 @@ struct jffs2_sb_info {
void *os_priv;
};
struct super_block {
struct jffs2_sb_info jffs2_sb;
LIST_HEAD s_node_hash[JFFS2_NODE_HASH_BUCKETS];
LosMux s_node_hash_lock;
struct jffs2_inode *s_root;
unsigned long s_mount_count;
void *s_dev;
UINT32 s_lock; /* Lock the inode cache */
EVENT_CB_S s_gc_thread_flags; /* Communication with the gcthread */
unsigned int s_gc_thread;
};
#define JFFS2_SB_INFO(sb) (&(sb)->jffs2_sb)
#define OFNI_BS_2SFFJ(c) \
((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->jffs2_sb)) ) )
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -33,7 +33,7 @@ void jffs2_destroy_slab_caches(void)
struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
{
struct jffs2_full_dirent *ret;
ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL);
ret = zalloc(sizeof(struct jffs2_full_dirent) + namesize);
dbg_memalloc("%p\n", ret);
return ret;
}
......@@ -47,7 +47,7 @@ void jffs2_free_full_dirent(struct jffs2_full_dirent *x)
struct jffs2_full_dnode *jffs2_alloc_full_dnode(void)
{
struct jffs2_full_dnode *ret;
ret = malloc(sizeof(struct jffs2_full_dnode));
ret = zalloc(sizeof(struct jffs2_full_dnode));
dbg_memalloc("%p\n", ret);
return ret;
}
......@@ -61,7 +61,7 @@ void jffs2_free_full_dnode(struct jffs2_full_dnode *x)
struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void)
{
struct jffs2_raw_dirent *ret;
ret = malloc(sizeof(struct jffs2_raw_dirent));
ret = zalloc(sizeof(struct jffs2_raw_dirent));
dbg_memalloc("%p\n", ret);
return ret;
}
......@@ -75,7 +75,7 @@ void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x)
struct jffs2_raw_inode *jffs2_alloc_raw_inode(void)
{
struct jffs2_raw_inode *ret;
ret = malloc(sizeof(struct jffs2_raw_inode));
ret = zalloc(sizeof(struct jffs2_raw_inode));
dbg_memalloc("%p\n", ret);
return ret;
}
......@@ -89,7 +89,7 @@ void jffs2_free_raw_inode(struct jffs2_raw_inode *x)
struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void)
{
struct jffs2_tmp_dnode_info *ret;
ret = malloc(sizeof(struct jffs2_tmp_dnode_info));
ret = zalloc(sizeof(struct jffs2_tmp_dnode_info));
dbg_memalloc("%p\n",
ret);
return ret;
......@@ -183,7 +183,7 @@ void jffs2_free_node_frag(struct jffs2_node_frag *x)
struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
{
struct jffs2_inode_cache *ret;
ret = malloc(sizeof(struct jffs2_inode_cache));;
ret = zalloc(sizeof(struct jffs2_inode_cache));;
dbg_memalloc("%p\n", ret);
return ret;
}
......
......@@ -21,10 +21,8 @@
#include "xattr.h"
#include "acl.h"
#include "summary.h"
#include "jffs2_config.h"
#include "os-ecos.h"
#include "vfs_jffs2.h"
#include "os-linux.h"
#include "port/fcntl.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -32,26 +30,9 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
enum
{
DT_UNKNOWN = 0,
#define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1,
#define DT_FIFO DT_FIFO
DT_CHR = 2,
#define DT_CHR DT_CHR
DT_DIR = 4,
#define DT_DIR DT_DIR
DT_BLK = 6,
#define DT_BLK DT_BLK
DT_REG = 8,
#define DT_REG DT_REG
DT_LNK = 10,
#define DT_LNK DT_LNK
DT_SOCK = 12,
#define DT_SOCK DT_SOCK
DT_WHT = 14
#define DT_WHT DT_WHT
struct kvec {
void *iov_base;
long iov_len;
};
#define JFFS2_NATIVE_ENDIAN
......
......@@ -12,30 +12,57 @@
#ifndef __JFFS2_OS_LINUX_H__
#define __JFFS2_OS_LINUX_H__
#include <dirent.h>
#include "fs/fs.h"
#include "jffs2.h"
#include "jffs2_fs_sb.h"
/* jffs2 debug output opion */
#define CONFIG_JFFS2_FS_DEBUG 0 /* 1 or 2 */
/* jffs2 gc thread section */
#define JFFS2_GC_THREAD_PRIORITY 10 /* GC thread's priority */
/* zlib section*/
#define CONFIG_JFFS2_ZLIB
#define CONFIG_JFFS2_RTIME
#define CONFIG_JFFS2_RUBIN
/* JFFS2 uses Linux mode bits natively -- no need for conversion */
#define os_to_jffs2_mode(x) (x)
#define jffs2_to_os_mode(x) (x)
#ifndef BUG_ON
#define BUG_ON(x) do {if (unlikely(x)) BUG();} while (0)
#endif
struct kstatfs;
struct kvec;
#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
#define JFFS2_INODE_INFO(i) (&(i)->jffs2_i)
#define OFNI_EDONI_2SFFJ(f) \
((struct jffs2_inode *) (((char *)f) - ((char *)(&((struct jffs2_inode *)NULL)->jffs2_i))))
#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size)
#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime)
#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime)
#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime)
#define ITIME(sec) ((struct timespec){sec, 0})
#define I_SEC(tv) ((tv).tv_sec)
#define sleep_on_spinunlock(wq, sl) do {spin_unlock(sl); msleep(100);} while (0)
#ifdef CYGOPT_FS_JFFS2_WRITE
#define jffs2_is_readonly(c) (0)
#else
#define jffs2_is_readonly(c) (1)
#endif
#define SECTOR_ADDR(x) ( (((unsigned long)(x) / c->sector_size) * c->sector_size) )
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
#ifdef CONFIG_JFFS2_SUMMARY
#define jffs2_can_mark_obsolete(c) (0)
......@@ -70,6 +97,7 @@ struct kvec;
#define jffs2_dirty_trigger(c) do {} while (0)
#else /* NAND and/or ECC'd NOR support present */
/* current not support */
#define jffs2_is_writebuffered(c) (0)
......@@ -113,28 +141,26 @@ void jffs2_dirty_trigger(struct jffs2_sb_info *c);
#endif /* WRITEBUFFER */
/* background.c */
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
#endif
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
/* dir.c */
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, int namelen);
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, struct _inode **new_i);
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode);
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name);
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
struct _inode *new_dir_i, const unsigned char *new_d_name);
struct jffs2_inode *jffs2_lookup(struct jffs2_inode *dir_i, const unsigned char *name, int namelen);
int jffs2_create(struct jffs2_inode *dir_i, const unsigned char *d_name, int mode, struct jffs2_inode **new_i);
int jffs2_mkdir (struct jffs2_inode *dir_i, const unsigned char *d_name, int mode, struct jffs2_inode **new_i);
int jffs2_link (struct jffs2_inode *old_d_inode, struct jffs2_inode *dir_i, const unsigned char *d_name);
int jffs2_unlink(struct jffs2_inode *dir_i, struct jffs2_inode *d_inode, const unsigned char *d_name);
int jffs2_rmdir (struct jffs2_inode *dir_i, struct jffs2_inode *d_inode, const unsigned char *d_name);
int jffs2_rename (struct jffs2_inode *old_dir_i, struct jffs2_inode *d_inode, const unsigned char *old_d_name,
struct jffs2_inode *new_dir_i, const unsigned char *new_d_name);
int jffs2_readdir(struct jffs2_inode *inode, off_t *offset, off_t *int_off, struct dirent *ent);
/* fs.c */
struct _inode *jffs2_iget(struct super_block *sb, uint32_t ino);
void jffs2_iput(struct _inode * i);
void jffs2_evict_inode (struct inode *);
void jffs2_dirty_inode(struct inode *inode, int flags);
struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri);
int jffs2_setattr (struct jffs2_inode *inode, struct IATTR *attr);
struct jffs2_inode *jffs2_iget(struct super_block *sb, uint32_t ino);
int jffs2_iput(struct jffs2_inode * i);
struct jffs2_inode *jffs2_new_inode (struct jffs2_inode *dir_i, int mode, struct jffs2_raw_inode *ri);
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
struct jffs2_inode_info *f);
......@@ -160,6 +186,10 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
int jffs2_flash_direct_read(struct jffs2_sb_info *c, loff_t ofs, size_t len,
size_t *retlen, const char *buf);
#endif /* __JFFS2_OS_LINUX_H__ */
/* super.c */
int jffs2_fill_super(struct super_block *sb);
int jffs2_mount(int part_no, struct jffs2_inode **root_node);
int jffs2_umount(struct jffs2_inode *root_node);
#endif /* __JFFS2_OS_LINUX_H__ */
......@@ -1344,7 +1344,6 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
return -ENOMEM;
}
dbg_readinode("creating inocache for root inode\n");
memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
f->inocache->ino = f->inocache->pino_nlink = 1;
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
f->inocache->state = INO_STATE_READING;
......
......@@ -952,7 +952,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
pr_notice("%s(): allocation of inode cache failed\n", __func__);
return NULL;
}
memset(ic, 0, sizeof(*ic));
ic->ino = ino;
ic->nodes = (void *)ic;
......
......@@ -20,9 +20,8 @@
#define MAX_SUMMARY_SIZE 65536
#include <sys/uio.h>
#include "stdint.h"
#include <linux/types.h>
#include "jffs2.h"
#include "jffs2_fs_sb.h"
#define BLK_STATE_ALLFF 0
#define BLK_STATE_CLEAN 1
......@@ -39,12 +38,6 @@
/* Summary structures used on flash */
struct kvec {
void *iov_base;
long iov_len;
};
struct jffs2_sum_unknown_flash
{
jint16_t nodetype; /* node type */
......
/*
* 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;
}
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;
}
spinor_mtd = GetMtd("spinor");
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;
(void)FreeMtd(spinor_mtd);
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;
}
......@@ -9,6 +9,7 @@
*
*/
#include <dirent.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
......@@ -28,8 +29,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
return -ENOMEM;
}
memset(ic, 0, sizeof(*ic));
f->inocache = ic;
f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
......
......@@ -88,11 +88,6 @@ extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
char *buffer, size_t size);
extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
const char *buffer, size_t size, int flags);
extern const struct xattr_handler *jffs2_xattr_handlers[];
extern const struct xattr_handler jffs2_user_xattr_handler;
extern const struct xattr_handler jffs2_trusted_xattr_handler;
......@@ -122,8 +117,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
#endif /* CONFIG_JFFS2_FS_XATTR */
#ifdef CONFIG_JFFS2_FS_SECURITY
extern int jffs2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr);
extern const struct xattr_handler jffs2_security_xattr_handler;
#else
#define jffs2_init_security(inode,dir,qstr) (0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册