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

📄 inode1.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * JFFS -- Journalling Flash File System, Linux implementation.
 *
 * Copyright (C) 1999, 2000  Finn Hakansson, Axis Communications, Inc.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * $Id: inode.c,v 1.71 2000/01/31 11:26:46 finn Exp $
 *
 */

/* inode.c -- Contains the code that is called from the VFS.  */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/malloc.h>
#include <linux/jffs.h>
#include <linux/fs.h>
#include <linux/locks.h>
#include <linux/sched.h>
#include <linux/ioctl.h>
#include <linux/stat.h>
#include <linux/blkdev.h>
#include <asm/byteorder.h>
#include "jffs_fm.h"
#include "intrep.h"

#if defined(CONFIG_JFFS_FS_VERBOSE) && CONFIG_JFFS_FS_VERBOSE
#define D(x) x
#else
#define D(x)
#endif
#define D1(x)
#define D2(x)
#define D3(x)
#define ASSERT(x) x

static int jffs_remove(struct inode *dir, const char *name,
		       int len, int type, int must_iput);

static struct super_operations jffs_ops;
static struct file_operations jffs_file_operations;
static struct inode_operations jffs_file_inode_operations;
static struct file_operations jffs_dir_operations;
static struct inode_operations jffs_dir_inode_operations;
static struct inode_operations jffs_symlink_inode_operations;


/* Called by the VFS at mount time to initialize the whole file system.  */
static struct super_block *
jffs_read_super(struct super_block *sb, void *data, int silent)
{
	kdev_t dev = sb->s_dev;

	printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
	       kdevname(dev));

	MOD_INC_USE_COUNT;
	lock_super(sb);
	set_blocksize(dev, BLOCK_SIZE);
	sb->s_blocksize = BLOCK_SIZE;
	sb->s_blocksize_bits = BLOCK_SIZE_BITS;
	sb->u.generic_sbp = (void *) 0;

	/* Build the file system.  */
	if (jffs_build_fs(sb) < 0) {
		goto jffs_sb_err1;
	}
	sb->s_magic = JFFS_MAGIC_SB_BITMASK;
	sb->s_op = &jffs_ops;

	/* Get the root directory of this file system.  */
	if (!(sb->s_mounted = iget(sb, JFFS_MIN_INO))) {
		goto jffs_sb_err2;
	}

#ifdef USE_GC
	/* Do a garbage collect every time we mount.  */
	jffs_garbage_collect((struct jffs_control *)sb->u.generic_sbp);
#endif

	unlock_super(sb);
	printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
	       kdevname(dev));
	return sb;

jffs_sb_err2:
	jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
jffs_sb_err1:
	unlock_super(sb);
	MOD_DEC_USE_COUNT;
	printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
	       kdevname(dev));
	return 0;
}


/* This function is called when the file system is umounted.  */
static void
jffs_put_super(struct super_block *sb)
{
	kdev_t dev = sb->s_dev;
	D2(printk("jffs_put_super()\n"));
	lock_super(sb);
	sb->s_dev = 0;
	jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
	unlock_super(sb);
	MOD_DEC_USE_COUNT;
	printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
	       kdevname(dev));
}


/* This function is called when user commands like chmod, chgrp and
   chown are executed. System calls like trunc() results in a call
   to this function.  */
