diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h index 451d425f021b3084027be502bf88fd7dbfc56e15..34d6aba2d68a4db611978de430d19a376767562e 100644 --- a/fs/jffs2/acl.h +++ b/fs/jffs2/acl.h @@ -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) diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index d087f0441e731bb2435248c8ae8f21b1d890a17c..2b7749e3261c85d781ad5b4246a0082585e33238 100755 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -13,17 +13,14 @@ #include #include #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); } diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index aa926f6802ff664d752ba622dbd779e2ddb75874..4580dfeec3ed13e306e50d4afa104d295a439140 100755 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -10,6 +10,7 @@ * */ +#include #include #include #include diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 38d0e2e8b2d4c1b91e88c519253eb7184a861ac7..80069e34325dda0f7c9ca9ee61b5debef79b8d78 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -10,25 +10,26 @@ * */ +#include #include #include #include #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; +} + diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c new file mode 100755 index 0000000000000000000000000000000000000000..c7b5011f0b8541577f4798e3b388cdef23b732fa --- /dev/null +++ b/fs/jffs2/file.c @@ -0,0 +1,42 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright © 2001-2007 Red Hat, Inc. + * Copyright © 2004-2010 David Woodhouse + * + * Created by David Woodhouse + * + * 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 */ +} + diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 29f236e16ca76eca70d0bf4a89f64a1a00ad3afa..d25e6f87352a58026c3e1938310a2687972fcdc8 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -12,6 +12,341 @@ #include #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); +} diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 686066aff46ddc5b41e98a4470765b0a32cafa99..36b5fe743111c2300975635a9f43e54ec57a9b77 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -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: diff --git a/fs/jffs2/jffs2.h b/fs/jffs2/jffs2.h index f9d334bcaae7901ffaf157c2b6c61691f6ea7d84..d4c76aa1d8b63b5a3e22813c0f7d05730685f586 100644 --- a/fs/jffs2/jffs2.h +++ b/fs/jffs2/jffs2.h @@ -13,6 +13,7 @@ #ifndef __LINUX_JFFS2_H__ #define __LINUX_JFFS2_H__ +#include #ifdef __cplusplus #if __cplusplus diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 787a922156288a96bf1cd811adea26321e703cb0..d574ed0e96f2668872845cdc8331901ad547fe52 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h @@ -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 diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 740701625f8029cb7a70a4721d9b262381da9748..409342025a6225b19f215f350360310d7c7b75a4 100755 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h @@ -21,7 +21,7 @@ #include #include #include -#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 } diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index b99857a16bca8b7401c3c7d03e24476684b91686..84ecc042eff1bc47c9cb8b0ec3aadb18025791f3 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -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; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 84d2d70301f967bf083d757ea6b4a3ff96dd55ff..1a6f3e91cf30c1087b8500e1a00b38624205e904 100755 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -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 diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 1a4fba7567626b3f4d53e2678789ce9493832b1b..261cf174f9d08e432d9389cb8fb196ddb75a8e13 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -12,30 +12,57 @@ #ifndef __JFFS2_OS_LINUX_H__ #define __JFFS2_OS_LINUX_H__ +#include +#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__ */ diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index aa81558f162c60d41b84f2c4770c7400d3767541..e12e2651a21e12f1ae60893e219e89a93720c2bc 100755 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -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; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index af7b29164c9aa5e9080c4ed38863debfd93a31d1..bcf83e8397f842a09cc243c3bb480896006441cb 100755 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -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; diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index f068df6b639f19e9c45f09d8a309851fc97c73e4..eaecd81e08add3bc8cea897e301d7226c87803d1 100755 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h @@ -20,9 +20,8 @@ #define MAX_SUMMARY_SIZE 65536 #include -#include "stdint.h" +#include #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 */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c new file mode 100755 index 0000000000000000000000000000000000000000..3c1ab446a138e6853b3f0b6cf72517bddb49204c --- /dev/null +++ b/fs/jffs2/super.c @@ -0,0 +1,189 @@ +/* + * 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; + } + 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; +} diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index f408b26f12ea534b8c09af3c4a1829796c34381d..3dfde623b279aa9fcb67a7a13570367c08a50b58 100755 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -9,6 +9,7 @@ * */ +#include #include #include #include @@ -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; diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 471e40ce8dd1fcc8724c48f883494e6b13ff0aab..bada5e4d25bcfee1aa5c82cd1a51e7636f802818 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -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)