⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs-ecos.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * JFFS2 -- Journalling Flash File System, Version 2. * * Copyright (C) 2001-2003 Red Hat, Inc. * * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com> * Contributors: David Woodhouse, Nick Garnett, Richard Panton. * * For licensing information, see the file 'LICENCE' in this directory. * * $Id: fs-ecos.c,v 1.45 2005/07/30 15:25:45 lunn Exp $ * */#include <linux/kernel.h>#include "nodelist.h"#include <linux/pagemap.h>#include <linux/crc32.h>#include "compr.h"#include <errno.h>#include <string.h>#include <cyg/io/config_keys.h>#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) && defined (__ARM_ARCH_4__)#error This compiler is known to be broken. Please see:#error http://ecos.sourceware.org/ml/ecos-patches/2003-08/msg00006.html#endif//==========================================================================// Forward definitions// Filesystem operationsstatic int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte);static int jffs2_umount(cyg_mtab_entry * mte);static int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		      int mode, cyg_file * fte);#ifdef CYGOPT_FS_JFFS2_WRITEstatic int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir,			    const char *name);static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,			    const char *name1, cyg_dir dir2, const char *name2);static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,			  cyg_dir dir2, const char *name2, int type);#endifstatic int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,			 cyg_file * fte);static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		       cyg_dir * dir_out);static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		      struct stat *buf);static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,			 int key, void *buf, int len);static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,			 int key, void *buf, int len);// File operationsstatic int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);#ifdef CYGOPT_FS_JFFS2_WRITEstatic int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);#endifstatic int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,			  CYG_ADDRWORD data);static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode);static int jffs2_fo_close(struct CYG_FILE_TAG *fp);static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf);static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,			    int len);static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,			    int len);// Directory operationsstatic int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);static int jffs2_read_inode (struct _inode *inode);static void jffs2_clear_inode (struct _inode *inode);static int jffs2_truncate_file (struct _inode *inode);//==========================================================================// Filesystem table entries// -------------------------------------------------------------------------// Fstab entry.// This defines the entry in the filesystem table.// For simplicity we use _FILESYSTEM synchronization for all accesses since// we should never block in any filesystem operations.#ifdef CYGOPT_FS_JFFS2_WRITEFSTAB_ENTRY(jffs2_fste, "jffs2", 0,	    CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,	    jffs2_mount,	    jffs2_umount,	    jffs2_open,	    jffs2_ops_unlink,	    jffs2_ops_mkdir,	    jffs2_ops_rmdir,	    jffs2_ops_rename,	    jffs2_ops_link,	    jffs2_opendir,	    jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo);#elseFSTAB_ENTRY(jffs2_fste, "jffs2", 0,	    CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,	    jffs2_mount,	    jffs2_umount,	    jffs2_open,	    (cyg_fsop_unlink *)cyg_fileio_erofs,	    (cyg_fsop_mkdir *)cyg_fileio_erofs,	    (cyg_fsop_rmdir *)cyg_fileio_erofs,	    (cyg_fsop_rename *)cyg_fileio_erofs,	    (cyg_fsop_link *)cyg_fileio_erofs,	    jffs2_opendir,	    jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo);#endif// -------------------------------------------------------------------------// File operations.// This set of file operations are used for normal open files.static cyg_fileops jffs2_fileops = {	jffs2_fo_read,#ifdef CYGOPT_FS_JFFS2_WRITE	jffs2_fo_write,#else	(cyg_fileop_write *) cyg_fileio_erofs,#endif	jffs2_fo_lseek,	jffs2_fo_ioctl,	cyg_fileio_seltrue,	jffs2_fo_fsync,	jffs2_fo_close,	jffs2_fo_fstat,	jffs2_fo_getinfo,	jffs2_fo_setinfo};// -------------------------------------------------------------------------// Directory file operations.// This set of operations are used for open directories. Most entries// point to error-returning stub functions. Only the read, lseek and// close entries are functional.static cyg_fileops jffs2_dirops = {	jffs2_fo_dirread,	(cyg_fileop_write *) cyg_fileio_enosys,	jffs2_fo_dirlseek,	(cyg_fileop_ioctl *) cyg_fileio_enosys,	cyg_fileio_seltrue,	(cyg_fileop_fsync *) cyg_fileio_enosys,	jffs2_fo_close,	(cyg_fileop_fstat *) cyg_fileio_enosys,	(cyg_fileop_getinfo *) cyg_fileio_enosys,	(cyg_fileop_setinfo *) cyg_fileio_enosys};//==========================================================================// STATIC VARIABLES !!!static unsigned char gc_buffer[PAGE_CACHE_SIZE];	//avoids malloc when user may be under memory pressurestatic unsigned char n_fs_mounted = 0;  // a counter to track the number of jffs2 instances mounted//==========================================================================// Directory operationsstruct jffs2_dirsearch {	struct _inode *dir;	    // directory to search	const unsigned char *path;  // path to follow	struct _inode *node;	    // Node found	const unsigned char *name;  // last name fragment used	int namelen;		    // name fragment length	cyg_bool last;		    // last name in path?};typedef struct jffs2_dirsearch jffs2_dirsearch;//==========================================================================// Ref count and nlink management// FIXME: This seems like real cruft. Wouldn't it be better just to do the// right thing?static void icache_evict(struct _inode *root_i, struct _inode *i){	struct _inode *this = root_i, *next; restart:	D2(printf("icache_evict\n"));	// If this is an absolute search path from the root,	// remove all cached inodes with i_count of zero (these are only 	// held where needed for dotdot filepaths)	while (this) {		next = this->i_cache_next;		if (this != i && this->i_count == 0) {			struct _inode *parent = this->i_parent;			if (this->i_cache_next)				this->i_cache_next->i_cache_prev = this->i_cache_prev;			if (this->i_cache_prev)				this->i_cache_prev->i_cache_next = this->i_cache_next;			jffs2_clear_inode(this);			memset(this, 0x5a, sizeof(*this));			free(this);			if (parent && parent != this) {				parent->i_count--;				this = root_i;				goto restart;			}		}		this = next;	}}//==========================================================================// Directory search// -------------------------------------------------------------------------// init_dirsearch()// Initialize a dirsearch object to start a searchstatic void init_dirsearch(jffs2_dirsearch * ds,			   struct _inode *dir, const unsigned char *name){	D2(printf("init_dirsearch name = %s\n", name));	D2(printf("init_dirsearch dir = %x\n", dir));	dir->i_count++;	ds->dir = dir;	ds->path = name;	ds->node = dir;	ds->name = name;	ds->namelen = 0;	ds->last = false;}// -------------------------------------------------------------------------// find_entry()// Search a single directory for the next name in a path and update the// dirsearch object appropriately.static int find_entry(jffs2_dirsearch * ds){	struct _inode *dir = ds->dir;	const unsigned char *name = ds->path;	const unsigned char *n = name;	char namelen = 0;	struct _inode *d;	D2(printf("find_entry\n"));	// check that we really have a directory	if (!S_ISDIR(dir->i_mode))		return ENOTDIR;	// Isolate the next element of the path name. 	while (*n != '\0' && *n != '/')		n++, namelen++;	// Check if this is the last path element.	while( *n == '/') n++;	if (*n == '\0')		ds->last = true;	// update name in dirsearch object	ds->name = name;	ds->namelen = namelen;	if (name[0] == '.')		switch (namelen) {		default:			break;		case 2:			// Dot followed by not Dot, treat as any other name 			if (name[1] != '.')				break;			// Dot Dot 			// Move back up the search path			D2(printf("find_entry found ..\n"));			ds->dir = ds->node;			ds->node = ds->dir->i_parent;			ds->node->i_count++;			return ENOERR;		case 1:			// Dot is consumed			D2(printf("find_entry found .\n"));			ds->node = ds->dir;			ds->dir->i_count++;			return ENOERR;		}	// Here we have the name and its length set up.	// Search the directory for a matching entry	D2(printf("find_entry for name = %s\n", ds->path));	d = jffs2_lookup(dir, name, namelen);	D2(printf("find_entry got dir = %x\n", d));	if (d == NULL)		return ENOENT;	if (IS_ERR(d))		return -PTR_ERR(d);	// If it's a new directory inode, increase refcount on its parent	if (S_ISDIR(d->i_mode) && !d->i_parent) {		d->i_parent = dir;		dir->i_count++;	}	// pass back the node we have found	ds->node = d;	return ENOERR;}// -------------------------------------------------------------------------// jffs2_find()// Main interface to directory search code. This is used in all file// level operations to locate the object named by the pathname.// Returns with use count incremented on both the sought object and // the directory it was found instatic int jffs2_find(jffs2_dirsearch * d){	int err;	D2(printf("jffs2_find for path =%s\n", d->path));	// Short circuit empty paths	if (*(d->path) == '\0') {		d->node->i_count++;		return ENOERR;	}	// iterate down directory tree until we find the object	// we want.	for (;;) {		err = find_entry(d);		if (err != ENOERR)			return err;		if (d->last)			return ENOERR;		/* We're done with it, although it we found a subdir that		   will have caused the refcount to have been increased */		jffs2_iput(d->dir);		// Update dirsearch object to search next directory.		d->dir = d->node;		d->path += d->namelen;		while (*(d->path) == '/')			d->path++;	// skip dirname separators	}}//==========================================================================// Pathconf support// This function provides support for pathconf() and fpathconf().static int jffs2_pathconf(struct _inode *node, struct cyg_pathconf_info *info){	int err = ENOERR;	D2(printf("jffs2_pathconf\n"));	switch (info->name) {	case _PC_LINK_MAX:		info->value = LINK_MAX;		break;	case _PC_MAX_CANON:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_MAX_INPUT:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_NAME_MAX:		info->value = NAME_MAX;		break;	case _PC_PATH_MAX:		info->value = PATH_MAX;		break;	case _PC_PIPE_BUF:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_ASYNC_IO:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_CHOWN_RESTRICTED:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_NO_TRUNC:		info->value = 0;		break;	case _PC_PRIO_IO:		info->value = 0;		break;	case _PC_SYNC_IO:		info->value = 0;		break;	case _PC_VDISABLE:		info->value = -1;	// not supported		err = EINVAL;		break;	default:		err = EINVAL;		break;	}	return err;}//==========================================================================// Filesystem operations// -------------------------------------------------------------------------// jffs2_mount()// Process a mount request. This mainly creates a root for the// filesystem.static int jffs2_read_super(struct super_block *sb){	struct jffs2_sb_info *c;	Cyg_ErrNo err;	cyg_uint32 len;	cyg_io_flash_getconfig_devsize_t ds;	cyg_io_flash_getconfig_blocksize_t bs;	D1(printk(KERN_DEBUG "jffs2: read_super\n"));	c = JFFS2_SB_INFO(sb);	len = sizeof (ds);	err = cyg_io_get_config(sb->s_dev,				CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);	if (err != ENOERR) {		D1(printf		   ("jffs2: cyg_io_get_config failed to get dev size: %d\n",		    err));		return err;	}	len = sizeof (bs);	bs.offset = 0;	err = cyg_io_get_config(sb->s_dev,				CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE, &bs, &len);	if (err != ENOERR) {		D1(printf		   ("jffs2: cyg_io_get_config failed to get block size: %d\n",		    err));		return err;	}	c->sector_size = bs.block_size;	c->flash_size = ds.dev_size;	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);	err = jffs2_do_mount_fs(c);	if (err)		return -err;	D1(printk(KERN_DEBUG "jffs2_read_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"));		err = PTR_ERR(sb->s_root);		sb->s_root = NULL;		goto out_nodes;	}	return 0;      out_nodes:	jffs2_free_ino_caches(c);	jffs2_free_raw_node_refs(c);	free(c->blocks);	return err;}static int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte){	extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end;	struct super_block *jffs2_sb = NULL;	struct jffs2_sb_info *c;	cyg_mtab_entry *m;	cyg_io_handle_t t;	Cyg_ErrNo err;	D2(printf("jffs2_mount\n"));	err = cyg_io_lookup(mte->devname, &t);	if (err != ENOERR)		return -err;	// Iterate through the mount table to see if we're mounted	// FIXME: this should be done better - perhaps if the superblock	// can be stored as an inode in the icache.	for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) {		// stop if there are more than the configured maximum		if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {			m = &cyg_mtab_end;			break;		}		if (m->valid && strcmp(m->fsname, "jffs2") == 0 &&		    strcmp(m->devname, mte->devname) == 0) {			jffs2_sb = (struct super_block *) m->data;		}	}	if (jffs2_sb == NULL) {		jffs2_sb = malloc(sizeof (struct super_block));		if (jffs2_sb == NULL)			return ENOMEM;		c = JFFS2_SB_INFO(jffs2_sb);		memset(jffs2_sb, 0, sizeof (struct super_block));		jffs2_sb->s_dev = t;		c->inocache_list = malloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);		if (!c->inocache_list) {			free(jffs2_sb);			return ENOMEM;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -