📄 fs-ecos.c
字号:
memcpy(nbuf, name, len);
nbuf[len] = '\0';
}
static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
struct _inode *d_inode = (struct _inode *) fp->f_data;
struct dirent *ent = (struct dirent *) uio->uio_iov[0].iov_base;
char *nbuf = ent->d_name;
int nlen = sizeof (ent->d_name) - 1;
off_t len = uio->uio_iov[0].iov_len;
struct jffs2_inode_info *f;
struct jffs2_sb_info *c;
struct _inode *inode = d_inode;
struct jffs2_full_dirent *fd;
unsigned long offset, curofs;
int found = 1;
if (len < sizeof (struct dirent))
return EINVAL;
D1(printk
(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino));
f = JFFS2_INODE_INFO(inode);
c = JFFS2_SB_INFO(inode->i_sb);
offset = fp->f_offset;
if (offset == 0) {
D1(printk
(KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino));
filldir(nbuf, nlen, ".", 1);
goto out;
}
if (offset == 1) {
filldir(nbuf, nlen, "..", 2);
goto out;
}
curofs = 1;
down(&f->sem);
for (fd = f->dents; fd; fd = fd->next) {
curofs++;
/* First loop: curofs = 2; offset = 2 */
if (curofs < offset) {
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));
offset++;
continue;
}
D2(printk
(KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset,
fd->name, fd->ino, fd->type));
filldir(nbuf, nlen, fd->name, strlen(fd->name));
goto out_sem;
}
/* Reached the end of the directory */
found = 0;
out_sem:
up(&f->sem);
out:
fp->f_offset = ++offset;
if (found) {
uio->uio_resid -= sizeof (struct dirent);
}
return ENOERR;
}
// -------------------------------------------------------------------------
// jffs2_fo_dirlseek()
// Seek directory to start.
static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence)
{
// Only allow SEEK_SET to zero
D2(printf("jffs2_fo_dirlseek\n"));
if (whence != SEEK_SET || *pos != 0)
return EINVAL;
*pos = fp->f_offset = 0;
return ENOERR;
}
//==========================================================================
//
// Called by JFFS2
// ===============
//
//
//==========================================================================
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_CACHE_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 */
}
static struct _inode *new_inode(struct super_block *sb)
{
// Only called in write.c jffs2_new_inode
// Always adds itself to inode cache
struct _inode *inode;
struct _inode *cached_inode;
inode = malloc(sizeof (struct _inode));
if (inode == NULL)
return 0;
D2(printf
("malloc new_inode %x ####################################\n",
inode));
memset(inode, 0, sizeof (struct _inode));
inode->i_sb = sb;
inode->i_ino = 1;
inode->i_count = 1;
inode->i_nlink = 1; // Let JFFS2 manage the link count
inode->i_size = 0;
inode->i_cache_next = NULL; // Newest inode, about to be cached
// Add to the icache
for (cached_inode = sb->s_root; cached_inode != NULL;
cached_inode = cached_inode->i_cache_next) {
if (cached_inode->i_cache_next == NULL) {
cached_inode->i_cache_next = inode; // Current last in cache points to newcomer
inode->i_cache_prev = cached_inode; // Newcomer points back to last
break;
}
}
return inode;
}
static struct _inode *ilookup(struct super_block *sb, cyg_uint32 ino)
{
struct _inode *inode = NULL;
D2(printf("ilookup\n"));
// Check for this inode in the cache
for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) {
if (inode->i_ino == ino) {
inode->i_count++;
break;
}
}
return inode;
}
struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino)
{
// Called in super.c jffs2_read_super, dir.c jffs2_lookup,
// and gc.c jffs2_garbage_collect_pass
// Must first check for cached inode
// If this fails let new_inode create one
struct _inode *inode;
int err;
D2(printf("jffs2_iget\n"));
inode = ilookup(sb, ino);
if (inode)
return inode;
// Not cached, so malloc it
inode = new_inode(sb);
if (inode == NULL)
return 0;
inode->i_ino = ino;
err = jffs2_read_inode(inode);
if (err) {
printf("jffs2_read_inode() failed\n");
jffs2_iput(inode);
inode = NULL;
return ERR_PTR(err);
}
return inode;
}
// -------------------------------------------------------------------------
// Decrement the reference count on an inode. If this makes the ref count
// zero, then this inode can be freed.
void jffs2_iput(struct _inode *i)
{
// Called in jffs2_find
// (and jffs2_open and jffs2_ops_mkdir?)
// super.c jffs2_read_super,
// and gc.c jffs2_garbage_collect_pass
recurse:
if (!i) {
printf("jffs2_iput() called with NULL inode\n");
// and let it fault...
}
i->i_count--;
if (i->i_count < 0)
BUG();
if (i->i_count)
return;
if (!i->i_nlink) {
struct _inode *parent;
// Remove from the icache linked list and free immediately
if (i->i_cache_prev)
i->i_cache_prev->i_cache_next = i->i_cache_next;
if (i->i_cache_next)
i->i_cache_next->i_cache_prev = i->i_cache_prev;
parent = i->i_parent;
jffs2_clear_inode(i);
memset(i, 0x5a, sizeof(*i));
free(i);
if (parent && parent != i) {
i = parent;
goto recurse;
}
} else {
// Evict some _other_ inode with i_count zero, leaving
// this latest one in the cache for a while
icache_evict(i->i_sb->s_root, i);
}
}
// -------------------------------------------------------------------------
// EOF jffs2.c
static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
{
memset(f, 0, sizeof(*f));
init_MUTEX_LOCKED(&f->sem);
}
static void jffs2_clear_inode (struct _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);
D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
jffs2_do_clear_inode(c, f);
}
/* 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 _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri)
{
struct _inode *inode;
struct super_block *sb = dir_i->i_sb;
struct jffs2_sb_info *c;
struct jffs2_inode_info *f;
int ret;
D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode));
c = JFFS2_SB_INFO(sb);
inode = new_inode(sb);
if (!inode)
return ERR_PTR(-ENOMEM);
f = JFFS2_INODE_INFO(inode);
jffs2_init_inode_info(f);
memset(ri, 0, sizeof(*ri));
/* Set OS-specific defaults for new inodes */
ri->uid = ri->gid = cpu_to_je16(0);
ri->mode = cpu_to_jemode(mode);
ret = jffs2_do_new_inode (c, f, mode, ri);
if (ret) {
jffs2_iput(inode);
return ERR_PTR(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 = cyg_timestamp();
ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
inode->i_size = 0;
return inode;
}
static int jffs2_read_inode (struct _inode *inode)
{
struct jffs2_inode_info *f;
struct jffs2_sb_info *c;
struct jffs2_raw_inode latest_node;
int ret;
D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
f = JFFS2_INODE_INFO(inode);
c = JFFS2_SB_INFO(inode->i_sb);
jffs2_init_inode_info(f);
ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
if (ret) {
up(&f->sem);
return 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->nlink;
up(&f->sem);
D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
return 0;
}
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
struct jffs2_inode_info *f)
{
jffs2_iput(OFNI_EDONI_2SFFJ(f));
}
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
int inum, int nlink)
{
struct _inode *inode;
struct jffs2_inode_cache *ic;
if (!nlink) {
/* 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) jffs2_iput() to happen.
There's a possibility that the final jffs2_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 jffs2_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) {
D1(printk(KERN_DEBUG "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) {
D1(printk(KERN_DEBUG "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 */
D1(printk(KERN_DEBUG "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 jffs2_iget() it, and if read_inode() is necessary that's OK.
*/
inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
if (IS_ERR(inode))
return (void *)inode;
}
return JFFS2_INODE_INFO(inode);
}
uint32_t jffs2_from_os_mode(uint32_t osmode)
{
uint32_t jmode = ((osmode & S_IRUSR)?00400:0) |
((osmode & S_IWUSR)?00200:0) |
((osmode & S_IXUSR)?00100:0) |
((osmode & S_IRGRP)?00040:0) |
((osmode & S_IWGRP)?00020:0) |
((osmode & S_IXGRP)?00010:0) |
((osmode & S_IROTH)?00004:0) |
((osmode & S_IWOTH)?00002:0) |
((osmode & S_IXOTH)?00001:0);
switch (osmode & S_IFMT) {
case S_IFSOCK:
return jmode | 0140000;
case S_IFLNK:
return jmode | 0120000;
case S_IFREG:
return jmode | 0100000;
case S_IFBLK:
return jmode | 0060000;
case S_IFDIR:
return jmode | 0040000;
case S_IFCHR:
return jmode | 0020000;
case S_IFIFO:
return jmode | 0010000;
case S_ISUID:
return jmode | 0004000;
case S_ISGID:
return jmode | 0002000;
#ifdef S_ISVTX
case S_ISVTX:
return jmode | 0001000;
#endif
}
printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode);
BUG();
return 0;
}
uint32_t jffs2_to_os_mode (uint32_t jmode)
{
uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) |
((jmode & 00200)?S_IWUSR:0) |
((jmode & 00100)?S_IXUSR:0) |
((jmode & 00040)?S_IRGRP:0) |
((jmode & 00020)?S_IWGRP:0) |
((jmode & 00010)?S_IXGRP:0) |
((jmode & 00004)?S_IROTH:0) |
((jmode & 00002)?S_IWOTH:0) |
((jmode & 00001)?S_IXOTH:0);
switch(jmode & 00170000) {
case 0140000:
return osmode | S_IFSOCK;
case 0120000:
return osmode | S_IFLNK;
case 0100000:
return osmode | S_IFREG;
case 0060000:
return osmode | S_IFBLK;
case 0040000:
return osmode | S_IFDIR;
case 0020000:
return osmode | S_IFCHR;
case 0010000:
return osmode | S_IFIFO;
case 0004000:
return osmode | S_ISUID;
case 0002000:
return osmode | S_ISGID;
#ifdef S_ISVTX
case 0001000:
return osmode | S_ISVTX;
#endif
}
printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode);
BUG();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -