Merge branch 'kill-jffs' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6

* 'kill-jffs' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6:
  Remove JFFS (version 1), as scheduled.
This commit is contained in:
Linus Torvalds 2007-02-19 13:25:36 -08:00
commit ebbe46f73a
12 changed files with 0 additions and 6859 deletions

View File

@ -283,13 +283,6 @@ Who: Len Brown <len.brown@intel.com>
---------------------------
What: JFFS (version 1)
When: 2.6.21
Why: Unmaintained for years, superceded by JFFS2 for years.
Who: Jeff Garzik <jeff@garzik.org>
---------------------------
What: sk98lin network driver
When: July 2007
Why: In kernel tree version of driver is unmaintained. Sk98lin driver

View File

@ -1189,32 +1189,6 @@ config EFS_FS
To compile the EFS file system support as a module, choose M here: the
module will be called efs.
config JFFS_FS
tristate "Journalling Flash File System (JFFS) support"
depends on MTD && BLOCK && BROKEN
help
JFFS is the Journalling Flash File System developed by Axis
Communications in Sweden, aimed at providing a crash/powerdown-safe
file system for disk-less embedded devices. Further information is
available at (<http://developer.axis.com/software/jffs/>).
NOTE: This filesystem is deprecated and is scheduled for removal in
2.6.21. See Documentation/feature-removal-schedule.txt
config JFFS_FS_VERBOSE
int "JFFS debugging verbosity (0 = quiet, 3 = noisy)"
depends on JFFS_FS
default "0"
help
Determines the verbosity level of the JFFS debugging messages.
config JFFS_PROC_FS
bool "JFFS stats available in /proc filesystem"
depends on JFFS_FS && PROC_FS
help
Enabling this option will cause statistics from mounted JFFS file systems
to be made available to the user in the /proc/fs/jffs/ directory.
config JFFS2_FS
tristate "Journalling Flash File System v2 (JFFS2) support"
select CRC32

View File

@ -94,7 +94,6 @@ obj-$(CONFIG_HPFS_FS) += hpfs/
obj-$(CONFIG_NTFS_FS) += ntfs/
obj-$(CONFIG_UFS_FS) += ufs/
obj-$(CONFIG_EFS_FS) += efs/
obj-$(CONFIG_JFFS_FS) += jffs/
obj-$(CONFIG_JFFS2_FS) += jffs2/
obj-$(CONFIG_AFFS_FS) += affs/
obj-$(CONFIG_ROMFS_FS) += romfs/

View File

@ -1,11 +0,0 @@
#
# Makefile for the linux Journalling Flash FileSystem (JFFS) routines.
#
# $Id: Makefile,v 1.11 2001/09/25 20:59:41 dwmw2 Exp $
#
obj-$(CONFIG_JFFS_FS) += jffs.o
jffs-y := jffs_fm.o intrep.o inode-v23.o
jffs-$(CONFIG_JFFS_PROC_FS) += jffs_proc.o
jffs-objs := $(jffs-y)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
/*
* JFFS -- Journaling Flash File System, Linux implementation.
*
* Copyright (C) 1999, 2000 Axis Communications AB.
*
* Created by Finn Hakansson <finn@axis.com>.
*
* 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: intrep.h,v 1.14 2001/09/23 23:28:37 dwmw2 Exp $
*
*/
#ifndef __LINUX_JFFS_INTREP_H__
#define __LINUX_JFFS_INTREP_H__
#include "jffs_fm.h"
struct jffs_node *jffs_alloc_node(void);
void jffs_free_node(struct jffs_node *n);
int jffs_get_node_inuse(void);
void jffs_cleanup_control(struct jffs_control *c);
int jffs_build_fs(struct super_block *sb);
int jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
const struct jffs_raw_inode *raw_inode,
const char *name, struct jffs_node *node);
struct jffs_file *jffs_find_file(struct jffs_control *c, __u32 ino);
struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int len);
void jffs_free_node(struct jffs_node *node);
int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *));
int jffs_possibly_delete_file(struct jffs_file *f);
int jffs_insert_file_into_tree(struct jffs_file *f);
int jffs_unlink_file_from_tree(struct jffs_file *f);
int jffs_file_count(struct jffs_file *f);
int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
struct jffs_raw_inode *raw_inode,
const char *name, const unsigned char *buf,
int recoverable, struct jffs_file *f);
int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, __u32 size);
/* Garbage collection stuff. */
int jffs_garbage_collect_thread(void *c);
void jffs_garbage_collect_trigger(struct jffs_control *c);
/* For debugging purposes. */
#if 0
int jffs_print_file(struct jffs_file *f);
#endif /* 0 */
void jffs_print_hash_table(struct jffs_control *c);
void jffs_print_tree(struct jffs_file *first_file, int indent);
#endif /* __LINUX_JFFS_INTREP_H__ */

View File