static int
jffs_notify_change(struct inode *inode, struct iattr *iattr)
{
	struct jffs_raw_inode raw_inode;
	struct jffs_control *c;
	struct jffs_fmcontrol *fmc;
	struct jffs_file *f;
	struct jffs_node *new_node;
	char *name = 0;
	int update_all;
	int res;

	f = (struct jffs_file *)inode->u.generic_ip;
	ASSERT(if (!f) {
		printk("jffs_notify_change(): Invalid inode number: %lu\n",
		       inode->i_ino);
		return -1;
	});

	D1(printk("***jffs_notify_change(): file: \"%s\", ino: %u\n",
		  f->name, f->ino));

	c = f->c;
	fmc = c->fmc;
	update_all = iattr->ia_valid & ATTR_FORCE;

	if (!JFFS_ENOUGH_SPACE(fmc)) {
		if (((update_all || iattr->ia_valid & ATTR_SIZE)
		    && (iattr->ia_size < f->size))) {
			/* See this case where someone is trying to
			   shrink the size of a file as an exception.
			   Accept it.  */
		}
		else {
			D1(printk("jffs_notify_change(): Free size = %u\n",
				  jffs_free_size1(fmc)
				  + jffs_free_size2(fmc)));
			D(printk(KERN_NOTICE "JFFS: No space left on "
				 "device\n"));
			return -ENOSPC;
		}
	}

	if (!(new_node = (struct jffs_node *)
			 kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) {
		D(printk("jffs_notify_change(): Allocation failed!\n"));
		return -ENOMEM;
	}
	DJM(no_jffs_node++);
	new_node->data_offset = 0;
	new_node->removed_size = 0;
	raw_inode.magic = JFFS_MAGIC_BITMASK;
	raw_inode.ino = f->ino;
	raw_inode.pino = f->pino;
	raw_inode.version = f->highest_version + 1;
	raw_inode.mode = f->mode;
	raw_inode.uid = f->uid;
	raw_inode.gid = f->gid;
	raw_inode.atime = f->atime;
	raw_inode.mtime = f->mtime;
	raw_inode.ctime = f->ctime;
	raw_inode.dsize = 0;
	raw_inode.offset = 0;
	raw_inode.rsize = 0;
	raw_inode.dsize = 0;
	raw_inode.nsize = 0;
	raw_inode.nlink = f->nlink;
	raw_inode.spare = 0;
	raw_inode.rename = 0;
	raw_inode.deleted = 0;

	if (update_all || iattr->ia_valid & ATTR_MODE) {
		raw_inode.mode = iattr->ia_mode;
		inode->i_mode = iattr->ia_mode;
	}
	if (update_all || iattr->ia_valid & ATTR_UID) {
		raw_inode.uid = iattr->ia_uid;
		inode->i_uid = iattr->ia_uid;
	}
	if (update_all || iattr->ia_valid & ATTR_GID) {
		raw_inode.gid = iattr->ia_gid;
		inode->i_gid = iattr->ia_gid;
	}
	if (update_all || iattr->ia_valid & ATTR_SIZE) {
		int len;
		D1(printk("jffs_notify_change(): Changing size "
			  "to %lu bytes!\n", iattr->ia_size));
		raw_inode.offset = iattr->ia_size;

		/* Calculate how many bytes need to be removed from
		   the end.  */

		if (f->size < iattr->ia_size) {
			len = 0;
		}
		else {
			len = f->size - iattr->ia_size;
		}

		raw_inode.rsize = len;

		/* The updated node will be a removal node, with
		   base at the new size and size of the nbr of bytes
		   to be removed.  */

		new_node->data_offset = iattr->ia_size;
		new_node->removed_size = len;
		inode->i_size = iattr->ia_size;

		/* If we truncate a file we want to add the name.  If we
		   always do that, we could perhaps free more space on
		   the flash (and besides it doesn't hurt).  */
		name = f->name;
		raw_inode.nsize = f->nsize;
		if (len) {
			invalidate_inode_pages(inode);
		}
		inode->i_ctime = CURRENT_TIME;
		inode->i_mtime = inode->i_ctime;
	}
	if (update_all || iattr->ia_valid & ATTR_ATIME) {
		raw_inode.atime = iattr->ia_atime;
		inode->i_atime = iattr->ia_atime;
	}
	if (update_all || iattr->ia_valid & ATTR_MTIME) {
		raw_inode.mtime = iattr->ia_mtime;
		inode->i_mtime = iattr->ia_mtime;
	}
	if (update_all || iattr->ia_valid & ATTR_CTIME) {
		raw_inode.ctime = iattr->ia_ctime;
		inode->i_ctime = iattr->ia_ctime;
	}

	/* Write this node to the flash.  */
	if ((res = jffs_write_node(c, new_node, &raw_inode, name, 0)) < 0) {
		D(printk("jffs_notify_change(): The write failed!\n"));
		kfree(new_node);
		DJM(no_jffs_node--);
		return res;
	}

	jffs_insert_node(c, f, &raw_inode, 0, new_node);
	inode->i_dirt = 1;
	return 0;
} /* jffs_notify_change()  */


/* Get statistics of the file system.  */
static void
jffs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
{
	struct statfs tmp;
	struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp;
	struct jffs_fmcontrol *fmc = c->fmc;

	D2(printk("jffs_statfs()\n"));

	c = (struct jffs_control *)sb->u.generic_sbp;
	memset(&tmp, 0, sizeof(tmp));
	tmp.f_type = JFFS_MAGIC_SB_BITMASK;
	tmp.f_bsize = PAGE_SIZE;
	tmp.f_blocks = (fmc->flash_size / BLOCK_SIZE)
		       - (fmc->min_free_size / BLOCK_SIZE);
	tmp.f_bfree = (jffs_free_size1(fmc) / BLOCK_SIZE
		       + jffs_free_size2(fmc) / BLOCK_SIZE)
		      - (fmc->min_free_size / BLOCK_SIZE);
	/* Find out how many files there are in the filesystem.  */
	tmp.f_files = jffs_foreach_file(c, jffs_file_count);
	tmp.f_ffree = tmp.f_bfree;
	/* tmp.f_fsid = 0; */
	tmp.f_namelen = JFFS_MAX_NAME_LEN;
	memcpy_tofs(buf, &tmp, bufsize);
}


/* Rename a file.  */
int
jffs_rename(struct inode *old_dir, const char *old_name, int old_len,
            struct inode *new_dir, const char *new_name, int new_len,
            int must_be_dir)
{
	struct jffs_raw_inode raw_inode;
	struct jffs_control *c;
	struct jffs_file *old_dir_f;
	struct jffs_file *new_dir_f;
	struct jffs_file *del_f;
	struct jffs_file *f;
	struct jffs_node *node;
	struct inode *inode;
	int result = 0;
	__u32 rename_data = 0;

	D2(printk("***jffs_rename()\n"));

	if (!old_dir || !old_name || !new_dir || !new_name) {
		D(printk("jffs_rename(): old_dir: 0x%p, old_name: 0x%p, "
			 "new_dir: 0x%p, new_name: 0x%p\n",
			 old_dir, old_name, new_dir, new_name));
		return -1;
	}

	c = (struct jffs_control *)old_dir->i_sb->u.generic_sbp;
	ASSERT(if (!c) {
		printk(KERN_ERR "jffs_rename(): The old_dir inode "
		       "didn't have a reference to a jffs_file struct\n");
		return -1;
	});

	if (!JFFS_ENOUGH_SPACE(c->fmc)) {
		D1(printk("jffs_rename(): Free size = %u\n",
			  jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
		D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
		return -ENOSPC;
	}

	while (c->rename_lock) {
		sleep_on(&c->rename_wait);
	}
	c->rename_lock = 1;

	/* Check the lengths of the names.  */
	if ((old_len > JFFS_MAX_NAME_LEN) || (new_len > JFFS_MAX_NAME_LEN)) {
		result = -ENAMETOOLONG;
		goto jffs_rename_end;
	}
	/* Find the the old directory.  */
	if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
		D(printk("jffs_rename(): Old dir invalid.\n"));
		result = -ENOTDIR;
		goto jffs_rename_end;
	}
	/* See if it really is a directory.  */
	if (!S_ISDIR(old_dir_f->mode)) {
		D(printk("jffs_rename(): old_dir is not a directory.\n"));
		result = -ENOTDIR;
		goto jffs_rename_end;
	}
	/* Try to find the file to move.  */
	if (!(f = jffs_find_child(old_dir_f, old_name, old_len))) {
		result = -ENOENT;
		goto jffs_rename_end;
	}
	/* Try to find the new directory's node.  */
	if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
		D(printk("jffs_rename(): New dir invalid.\n"));
		result = -ENOTDIR;
		goto jffs_rename_end;
	}
	/* See if the node really is a directory.  */
	if (!S_ISDIR(new_dir_f->mode)) {
		D(printk("jffs_rename(): The new position of the node "
			 "is not a directory.\n"));
		result = -ENOTDIR;
		goto jffs_rename_end;
	}

	/* Create a node and initialize as much as needed.  */
	if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
						  GFP_KERNEL))) {
		D(printk("jffs_rename(): Allocation failed: node == 0\n"));
		result = -ENOMEM;
		goto jffs_rename_end;
	}
	DJM(no_jffs_node++);
	node->data_offset = 0;
	node->removed_size = 0;

	/* Initialize the raw inode.  */
	raw_inode.magic = JFFS_MAGIC_BITMASK;
	raw_inode.ino = f->ino;
	raw_inode.pino = new_dir_f->ino;
	raw_inode.version = f->highest_version + 1;
	raw_inode.mode = f->mode;
	raw_inode.uid = current->fsuid;
	raw_inode.gid = current->fsgid;
#if 0
	raw_inode.uid = f->uid;
	raw_inode.gid = f->gid;
#endif
	raw_inode.atime = CURRENT_TIME;
	raw_inode.mtime = raw_inode.atime;
	raw_inode.ctime = f->ctime;
	raw_inode.offset = 0;
	raw_inode.dsize = 0;
	raw_inode.rsize = 0;
	raw_inode.nsize = new_len;
	raw_inode.nlink = f->nlink;
	raw_inode.spare = 0;
	raw_inode.rename = 0;
	raw_inode.deleted = 0;

	/* See if there already exists a file with the same name as
	   new_name.  */
	if ((del_f = jffs_find_child(new_dir_f, new_name, new_len))) {
		raw_inode.rename = 1;
		/*raw_inode.mode = del_f->ino;*/
	}

	/* Write the new node to the flash memory.  */
	if ((result = jffs_write_node(c, node, &raw_inode, new_name,
				      (unsigned char*)&rename_data)) < 0) {
		D(printk("jffs_rename(): Failed to write node to flash.\n"));
		kfree(node);
		DJM(no_jffs_node--);
		goto jffs_rename_end;
	}

	if (raw_inode.rename) {
		/* The file with the same name must be deleted.  */
		c->fmc->no_call_gc = 1;
		if ((result = jffs_remove(new_dir, new_name, new_len,
				          del_f->mode, 0)) < 0) {
			/* This is really bad.  */
			printk(KERN_ERR "JFFS: An error occurred in "
			       "rename().\n");
		}

⌨️ 快捷键说明

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