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

📄 fs-ecos.c

📁 带SD卡的LINUX根文件系统. 在ARM上应用
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * JFFS2 -- Journalling Flash File System, Version 2. * * Copyright (C) 2001, 2002 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.8 2003/01/21 18:13:01 dwmw2 Exp $ * */#include <linux/types.h>#include <linux/stat.h>#include <linux/kernel.h>#include "jffs2port.h"#include <linux/jffs2.h>#include <linux/jffs2_fs_sb.h>#include <linux/jffs2_fs_i.h>#include <linux/pagemap.h>#include "nodelist.h"#include <errno.h>#include <string.h>#include <cyg/io/io.h>#include <cyg/io/config_keys.h>#include <cyg/io/flash.h>//==========================================================================// 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);static 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);static 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);static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static 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);//==========================================================================// 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.FSTAB_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);// -------------------------------------------------------------------------// File operations.// This set of file operations are used for normal open files.static cyg_fileops jffs2_fileops = {	jffs2_fo_read,	jffs2_fo_write,	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 char read_write_buffer[PAGE_CACHE_SIZE];	//avoids malloc when user may be under memory pressurestatic char gc_buffer[PAGE_CACHE_SIZE];	//avoids malloc when user may be under memory pressure//==========================================================================// Directory operationsstruct jffs2_dirsearch {	struct inode *dir;	// directory to search	const char *path;	// path to follow	struct inode *node;	// Node found	const 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// -------------------------------------------------------------------------// dec_refcnt()// Decrment the reference count on an inode. If this makes the ref count// zero, then this inode can be freed.static int dec_refcnt(struct inode *node){	int err = ENOERR;	node->i_count--;	// In JFFS2 inode's are temporary in ram structures that are free'd when the usage i_count drops to 0	// The i_nlink however is managed by JFFS2 and is unrelated to usage	if (node->i_count == 0) {		// This inode is not in use, so delete it.		iput(node);	}	return err;}// 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 *cached_inode;	struct inode *next_inode;	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)	if (i == root_i) {		for (cached_inode = root_i; cached_inode != NULL;		     cached_inode = next_inode) {			next_inode = cached_inode->i_cache_next;			if (cached_inode->i_count == 0) {				cached_inode->i_cache_prev->i_cache_next = cached_inode->i_cache_next;	// Prveious entry points ahead of us				if (cached_inode->i_cache_next != NULL)					cached_inode->i_cache_next->i_cache_prev = cached_inode->i_cache_prev;	// Next entry points behind us				jffs2_clear_inode(cached_inode);				D2(printf				   ("free icache_evict inode %x $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n",				    cached_inode));				free(cached_inode);			}		}	}}//==========================================================================// Directory search// -------------------------------------------------------------------------// init_dirsearch()// Initialize a dirsearch object to start a searchstatic void init_dirsearch(jffs2_dirsearch * ds,			   struct inode *dir, const char *name){	D2(printf("init_dirsearch name = %s\n", name));	D2(printf("init_dirsearch dir = %x\n", dir));	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){	unsigned long hash;	struct qstr this;	unsigned int c;	const char *hashname;	struct inode *dir = ds->dir;	const char *name = ds->path;	const 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++;	// If we terminated on a NUL, set last flag.	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->node = ds->dir->i_parent;			if (ds->dir->i_count == 0) {				iput(ds->dir);	// This inode may be evicted				ds->dir = NULL;			}			return ENOERR;		case 1:			// Dot is consumed			D2(printf("find_entry found .\n"));			ds->node = ds->dir;			return ENOERR;		}	// Here we have the name and its length set up.	// Search the directory for a matching entry	hashname = name;	this.name = hashname;	c = *(const unsigned char *) hashname;	hash = init_name_hash();	do {		hashname++;		hash = partial_name_hash(c, hash);		c = *(const unsigned char *) hashname;	} while (c && (c != '/'));	this.len = hashname - (const char *) this.name;	this.hash = end_name_hash(hash);	D2(printf("find_entry for name = %s\n", ds->path));	d = jffs2_lookup(dir, &this);	D2(printf("find_entry got dir = %x\n", d));	if (d == NULL)		return ENOENT;	// The back path for dotdot to follow	d->i_parent = dir;	// 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.static 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')		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;		// every inode traversed in the find is temporary and should be free'd		//iput(d->dir);		// Update dirsearch object to search next directory.		d->dir = d->node;		d->path += d->namelen;		if (*(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;	struct inode *root_i;	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"));	root_i = iget(sb, 1);	if (is_bad_inode(root_i)) {		D1(printk(KERN_WARNING "get root inode failed\n"));		err = EIO;		goto out_nodes;	}	D1(printk(KERN_DEBUG "jffs2_read_super(): d_alloc_root()\n"));	sb->s_root = d_alloc_root(root_i);	if (!sb->s_root) {		err = ENOMEM;		goto out_root_i;	}	sb->s_blocksize = PAGE_CACHE_SIZE;	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;	sb->s_magic = JFFS2_SUPER_MAGIC;	return 0;      out_root_i:	iput(root_i);      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 mtab[], 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"));

⌨️ 快捷键说明

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