@ -1,798 +0,0 @@
/*
* JFFS -- Journaling Flash File System, Linux implementation.
*
* Copyright (C) 1999, 2000 Axis Communications AB.
*
* Created by Finn Hakansson <finn@axis.com>.
*
* 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: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
*
* Ported to Linux 2.3.x and MTD:
* Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
*
*/
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/blkdev.h>
#include <linux/jffs.h>
#include "jffs_fm.h"
#include "intrep.h"
#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
#endif
static struct jffs_fm *jffs_alloc_fm(void);
static void jffs_free_fm(struct jffs_fm *n);
extern struct kmem_cache *fm_cache;
extern struct kmem_cache *node_cache;
#if CONFIG_JFFS_FS_VERBOSE > 0
void
jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
{
D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
D(printk("{\n"));
D(printk(" %u, /* flash_size */\n", fmc->flash_size));
D(printk(" %u, /* used_size */\n", fmc->used_size));
D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
D(printk(" %u, /* free_size */\n", fmc->free_size));
D(printk(" %u, /* sector_size */\n", fmc->sector_size));
D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
D(printk(" 0x%p, /* head */ "
"(head->offset = 0x%08x)\n",
fmc->head, (fmc->head ? fmc->head->offset : 0)));
D(printk(" 0x%p, /* tail */ "
"(tail->offset + tail->size = 0x%08x)\n",
fmc->tail,
(fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
D(printk("}\n"));
}
#endif /* CONFIG_JFFS_FS_VERBOSE > 0 */
#if CONFIG_JFFS_FS_VERBOSE > 2
static void
jffs_print_fm(struct jffs_fm *fm)
{
D(printk("struct jffs_fm: 0x%p\n", fm));
D(printk("{\n"));
D(printk(" 0x%08x, /* offset */\n", fm->offset));
D(printk(" %u, /* size */\n", fm->size));
D(printk(" 0x%p, /* prev */\n", fm->prev));
D(printk(" 0x%p, /* next */\n", fm->next));
D(printk(" 0x%p, /* nodes */\n", fm->nodes));
D(printk("}\n"));
}
#endif /* CONFIG_JFFS_FS_VERBOSE > 2 */
#if 0
void
jffs_print_node_ref(struct jffs_node_ref *ref)
{
D(printk("struct jffs_node_ref: 0x%p\n", ref));
D(printk("{\n"));
D(printk(" 0x%p, /* node */\n", ref->node));
D(printk(" 0x%p, /* next */\n", ref->next));
D(printk("}\n"));
}
#endif /* 0 */
/* This function creates a new shiny flash memory control structure. */
struct jffs_fmcontrol *
jffs_build_begin(struct jffs_control *c, int unit)
{
struct jffs_fmcontrol *fmc;
struct mtd_info *mtd;
D3(printk("jffs_build_begin()\n"));
fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
if (!fmc) {
D(printk("jffs_build_begin(): Allocation of "
"struct jffs_fmcontrol failed!\n"));
return (struct jffs_fmcontrol *)0;
}
DJM(no_jffs_fmcontrol++);
mtd = get_mtd_device(NULL, unit);
if (IS_ERR(mtd)) {
kfree(fmc);
DJM(no_jffs_fmcontrol--);
return NULL;
}
/* Retrieve the size of the flash memory. */
fmc->flash_size = mtd->size;
D3(printk(" fmc->flash_size = %d bytes\n", fmc->flash_size));
fmc->used_size = 0;
fmc->dirty_size = 0;
fmc->free_size = mtd->size;
fmc->sector_size = mtd->erasesize;
fmc->max_chunk_size = fmc->sector_size >> 1;
/* min_free_size:
1 sector, obviously.
+ 1 x max_chunk_size, for when a nodes overlaps the end of a sector
+ 1 x max_chunk_size again, which ought to be enough to handle
the case where a rename causes a name to grow, and GC has
to write out larger nodes than the ones it's obsoleting.
We should fix it so it doesn't have to write the name
_every_ time. Later.
+ another 2 sectors because people keep getting GC stuck and
we don't know why. This scares me - I want formal proof
of correctness of whatever number we put here. dwmw2.
*/
fmc->min_free_size = fmc->sector_size << 2;
fmc->mtd = mtd;
fmc->c = c;
fmc->head = NULL;
fmc->tail = NULL;
fmc->head_extra = NULL;
fmc->tail_extra = NULL;
mutex_init(&fmc->biglock);
return fmc;
}
/* When the flash memory scan has completed, this function should be called
before use of the control structure. */
void
jffs_build_end(struct jffs_fmcontrol *fmc)
{
D3(printk("jffs_build_end()\n"));
if (!fmc->head) {
fmc->head = fmc->head_extra;
fmc->tail = fmc->tail_extra;
}
else if (fmc->head_extra) {
fmc->tail_extra->next = fmc->head;
fmc->head->prev = fmc->tail_extra;
fmc->head = fmc->head_extra;
}
fmc->head_extra = NULL; /* These two instructions should be omitted. */
fmc->tail_extra = NULL;
D3(jffs_print_fmcontrol(fmc));
}
/* Call this function when the file system is unmounted. This function
frees all memory used by this module. */
void
jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc)
{
if (fmc) {
struct jffs_fm *next = fmc->head;
while (next) {
struct jffs_fm *cur = next;
next = next->next;
jffs_free_fm(cur);
}
put_mtd_device(fmc->mtd);
kfree(fmc);
DJM(no_jffs_fmcontrol--);
}
}
/* This function returns the size of the first chunk of free space on the
flash memory. This function will return something nonzero if the flash
memory contains any free space. */
__u32
jffs_free_size1(struct jffs_fmcontrol *fmc)
{
__u32 head;
__u32 tail;
__u32 end = fmc->flash_size;
if (!fmc->head) {
/* There is nothing on the flash. */
return fmc->flash_size;
}
/* Compute the beginning and ending of the contents of the flash. */
head = fmc->head->offset;
tail = fmc->tail->offset + fmc->tail->size;
if (tail == end) {
tail = 0;
}
ASSERT(else if (tail > end) {
printk(KERN_WARNING "jffs_free_size1(): tail > end\n");
tail = 0;
});
if (head <= tail) {
return end - tail;
}
else {
return head - tail;
}
}
/* This function will return something nonzero in case there are two free
areas on the flash. Like this:
+----------------+------------------+----------------+
| FREE 1 | USED / DIRTY | FREE 2 |
+----------------+------------------+----------------+
fmc->head -----^
fmc->tail ------------------------^
The value returned, will be the size of the first empty area on the
flash, in this case marked "FREE 1". */
__u32
jffs_free_size2(struct jffs_fmcontrol *fmc)
{
if (fmc->head) {
__u32 head = fmc->head->offset;
__u32 tail = fmc->tail->offset + fmc->tail->size;
if (tail == fmc->flash_size) {
tail = 0;
}
if (tail >= head) {
return head;
}
}
return 0;
}
/* Allocate a chunk of flash memory. If there is enough space on the
device, a reference to the associated node is stored in the jffs_fm
struct. */
int
jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
struct jffs_fm **result)
{
struct jffs_fm *fm;
__u32 free_chunk_size1;
__u32 free_chunk_size2;
D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, "
"node = 0x%p\n", fmc, size, node));
*result = NULL;
if (!(fm = jffs_alloc_fm())) {
D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n"));
return -ENOMEM;
}
free_chunk_size1 = jffs_free_size1(fmc);
free_chunk_size2 = jffs_free_size2(fmc);
if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
printk(KERN_WARNING "Free size accounting screwed\n");
printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
}
D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
"free_chunk_size2 = %u\n",
free_chunk_size1, free_chunk_size2));
if (size <= free_chunk_size1) {
if (!(fm->nodes = (struct jffs_node_ref *)
kmalloc(sizeof(struct jffs_node_ref),
GFP_KERNEL))) {
D(printk("jffs_fmalloc(): kmalloc() failed! "
"(node_ref)\n"));
jffs_free_fm(fm);
return -ENOMEM;
}
DJM(no_jffs_node_ref++);
fm->nodes->node = node;
fm->nodes->next = NULL;
if (fmc->tail) {
fm->offset = fmc->tail->offset + fmc->tail->size;
if (fm->offset == fmc->flash_size) {
fm->offset = 0;
}
ASSERT(else if (fm->offset > fmc->flash_size) {
printk(KERN_WARNING "jffs_fmalloc(): "
"offset > flash_end\n");
fm->offset = 0;
});
}
else {
/* There don't have to be files in the file
system yet. */
fm->offset = 0;
}
fm->size = size;
fmc->free_size -= size;
fmc->used_size += size;
}
else if (size > free_chunk_size2) {
printk(KERN_WARNING "JFFS: Tried to allocate a too "
"large flash memory chunk. (size = %u)\n", size);
jffs_free_fm(fm);
return -ENOSPC;
}
else {
fm->offset = fmc->tail->offset + fmc->tail->size;
fm->size = free_chunk_size1;
fm->nodes = NULL;
fmc->free_size -= fm->size;
fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a
bug that caused infinite garbage collection.
It previously set fmc->dirty_size to size (which is the
size of the requested chunk).
*/
}
fm->next = NULL;
if (!fmc->head) {
fm->prev = NULL;
fmc->head = fm;
fmc->tail = fm;
}
else {
fm->prev = fmc->tail;
fmc->tail->next = fm;
fmc->tail = fm;
}
D3(jffs_print_fmcontrol(fmc));
D3(jffs_print_fm(fm));
*result = fm;
return 0;
}
/* The on-flash space is not needed anymore by the passed node. Remove
the reference to the node from the node list. If the data chunk in
the flash memory isn't used by any more nodes anymore (fm->nodes == 0),
then mark that chunk as dirty. */
int
jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node)
{
struct jffs_node_ref *ref;
struct jffs_node_ref *prev;
ASSERT(int del = 0);
D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n",
node->ino, node->version));
ASSERT(if (!fmc || !fm || !fm->nodes) {
printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, "
"fm->nodes: 0x%p\n",
fmc, fm, (fm ? fm->nodes : NULL));
return -1;
});
/* Find the reference to the node that is going to be removed
and remove it. */
for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) {
if (ref->node == node) {
if (prev) {
prev->next = ref->next;
}
else {
fm->nodes = ref->next;
}
kfree(ref);
DJM(no_jffs_node_ref--);
ASSERT(del = 1);
break;
}
prev = ref;
}
/* If the data chunk in the flash memory isn't used anymore
just mark it as obsolete. */
if (!fm->nodes) {
/* No node uses this chunk so let's remove it. */
fmc->used_size -= fm->size;
fmc->dirty_size += fm->size;
#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
if (jffs_mark_obsolete(fmc, fm->offset) < 0) {
D1(printk("jffs_fmfree(): Failed to mark an on-flash "
"node obsolete!\n"));
return -1;
}
#endif
}
ASSERT(if (!del) {
printk(KERN_WARNING "***jffs_fmfree(): "
"Didn't delete any node reference!\n");
});
return 0;
}
/* This allocation function is used during the initialization of
the file system. */
struct jffs_fm *
jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
struct jffs_node *node)
{
struct jffs_fm *fm;
D3(printk("jffs_fmalloced()\n"));
if (!(fm = jffs_alloc_fm())) {
D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n",
fmc, offset, size, node));
return NULL;
}
fm->offset = offset;
fm->size = size;
fm->prev = NULL;
fm->next = NULL;
fm->nodes = NULL;
if (node) {
/* `node' exists and it should be associated with the
jffs_fm structure `fm'. */
if (!(fm->nodes = (struct jffs_node_ref *)
kmalloc(sizeof(struct jffs_node_ref),
GFP_KERNEL))) {
D(printk("jffs_fmalloced(): !fm->nodes\n"));
jffs_free_fm(fm);
return NULL;
}
DJM(no_jffs_node_ref++);
fm->nodes->node = node;
fm->nodes->next = NULL;
fmc->used_size += size;
fmc->free_size -= size;
}
else {
/* If there is no node, then this is just a chunk of dirt. */
fmc->dirty_size += size;
fmc->free_size -= size;
}
if (fmc->head_extra) {
fm->prev = fmc->tail_extra;
fmc->tail_extra->next = fm;
fmc->tail_extra = fm;
}
else if (!fmc->head) {
fmc->head = fm;
fmc->tail = fm;
}
else if (fmc->tail->offset + fmc->tail->size < offset) {
fmc->head_extra = fm;
fmc->tail_extra = fm;
}
else {
fm->prev = fmc->tail;
fmc->tail->next = fm;
fmc->tail = fm;
}
D3(jffs_print_fmcontrol(fmc));
D3(jffs_print_fm(fm));
return fm;
}
/* Add a new node to an already existing jffs_fm struct. */
int
jffs_add_node(struct jffs_node *node)
{
struct jffs_node_ref *ref;
D3(printk("jffs_add_node(): ino = %u\n", node->ino));
ref = kmalloc(sizeof(*ref), GFP_KERNEL);
if (!ref)
return -ENOMEM;
DJM(no_jffs_node_ref++);
ref->node = node;
ref->next = node->fm->nodes;
node->fm->nodes = ref;
return 0;
}
/* Free a part of some allocated space. */
void
jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size)
{
D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, "
"fm->nodes->node->ino = %u, size = %u\n",
fm, (fm ? fm->nodes : 0),
(!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size));
if (fm->nodes) {
kfree(fm->nodes);
DJM(no_jffs_node_ref--);
fm->nodes = NULL;
}
fmc->used_size -= fm->size;
if (fm == fmc->tail) {
fm->size -= size;
fmc->free_size += size;
}
fmc->dirty_size += fm->size;
}
/* Find the jffs_fm struct that contains the end of the data chunk that
begins at the logical beginning of the flash memory and spans `size'
bytes. If we want to erase a sector of the flash memory, we use this
function to find where the sector limit cuts a chunk of data. */
struct jffs_fm *
jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size)
{
struct jffs_fm *fm;
__u32 pos = 0;
if (size == 0) {
return NULL;
}
ASSERT(if (!fmc) {
printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n");
return NULL;
});
fm = fmc->head;
while (fm) {
pos += fm->size;
if (pos < size) {
fm = fm->next;
}
else if (pos > size) {
break;
}
else {
fm = NULL;
break;
}
}
return fm;
}
/* Move the head of the fmc structures and delete the obsolete parts. */
void
jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
{
struct jffs_fm *fm;
struct jffs_fm *del;
ASSERT(if (!fmc) {
printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n");
return;
});
fmc->dirty_size -= erased_size;
fmc->free_size += erased_size;
for (fm = fmc->head; fm && (erased_size > 0);) {
if (erased_size >= fm->size) {
erased_size -= fm->size;
del = fm;
fm = fm->next;
fm->prev = NULL;
fmc->head = fm;
jffs_free_fm(del);
}
else {
fm->size -= erased_size;
fm->offset += erased_size;
break;
}
}
}
/* Return the oldest used node in the flash memory. */
struct jffs_node *
jffs_get_oldest_node(struct jffs_fmcontrol *fmc)
{
struct jffs_fm *fm;
struct jffs_node_ref *nref;
struct jffs_node *node = NULL;
ASSERT(if (!fmc) {
printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n");
return NULL;
});
for (fm = fmc->head; fm && !fm->nodes; fm = fm->next);
if (!fm) {
return NULL;
}
/* The oldest node is the last one in the reference list. This list
shouldn't be too long; just one or perhaps two elements. */
for (nref = fm->nodes; nref; nref = nref->next) {
node = nref->node;
}
D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n",
(node ? node->ino : 0), (node ? node->version : 0)));
return node;
}
#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
/* Mark an on-flash node as obsolete.
Note that this is just an optimization that isn't necessary for the
filesystem to work. */
static int
jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
{
/* The `accurate_pos' holds the position of the accurate byte
in the jffs_raw_inode structure that we are going to mark
as obsolete. */
__u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET;
unsigned char zero = 0x00;
size_t len;
D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos));
ASSERT(if (!fmc) {
printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n");
return -1;
});
/* Write 0x00 to the raw inode's accurate member. Don't care
about the return value. */
MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero);
return 0;
}
#endif /* JFFS_MARK_OBSOLETE */
/* check if it's possible to erase the wanted range, and if not, return
* the range that IS erasable, or a negative error code.
*/
static long
jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
{
u_long ssize;
/* assume that sector size for a partition is constant even
* if it spans more than one chip (you usually put the same
* type of chips in a system)
*/
ssize = mtd->erasesize;
if (offset % ssize) {
printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
/* The offset is not sector size aligned. */
return -1;
}
else if (offset > mtd->size) {
printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size);
return -2;
}
else if (offset + size > mtd->size) {
printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size);
return -3;
}
return (size / ssize) * ssize;
}
/* How much dirty flash memory is possible to erase at the moment? */
long
jffs_erasable_size(struct jffs_fmcontrol *fmc)
{
struct jffs_fm *fm;
__u32 size = 0;
long ret;
ASSERT(if (!fmc) {
printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n");
return -1;
});
if (!fmc->head) {
/* The flash memory is totally empty. No nodes. No dirt.
Just return. */
return 0;
}
/* Calculate how much space that is dirty. */
for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) {
if (size && fm->offset == 0) {
/* We have reached the beginning of the flash. */
break;
}
size += fm->size;
}
/* Someone's signature contained this:
There's a fine line between fishing and just standing on
the shore like an idiot... */
ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size);
ASSERT(if (ret < 0) {
printk("jffs_erasable_size: flash_erasable_size() "
"returned something less than zero (%ld).\n", ret);
printk("jffs_erasable_size: offset = 0x%08x\n",
fmc->head->offset);
});
/* If there is dirt on the flash (which is the reason to why
this function was called in the first place) but no space is
possible to erase right now, the initial part of the list of
jffs_fm structs, that hold place for dirty space, could perhaps
be shortened. The list's initial "dirty" elements are merged
into just one large dirty jffs_fm struct. This operation must
only be performed if nothing is possible to erase. Otherwise,
jffs_clear_end_of_node() won't work as expected. */
if (ret == 0) {
struct jffs_fm *head = fmc->head;
struct jffs_fm *del;
/* While there are two dirty nodes beside each other.*/
while (head->nodes == 0
&& head->next
&& head->next->nodes == 0) {
del = head->next;
head->size += del->size;
head->next = del->next;
if (del->next) {
del->next->prev = head;
}
jffs_free_fm(del);
}
}
return (ret >= 0 ? ret : 0);
}
static struct jffs_fm *jffs_alloc_fm(void)
{
struct jffs_fm *fm;
fm = kmem_cache_alloc(fm_cache,GFP_KERNEL);
DJM(if (fm) no_jffs_fm++;);
return fm;
}
static void jffs_free_fm(struct jffs_fm *n)
{
kmem_cache_free(fm_cache,n);
DJM(no_jffs_fm--);
}
struct jffs_node *jffs_alloc_node(void)
{
struct jffs_node *n;
n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL);
if(n != NULL)
no_jffs_node++;
return n;
}
void jffs_free_node(struct jffs_node *n)
{
kmem_cache_free(node_cache,n);
no_jffs_node--;
}
int jffs_get_node_inuse(void)
{
return no_jffs_node;
}

View File

@ -1,149 +0,0 @@
/*
* JFFS -- Journaling Flash File System, Linux implementation.
*
* Copyright (C) 1999, 2000 Axis Communications AB.
*
* Created by Finn Hakansson <finn@axis.com>.
*
* 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: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
*
* Ported to Linux 2.3.x and MTD:
* Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
*
*/
#ifndef __LINUX_JFFS_FM_H__
#define __LINUX_JFFS_FM_H__
#include <linux/types.h>
#include <linux/jffs.h>
#include <linux/mtd/mtd.h>
#include <linux/mutex.h>
/* The alignment between two nodes in the flash memory. */
#define JFFS_ALIGN_SIZE 4
/* Mark the on-flash space as obsolete when appropriate. */
#define JFFS_MARK_OBSOLETE 0
#ifndef CONFIG_JFFS_FS_VERBOSE
#define CONFIG_JFFS_FS_VERBOSE 1
#endif
#if CONFIG_JFFS_FS_VERBOSE > 0
#define D(x) x
#define D1(x) D(x)
#else
#define D(x)
#define D1(x)
#endif
#if CONFIG_JFFS_FS_VERBOSE > 1
#define D2(x) D(x)
#else
#define D2(x)
#endif
#if CONFIG_JFFS_FS_VERBOSE > 2
#define D3(x) D(x)
#else
#define D3(x)
#endif
#define ASSERT(x) x
/* How many padding bytes should be inserted between two chunks of data
on the flash? */
#define JFFS_GET_PAD_BYTES(size) ( (JFFS_ALIGN_SIZE-1) & -(__u32)(size) )
#define JFFS_PAD(size) ( (size + (JFFS_ALIGN_SIZE-1)) & ~(JFFS_ALIGN_SIZE-1) )
struct jffs_node_ref
{
struct jffs_node *node;
struct jffs_node_ref *next;
};
/* The struct jffs_fm represents a chunk of data in the flash memory. */
struct jffs_fm
{
__u32 offset;
__u32 size;
struct jffs_fm *prev;
struct jffs_fm *next;
struct jffs_node_ref *nodes; /* USED if != 0. */
};
struct jffs_fmcontrol
{
__u32 flash_size;
__u32 used_size;
__u32 dirty_size;
__u32 free_size;
__u32 sector_size;
__u32 min_free_size; /* The minimum free space needed to be able
to perform garbage collections. */
__u32 max_chunk_size; /* The maximum size of a chunk of data. */
struct mtd_info *mtd;
struct jffs_control *c;
struct jffs_fm *head;
struct jffs_fm *tail;
struct jffs_fm *head_extra;
struct jffs_fm *tail_extra;
struct mutex biglock;
};
/* Notice the two members head_extra and tail_extra in the jffs_control
structure above. Those are only used during the scanning of the flash
memory; while the file system is being built. If the data in the flash
memory is organized like
+----------------+------------------+----------------+
| USED / DIRTY | FREE | USED / DIRTY |
+----------------+------------------+----------------+
then the scan is split in two parts. The first scanned part of the
flash memory is organized through the members head and tail. The
second scanned part is organized with head_extra and tail_extra. When
the scan is completed, the two lists are merged together. The jffs_fm
struct that head_extra references is the logical beginning of the
flash memory so it will be referenced by the head member. */
struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, int unit);
void jffs_build_end(struct jffs_fmcontrol *fmc);
void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
struct jffs_node *node, struct jffs_fm **result);
int jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
struct jffs_node *node);
__u32 jffs_free_size1(struct jffs_fmcontrol *fmc);
__u32 jffs_free_size2(struct jffs_fmcontrol *fmc);
void jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size);
struct jffs_fm *jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size);
struct jffs_node *jffs_get_oldest_node(struct jffs_fmcontrol *fmc);
long jffs_erasable_size(struct jffs_fmcontrol *fmc);
struct jffs_fm *jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset,
__u32 size, struct jffs_node *node);
int jffs_add_node(struct jffs_node *node);
void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
__u32 size);
#if CONFIG_JFFS_FS_VERBOSE > 0
void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
#endif
#if 0
void jffs_print_node_ref(struct jffs_node_ref *ref);
#endif /* 0 */
#endif /* __LINUX_JFFS_FM_H__ */

