mirror of
https://github.com/openharmony/third_party_Linux_Kernel.git
synced 2026-07-01 22:44:03 -04:00
!1 轻内核VFS层重构,添加路径缓存
Merge pull request !1 from 野生毛霉君/noEmployeeNum_ChangeID_13306412_wangchenyang
This commit is contained in:
@@ -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)
|
||||
|
||||
+25
-30
@@ -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>
|
||||
|
||||
+96
-63
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
|
||||
+400
@@ -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
|
||||
|
||||
+18
-1
@@ -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
|
||||
|
||||
+18
-1
@@ -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
|
||||
}
|
||||
|
||||
+6
-6
@@ -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;
|
||||
}
|
||||
|
||||
+4
-23
@@ -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
|
||||
|
||||
+54
-24
@@ -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);
|
||||
|
||||
/* 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;
|
||||
|
||||
+1
-8
@@ -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 */
|
||||
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
+1
-2
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user