View File

@ -1,261 +0,0 @@
/*
* JFFS -- Journaling Flash File System, Linux implementation.
*
* Copyright (C) 2000 Axis Communications AB.
*
* Created by Simon Kagstrom <simonk@axis.com>.
*
* $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $
*
* 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.
*
* Overview:
* This file defines JFFS partition entries in the proc file system.
*
* TODO:
* Create some more proc files for different kinds of info, i.e. statistics
* about written and read bytes, number of calls to different routines,
* reports about failures.
*/
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/jffs.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/time.h>
#include <linux/types.h>
#include "jffs_fm.h"
#include "jffs_proc.h"
/*
* Structure for a JFFS partition in the system
*/
struct jffs_partition_dir {
struct jffs_control *c;
struct proc_dir_entry *part_root;
struct proc_dir_entry *part_info;
struct proc_dir_entry *part_layout;
struct jffs_partition_dir *next;
};
/*
* Structure for top-level entry in '/proc/fs' directory
*/
struct proc_dir_entry *jffs_proc_root;
/*
* Linked list of 'jffs_partition_dirs' to help us track
* the mounted JFFS partitions in the system
*/
static struct jffs_partition_dir *jffs_part_dirs;
/*
* Read functions for entries
*/
static int jffs_proc_info_read(char *page, char **start, off_t off,
int count, int *eof, void *data);
static int jffs_proc_layout_read (char *page, char **start, off_t off,
int count, int *eof, void *data);
/*
* Register a JFFS partition directory (called upon mount)
*/
int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c)
{
struct jffs_partition_dir *part_dir;
struct proc_dir_entry *part_info = NULL;
struct proc_dir_entry *part_layout = NULL;
struct proc_dir_entry *part_root = NULL;
char name[10];
sprintf(name, "%d", mtd);
/* Allocate structure for local JFFS partition table */
part_dir = (struct jffs_partition_dir *)
kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL);
if (!part_dir)
goto out;
/* Create entry for this partition */
part_root = proc_mkdir(name, jffs_proc_root);
if (!part_root)
goto out1;
/* Create entry for 'info' file */
part_info = create_proc_entry ("info", 0, part_root);
if (!part_info)
goto out2;
part_info->read_proc = jffs_proc_info_read;
part_info->data = (void *) c;
/* Create entry for 'layout' file */
part_layout = create_proc_entry ("layout", 0, part_root);
if (!part_layout)
goto out3;
part_layout->read_proc = jffs_proc_layout_read;
part_layout->data = (void *) c;
/* Fill in structure for table and insert in the list */
part_dir->c = c;
part_dir->part_root = part_root;
part_dir->part_info = part_info;
part_dir->part_layout = part_layout;
part_dir->next = jffs_part_dirs;
jffs_part_dirs = part_dir;
/* Return happy */
return 0;
out3:
remove_proc_entry("info", part_root);
out2:
remove_proc_entry(name, jffs_proc_root);
out1:
kfree(part_dir);
out:
return -ENOMEM;
}
/*
* Unregister a JFFS partition directory (called at umount)
*/
int jffs_unregister_jffs_proc_dir(struct jffs_control *c)
{
struct jffs_partition_dir *part_dir = jffs_part_dirs;
struct jffs_partition_dir *prev_part_dir = NULL;
while (part_dir) {
if (part_dir->c == c) {
/* Remove entries for partition */
remove_proc_entry (part_dir->part_info->name,
part_dir->part_root);
remove_proc_entry (part_dir->part_layout->name,
part_dir->part_root);
remove_proc_entry (part_dir->part_root->name,
jffs_proc_root);
/* Remove entry from list */
if (prev_part_dir)
prev_part_dir->next = part_dir->next;
else
jffs_part_dirs = part_dir->next;
/*
* Check to see if this is the last one
* and remove the entry from '/proc/fs'
* if it is.
*/
if (jffs_part_dirs == part_dir->next)
remove_proc_entry ("jffs", proc_root_fs);
/* Free memory for entry */
kfree(part_dir);
/* Return happy */
return 0;
}
/* Move to next entry */
prev_part_dir = part_dir;
part_dir = part_dir->next;
}
/* Return unhappy */
return -1;
}
/*
* Read a JFFS partition's `info' file
*/
static int jffs_proc_info_read (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct jffs_control *c = (struct jffs_control *) data;
int len = 0;
/* Get information on the parition */
len += sprintf (page,
"partition size: %08lX (%u)\n"
"sector size: %08lX (%u)\n"
"used size: %08lX (%u)\n"
"dirty size: %08lX (%u)\n"
"free size: %08lX (%u)\n\n",
(unsigned long) c->fmc->flash_size, c->fmc->flash_size,
(unsigned long) c->fmc->sector_size, c->fmc->sector_size,
(unsigned long) c->fmc->used_size, c->fmc->used_size,
(unsigned long) c->fmc->dirty_size, c->fmc->dirty_size,
(unsigned long) (c->fmc->flash_size -
(c->fmc->used_size + c->fmc->dirty_size)),
c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size));
/* We're done */
*eof = 1;
/* Return length */
return len;
}
/*
* Read a JFFS partition's `layout' file
*/
static int jffs_proc_layout_read (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct jffs_control *c = (struct jffs_control *) data;
struct jffs_fm *fm = NULL;
struct jffs_fm *last_fm = NULL;
int len = 0;
/* Get the first item in the list */
fm = c->fmc->head;
/* Print free space */
if (fm && fm->offset) {
len += sprintf (page, "00000000 %08lX free\n",
(unsigned long) fm->offset);
}
/* Loop through all of the flash control structures */
while (fm && (len < (off + count))) {
if (fm->nodes) {
len += sprintf (page + len,
"%08lX %08lX ino=%08lX, ver=%08lX\n",
(unsigned long) fm->offset,
(unsigned long) fm->size,
(unsigned long) fm->nodes->node->ino,
(unsigned long) fm->nodes->node->version);
}
else {
len += sprintf (page + len,
"%08lX %08lX dirty\n",
(unsigned long) fm->offset,
(unsigned long) fm->size);
}
last_fm = fm;
fm = fm->next;
}
/* Print free space */
if ((len < (off + count)) && last_fm
&& (last_fm->offset < c->fmc->flash_size)) {
len += sprintf (page + len,
"%08lX %08lX free\n",
(unsigned long) last_fm->offset +
last_fm->size,
(unsigned long) (c->fmc->flash_size -
(last_fm->offset + last_fm->size)));
}
/* We're done */
*eof = 1;
/* Return length */
return len;
}

View File

@ -1,28 +0,0 @@
/*
* JFFS -- Journaling Flash File System, Linux implementation.
*
* Copyright (C) 2000 Axis Communications AB.
*
* Created by Simon Kagstrom <simonk@axis.com>.
*
* 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: jffs_proc.h,v 1.2 2000/11/15 22:04:12 sjhill Exp $
*/
/* jffs_proc.h defines a structure for inclusion in the proc-file system. */
#ifndef __LINUX_JFFS_PROC_H__
#define __LINUX_JFFS_PROC_H__
#include <linux/proc_fs.h>
/* The proc_dir_entry for jffs (defined in jffs_proc.c). */
extern struct proc_dir_entry *jffs_proc_root;
int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c);
int jffs_unregister_jffs_proc_dir(struct jffs_control *c);
#endif /* __LINUX_JFFS_PROC_H__ */

View File

@ -1,224 +0,0 @@
/*
* JFFS -- Journalling Flash File System, Linux implementation.
*
* Copyright (C) 1999, 2000 Axis Communications AB.
*
* Created by Finn Hakansson <finn@axis.com>.
*
* 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: jffs.h,v 1.20 2001/09/18 21:33:37 dwmw2 Exp $
*
* Ported to Linux 2.3.x and MTD:
* Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
*
*/
#ifndef __LINUX_JFFS_H__
#define __LINUX_JFFS_H__
#include <linux/types.h>
#include <linux/completion.h>
#define JFFS_VERSION_STRING "1.0"
/* This is a magic number that is used as an identification number for
this file system. It is written to the super_block structure. */
#define JFFS_MAGIC_SB_BITMASK 0x07c0 /* 1984 */
/* This is a magic number that every on-flash raw inode begins with. */
#define JFFS_MAGIC_BITMASK 0x34383931 /* "1984" */
/* These two bitmasks are the valid ones for the flash memories we have
for the moment. */
#define JFFS_EMPTY_BITMASK 0xffffffff
#define JFFS_DIRTY_BITMASK 0x00000000
/* This is the inode number of the root node. */
#define JFFS_MIN_INO 1
/* How many slots in the file hash table should we have? */
#define JFFS_HASH_SIZE 40
/* Don't use more than 254 bytes as the maximum allowed length of a file's
name due to errors that could occur during the scanning of the flash
memory. In fact, a name length of 255 or 0xff, could be the result of
an uncompleted write. For instance, if a raw inode is written to the
flash memory and there is a power lossage just before the length of
the name is written, the length 255 would be interpreted as an illegal
value. */
#define JFFS_MAX_NAME_LEN 254
/* Commands for ioctl(). */
#define JFFS_IOCTL_MAGIC 't'
#define JFFS_PRINT_HASH _IO(JFFS_IOCTL_MAGIC, 90)
#define JFFS_PRINT_TREE _IO(JFFS_IOCTL_MAGIC, 91)
#define JFFS_GET_STATUS _IO(JFFS_IOCTL_MAGIC, 92)
/* XXX: This is something that we should try to get rid of in the future. */
#define JFFS_MODIFY_INODE 0x01
#define JFFS_MODIFY_NAME 0x02
#define JFFS_MODIFY_DATA 0x04
#define JFFS_MODIFY_EXIST 0x08
struct jffs_control;
/* The JFFS raw inode structure: Used for storage on physical media. */
/* Perhaps the uid, gid, atime, mtime and ctime members should have
more space due to future changes in the Linux kernel. Anyhow, since
a user of this filesystem probably have to fix a large number of
other things, we have decided to not be forward compatible. */
struct jffs_raw_inode
{
__u32 magic; /* A constant magic number. */
__u32 ino; /* Inode number. */
__u32 pino; /* Parent's inode number. */
__u32 version; /* Version number. */
__u32 mode; /* The file's type or mode. */
__u16 uid; /* The file's owner. */
__u16 gid; /* The file's group. */
__u32 atime; /* Last access time. */
__u32 mtime; /* Last modification time. */
__u32 ctime; /* Creation time. */
__u32 offset; /* Where to begin to write. */
__u32 dsize; /* Size of the node's data. */
__u32 rsize; /* How much are going to be replaced? */
__u8 nsize; /* Name length. */
__u8 nlink; /* Number of links. */
__u8 spare : 6; /* For future use. */
__u8 rename : 1; /* Rename to a name of an already existing file? */
__u8 deleted : 1; /* Has this file been deleted? */
__u8 accurate; /* The inode is obsolete if accurate == 0. */
__u32 dchksum; /* Checksum for the data. */
__u16 nchksum; /* Checksum for the name. */
__u16 chksum; /* Checksum for the raw inode. */
};
/* Define the offset of the accurate byte in struct jffs_raw_inode. */
#define JFFS_RAW_INODE_ACCURATE_OFFSET (sizeof(struct jffs_raw_inode) \
- 2 * sizeof(__u32) - sizeof(__u8))
/* Define the offset of the chksum member in struct jffs_raw_inode. */
#define JFFS_RAW_INODE_CHKSUM_OFFSET (sizeof(struct jffs_raw_inode) \
- sizeof(__u16))
/* Define the offset of the dchksum member in struct jffs_raw_inode. */
#define JFFS_RAW_INODE_DCHKSUM_OFFSET (sizeof(struct jffs_raw_inode) \
- sizeof(__u16) - sizeof(__u16) \
- sizeof(__u32))
/* The RAM representation of the node. The names of pointers to
jffs_nodes are very often just called `n' in the source code. */
struct jffs_node
{
__u32 ino; /* Inode number. */
__u32 version; /* Version number. */
__u32 data_offset; /* Logic location of the data to insert. */
__u32 data_size; /* The amount of data this node inserts. */
__u32 removed_size; /* The amount of data that this node removes. */
__u32 fm_offset; /* Physical location of the data in the actual
flash memory data chunk. */
__u8 name_size; /* Size of the name. */
struct jffs_fm *fm; /* Physical memory information. */
struct jffs_node *version_prev;
struct jffs_node *version_next;
struct jffs_node *range_prev;
struct jffs_node *range_next;
};
/* The RAM representation of a file (plain files, directories,
links, etc.). Pointers to jffs_files are normally named `f'
in the JFFS source code. */
struct jffs_file
{
__u32 ino; /* Inode number. */
__u32 pino; /* Parent's inode number. */
__u32 mode; /* file_type, mode */
__u16 uid; /* owner */
__u16 gid; /* group */
__u32 atime; /* Last access time. */
__u32 mtime; /* Last modification time. */
__u32 ctime; /* Creation time. */
__u8 nsize; /* Name length. */
__u8 nlink; /* Number of links. */
__u8 deleted; /* Has this file been deleted? */
char *name; /* The name of this file; NULL-terminated. */
__u32 size; /* The total size of the file's data. */
__u32 highest_version; /* The highest version number of this file. */
struct jffs_control *c;
struct jffs_file *parent; /* Reference to the parent directory. */
struct jffs_file *children; /* Always NULL for plain files. */
struct jffs_file *sibling_prev; /* Siblings in the same directory. */
struct jffs_file *sibling_next;
struct list_head hash; /* hash list. */
struct jffs_node *range_head; /* The final data. */
struct jffs_node *range_tail; /* The first data. */
struct jffs_node *version_head; /* The youngest node. */
struct jffs_node *version_tail; /* The oldest node. */
};
/* This is just a definition of a simple list used for keeping track of
files deleted due to a rename. This list is only used during the
mounting of the file system and only if there have been rename operations
earlier. */
struct jffs_delete_list
{
__u32 ino;
struct jffs_delete_list *next;
};
/* A struct for the overall file system control. Pointers to
jffs_control structs are named `c' in the source code. */
struct jffs_control
{
struct super_block *sb; /* Reference to the VFS super block. */
struct jffs_file *root; /* The root directory file. */
struct list_head *hash; /* Hash table for finding files by ino. */
struct jffs_fmcontrol *fmc; /* Flash memory control structure. */
__u32 hash_len; /* The size of the hash table. */
__u32 next_ino; /* Next inode number to use for new files. */
__u16 building_fs; /* Is the file system being built right now? */
struct jffs_delete_list *delete_list; /* Track deleted files. */
pid_t thread_pid; /* GC thread's PID */
struct task_struct *gc_task; /* GC task struct */
struct completion gc_thread_comp; /* GC thread exit mutex */
__u32 gc_minfree_threshold; /* GC trigger thresholds */
__u32 gc_maxdirty_threshold;
};
/* Used to inform about flash status. */
struct jffs_flash_status
{
__u32 size;
__u32 used;
__u32 dirty;
__u32 begin;
__u32 end;
};
/* This stuff could be used for finding memory leaks. */
#define JFFS_MEMORY_DEBUG 0
extern long no_jffs_node;
#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
extern long no_jffs_control;
extern long no_jffs_raw_inode;
extern long no_jffs_node_ref;
extern long no_jffs_fm;
extern long no_jffs_fmcontrol;
extern long no_hash;
extern long no_name;
#define DJM(x) x
#else
#define DJM(x)
#endif
#endif /* __LINUX_JFFS_H__ */